Week 3 test guide

A test failed and you don't know why? Find it here: what it checks, and the plausible bugs that are known to fail it. Then read the matching part of the week 3 spec.

How to use this

Run python tools/test.py --compiler PATH --week 3 -v, copy the failing test's name, and search below. "Bugs known to fail it" lists mistakes that were planted in the reference compiler and caught by this test, so one of them is a good first guess. It's not a complete list, and the debugging guide covers what to do when none fit.

testkindwhat it checksbugs known to fail it
render/r_bounds_from_rangesrenderrender version of run/bounds_from_rangesend doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
values hoisted to outer loops
render/r_computed_boundrenderrender version of run/computed_boundend doesn't close its range
final version not followed
stores under ends unsequenced
render/r_conv1d_i32_pad2renderpadding 2 on i32C cmplt as <=
C where swapped
end doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
stores under ends unsequenced
values hoisted to outer loops
render/r_conv1d_paddedrendera padded conv1d with masked tapsC cmplt as <=
C where swapped
end doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_conv1d_validrendera valid conv1dend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
stores under ends unsequenced
values hoisted to outer loops
render/r_conv2d_i32renderan i32 conv2dend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_conv2d_validrendera valid conv2dend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_dynamic_triprendera trip count loaded from memory: the index is masked with mod so the view is provableend doesn't close its range
final version not followed
render loop uses <=
stores under ends unsequenced
render/r_gemm_1x5x1rendera dot productend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
stores under ends unsequenced
values hoisted to outer loops
render/r_gemm_2x3x2renderlooped matmul in Cend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
stores under ends unsequenced
values hoisted to outer loops
render/r_gemm_3x1x4renderan outer product (K = 1)end doesn't close its range
final version not followed
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_gemm_4x3x5rendera non-square matmulend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_gemm_f32_roundingrenderf32 accumulation order is exact: products of thirdsend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_gemm_i32_wraprenderi32 matmul wraps through uint32_t inside loopsC plain signed add
end doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_in_loop_after_chainrenderrender version of run/in_loop_after_chainend doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
render/r_loop_carried_loadrenderrender version of run/loop_carried_loadend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
render/r_loop_invariant_valuerenderrender version of run/loop_invariant_valueend doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
render/r_mixed_dtypes_looprenderone loop writes f32, i32 and bool buffersend doesn't close its range
final version not followed
render loop uses <=
stores under ends unsequenced
render/r_multi_effect_endrenderrender version of run/multi_effect_endend doesn't close its range
final version not followed
render loop uses <=
stores under ends unsequenced
render/r_negative_triprenderrender version of run/negative_tripstores under ends unsequenced
render/r_negzero_datarenderdata=[-0.0 0.0] round-trips through a loop: recip of each lands in the output as -inf, infend doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
render/r_old_version_after_looprenderrender version of run/old_version_after_loopend doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
render/r_prefix_f32renderan f32 running totalC alloc not zeroed
end doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
stores under ends unsequenced
render/r_prefix_sumrendera running totalC alloc not zeroed
C plain signed add
end doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
stores under ends unsequenced
render/r_reduce_max_nanrendera max accumulator meets nanC max ignores nan
end doesn't close its range
final version not followed
loads never move into loops
stores under ends unsequenced
render/r_reduce_max_negzerorendermax over -0.0 valuesend doesn't close its range
final version not followed
render loop uses <=
stores under ends unsequenced
render/r_reduce_product_wraprenderan i32 product accumulator wrapsC plain signed add
loads never move into loops
render loop starts at 1
stores under ends unsequenced
render/r_reduce_sum_orderrender1e8 + 1 + -1e8 + 1 sums to 1.0 in f32end doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
render/r_rowsumrenderrow sumsend doesn't close its range
final version not followed
loads never move into loops
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_skip_middle_rangerenderrender version of run/skip_middle_rangeend doesn't close its range
final version not followed
nesting demands every range
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_split_use_across_assertsrenderrender must place the load where the whole program says, even though render ignores the assert that pins itend doesn't close its range
final version not followed
loads follow their deepest use
placement sees only the roots
stores under ends unsequenced
render/r_split_use_loadrenderrender version of run/split_use_loadend doesn't close its range
final version not followed
stores under ends unsequenced
render/r_three_deeprenderthree nested loops writing a 2x3x2 index cubeend doesn't close its range
final version not followed
render loop starts at 1
stores under ends unsequenced
values hoisted to outer loops
render/r_transpose_3x4rendertransposeend doesn't close its range
final version not followed
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_transpose_f32renderf32 transpose keeps -0.0 and nanend doesn't close its range
final version not followed
render loop starts at 1
render loop uses <=
stores under ends unsequenced
values hoisted to outer loops
render/r_wrap_in_looprenderadding 2^30 four times wraps through INT_MIN back to 0end doesn't close its range
final version not followed
stores under ends unsequenced
render/r_zero_triprenderrender version of run/zero_triprender loop uses <=
stores under ends unsequenced
run/bounds_from_rangesrun: passi*4 + k with i < 3 and k < 4 is provably inside 12 elementsend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/computed_boundrun: passa range bound can be any i32 with no open rangesend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
run/conv1d_i32_padded2run: passpadding of 2 on i32cmplt is <=
end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
where branches swapped
run/conv1d_paddedrun: passa padded convolution masks out-of-range taps with where, after clamping the index into a provable rangecmplt is <=
end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
where branches swapped
run/conv1d_validrun: passa valid 1-d convolution: output o sums x[o+k]*w[k]end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/conv2d_validrun: passa valid 2-d convolution: four nested loopsend doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/err_after_loop_stale_versionrun: invalidafter names %o, but the loop stores into %o0, the version after the reset: the versions would forkafter-on-loop accepts a stale version
run/err_after_wrong_memory_looprun: invalidafter names memory the loop never stores intoafter-on-loop skips memory check
run/err_assert_closed_rangerun: invalidan assert can't read a range even when the range's loop is closed elsewhereasserts may read open ranges
run/err_assert_open_rangerun: invalidan assert can't depend on an open rangenone recorded
run/err_call_open_rangerun: invalida call can't take an argument that depends on an open rangecalls may take open-range args
run/err_end_last_not_rangerun: invalidthe last operand of end must be a rangenone recorded
run/err_end_unused_rangerun: invalidend closes a range its effect doesn't usenone recorded
run/err_end_unused_range_closedrun: invalidend over j repeats a store that doesn't use j. Otherwise j is well formed, so only the 'end must use its range' rule rejects itend need not use its range
run/err_end_value_not_effectrun: invalidend repeats effects, not valuesend accepts values
run/err_loop_never_closedrun: invalida store inside a loop that no end closesunclosed loops allowed
run/err_loop_store_unsequencedrun: invalidthe end runs the store, but no after sequences the loopunsequenced store ok
run/err_memory_in_call_body_looprun: invalida call body can't read memory, even when called from a loopmemory in call body ok
run/err_range_bound_dependsrun: invalida range's bound can't depend on another range (no triangular loops in week 3)bounds may depend on ranges
run/err_range_f32_boundrun: invalida range bound is an i32none recorded
run/err_range_overrunrun: invalidrange 4 indexes a 3-element buffer: offset in [0, 3] can't be proven insidebounds off by one
bounds unchecked
range interval is [0, 0]
range interval one too tight
run/err_range_two_endsrun: invalida range is closed by exactly one enda range may close twice
run/err_range_value_escapesrun: invalida value that depends on a range can't leak into an assert outside the loopasserts may read open ranges
run/err_two_stores_one_version_looprun: invalidtwo stores into the same version inside one loop body are unorderedtwo stores per version
run/err_wrong_striderun: invalidi*3 + k with k < 4 overruns a 6-element buffer at i=1, k=3bounds off by one
bounds unchecked
range interval is [0, 0]
range interval one too tight
run/gemm_1xKrun: passa 1xK @ Kx1 matmul is a dot productend doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/gemm_2x3x2run: passmatmul by hand: three loops, an accumulator reset once per output elementend doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/gemm_Kx1_outerrun: passKx1 @ 1xN with K=1 inner loop is an outer productend doesn't close its range
evaluates everything
load ignores the offset
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/gemm_i32_wraprun: passi32 matmul wraps inside the loopend doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/gemm_nonsquarerun: pass3x4 @ 4x2end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/in_loop_after_chainrun: passtwo stores into one element in one iteration: the second reads the first through an after inside the loopend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
run/loop_assert_failrun: assert_failthe loop writes squares, but the assert expects the wrong last valueend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
run/loop_carried_loadrun: passa load whose only use is inside a loop that stores into its version is reloaded every iteration: 10, 11, 12, 13end doesn't close its range
evaluates everything
loads never move into loops
loop runs one extra time
stores under ends unsequenced
run/loop_invariant_valuerun: passa value with no range dependence is the same in every iterationend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
run/loop_runtime_errorrun: invalida division by zero inside a loop an assert depends on is a runtime errordiv by zero returns 0
run/multi_effect_endrun: passone end can repeat several stores into different buffersend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
run/negative_triprun: passa negative bound also runs zero timesend doesn't close its range
evaluates everything
stores under ends unsequenced
zero-trip loops run once
run/negzero_a_plusrun: passa buffer of +0.0 (parsed before negzero_b_minus, with the same names)evaluates everything
run/negzero_b_minusrun: passdata=[-0.0] must survive even if an identical buffer of +0.0 was built earlier: recip tells them apartevaluates everything
recip 0 ignores sign
run/old_version_after_looprun: passa load of the pre-loop version, used after the loop, still sees the old contentsend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
run/pinned_load_outsiderun: passthe load's first use (x + 1) doesn't depend on the range, so both run once before the loop: every iteration writes 11end doesn't close its range
evaluates everything
stores under ends unsequenced
run/prefix_sumrun: passa running total: two stores per iteration into two different memories, one endalloc not zeroed
end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs backwards
loop runs one extra time
stores under ends unsequenced
run/prefix_sum_wraprun: passa running total that wrapsadd doesn't wrap
alloc not zeroed
end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs backwards
loop runs one extra time
stores under ends unsequenced
run/reduce_max_nanrun: passa max accumulator that meets nan stays nanNaN != NaN in assert
end doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
max ignores NaN
stores under ends unsequenced
run/reduce_max_plainrun: passa max accumulatorend doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
run/reduce_product_wraprun: passa product accumulator wraps in i32end doesn't close its range
evaluates everything
loads never move into loops
loop runs one extra time
mul doesn't wrap
stores under ends unsequenced
run/reduce_sum_f32_orderrun: passthe sum runs in increasing k: 1e8 + 1 + -1e8 + 1 is 1.0 in f32, not 2.0end doesn't close its range
evaluates everything
f32 ops not rounded
load ignores the offset
loop runs backwards
loop runs one extra time
stores under ends unsequenced
run/rowsum_3x4run: passrow sums: one accumulator per row, reset by a store that depends on the rowend doesn't close its range
evaluates everything
load ignores the offset
loads never move into loops
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/skip_middle_rangerun: passan inner loop inside two loops can ignore the middle range, and it just rerunsend doesn't close its range
evaluates everything
loop runs one extra time
nesting demands every range
stores under ends unsequenced
values hoisted to outer loops
run/split_use_across_assertsrun: passwhere a load runs depends on every use in the program: the second assert uses %x outside the loop, so the loop sees the pre-loop 10 every time, even while checking the first assert aloneend doesn't close its range
evaluates everything
loads follow their deepest use
placement sees only the roots
stores under ends unsequenced
run/split_use_loadrun: passa load with uses inside and outside the loop runs once, before it: every iteration writes 10 + 1end doesn't close its range
evaluates everything
stores under ends unsequenced
run/transpose_2x3run: passtranspose: read row-major, write column-majorend doesn't close its range
evaluates everything
load ignores the offset
loop runs one extra time
stores under ends unsequenced
values hoisted to outer loops
run/zero_triprun: passrange 0 runs zero times: the buffer keeps its dataend doesn't close its range
evaluates everything
loop runs one extra time
stores under ends unsequenced
zero-trip loops run once