Week 2 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 2 spec.

How to use this

Run python tools/test.py --compiler PATH --week 2 -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/alloc_read_before_writerenderreading an alloc before any store sees zerosC alloc not zeroed
C rank-1 store one elem
final version not followed
render/alloc_scratchrendera local alloc holds an intermediate, and it starts as zerosfinal version not followed
render/alloc_two_distinctrendertwo same-size allocs are separate arraysC alloc not zeroed
C rank-1 store one elem
allocs share storage
final version not followed
render/asserts_ignoredrenderrender ignores asserts and statements the outputs don't neednone recorded
render/bool_opsrenderbool xor, where on bools, and bool to i32C where swapped
render/call_inlinedrendercalls render inline: the body runs on loaded argsC rank-1 store one elem
render/call_nested_closedrendera nested call's body keeps its own param 0 when inlinednone recorded
render/casts_to_i32_and_boolrenderf32 to i32 truncates, and anything to bool is != 0, nan includedC cast to i32 rounds
render/copy_scalarrenderthe smallest kernel: one load, one storenone recorded
render/dynamic_offset_boolrendera bool-derived offset picks one of two elementsnone recorded
render/dynamic_offset_storerenderstore at a masked loaded offsetnone recorded
render/f32_chainrendera longer f32 chain where every intermediate roundsnone recorded
render/f32_exact_literalsrenderf32 constants need every digit: 1/3 and the largest finite f32 must come out exactC float literals 6 digits
render/f32_from_i32_castrenderi32 to f32 rounds to nearest even, and bool to f32 is 0 or 1C cast to i32 rounds
render/f32_maxrendermax with nan on either side and both signed-zero ordersC max ignores -0.0
C max ignores nan
render/f32_reciprenderrecip of zeros, infinities and a value that roundsnone recorded
render/f32_roundingrenderevery f32 op rounds; -ffp-contract=off keeps a*b+c from fusingnone recorded
render/f32_signed_zerorender-0.0 survives where it should and doesn't where it shouldn'tnone recorded
render/f32_specialsrendernan and inf arithmeticnone recorded
render/f32_where_cmpltrendercmplt with nan is false, and where picks a branchC cmplt as <=
C where swapped
render/i32_add_wraprenderi32 add wraps, and in C that has to go through uint32_tC plain signed add
render/i32_div_mod_intminrenderINT_MIN / -1 and INT_MIN % -1 are UB in C; the kernel must not trapC div without -1 guard
C mod without -1 guard
render/i32_div_mod_truncrenderC division truncates toward zero, and mod takes the dividend's signnone recorded
render/i32_max_cmp_xorrendermax, xor and a cmplt-driven where on i32 edgesC where swapped
render/i32_mul_wraprenderi32 mul wraps without UBC plain signed add
render/i32_shl_wraprendershl into the sign bit and past itC plain signed add
render/load_whole_indexrenderload a whole buffer and index itnone recorded
render/mixed_dtypesrenderthree buffers of different dtypes in one kernelloads not before stores
render/nested_view_offsetsrendershrink of shrink: offsets add in the C tooC nested offsets lost
C rank-1 load no offset
render/old_version_late_userenderan old-version load whose value is used two stores laterloads not before stores
render/rank1_copyrenderload a [3] view and store it into another buffer's [3] viewC rank-1 load no offset
render/rmw_chainrenderthree increments of the same elementnone recorded
render/special_data_copyrenderspecial float data copies through bit for bitnone recorded
render/stack_index_dynamicrenderindex a stack with a loaded indexnone recorded
render/store_whole_bufferrenderstore a rank-1 value into a whole buffernone recorded
render/swap_schedulerenderswap: the second store uses a load of the original version, so loads must be scheduled firstloads not before stores
render/unwritten_bufferrendera buffer the kernel never writes keeps its datanone recorded
run/alloc_distinctrun: passtwo allocs of the same size are different memoryalloc not zeroed
run/alloc_scratchrun: passalloc is local scratch that starts as zerosalloc not zeroed
run/bounds_bool_offsetrun: passa bool cast to i32 is in [0, 1], so it can index a 2-element bufferload ignores the offset
run/bounds_const_arith_offsetrun: passconstant arithmetic offsets have exact boundsload ignores the offset
run/bounds_last_windowrun: passa [k] view that ends exactly at the end is in boundsload ignores the offset
run/bounds_masked_offsetrun: passa loaded index masked with max and mod is provably in [0, 3]none recorded
run/buf_boolrun: passbool buffers hold true/falsenone recorded
run/buf_chain3run: passthree stores in a row, each into the previous versionnone recorded
run/buf_data_loadrun: passdata= gives a buffer its initial contents, and a scalar view loads one elementnone recorded
run/buf_f32_roundingrun: passf32 data rounds like f32 literals, and stays f32 through memorynone recorded
run/buf_old_versionrun: passa load of the old version still sees the old value, even if written after the store in the filenone recorded
run/buf_rmwrun: passread, modify, write backnone recorded
run/buf_store_afterrun: passafter names the version with the store appliednone recorded
run/buf_versions_differrun: passevery version keeps its own contentsnone recorded
run/buf_zerosrun: passwithout data=, a buffer starts as zeros of its dtypenone recorded
run/copy_between_buffersrun: passload from one buffer, store into anotherrank-1 store writes one
run/err_after_not_storerun: invalidthe second operand of after must be a storenone recorded
run/err_after_on_viewrun: invalidafter takes a whole buffer version, not a viewnone recorded
run/err_after_stale_versionrun: invalidafter names an older version of the right buffer: still wrongafter version unchecked
run/err_after_wrong_versionrun: invalidafter must name the version the store writes intoafter version unchecked
run/err_alloc_slotrun: invalidalloc has no slot: it isn't an inputnone recorded
run/err_bounds_mask_too_widerun: invalidmasking to [0, 4] doesn't fit a scalar view in a 4-element bufferbounds off by one
bounds unchecked
run/err_bounds_mod_negativerun: invalidmod alone keeps the sign, so the offset could be negativebounds allow negative
bounds unchecked
run/err_bounds_negativerun: invalidnegative offsets are out of boundsbounds allow negative
bounds unchecked
run/err_bounds_nestedrun: invalida nested view must fit its parent view, not just the bufferbounds off by one
nested view vs storage
run/err_bounds_past_endrun: invalidelements 3 and 4 of a 4-element buffer: 4 is past the endbounds off by one
run/err_bounds_raw_loadedrun: invalida raw loaded index could be anything, so the view can't be proven in boundsnone recorded
run/err_bounds_scalar_at_nrun: invalidelement 4 of a 4-element buffer doesn't existnone recorded
run/err_bounds_unusedrun: invalidbounds are checked statically, even for a view nothing usesnone recorded
run/err_buffer_no_slotrun: invalidbuffer needs slot=none recorded
run/err_buffer_size_zerorun: invalida buffer has at least one elementnone recorded
run/err_data_dtyperun: invaliddata values must be literals of the buffer's dtypedata dtype unchecked
run/err_data_lengthrun: invaliddata= must give exactly n valuesdata length unchecked
run/err_duplicate_slotrun: invalidslots are uniqueduplicate slots ok
run/err_duplicate_slot_identicalrun: invalidtwo identical buffer statements are still two buffers sharing a slotduplicate slots ok
identical buffers merge
run/err_load_valuerun: invalidload reads memory, not a valuenone recorded
run/err_mem_alu_operandrun: invalidmemory isn't a value: load it firstnone recorded
run/err_mem_assertrun: invalidassert compares values, not memorymemory as ALU operand ok
run/err_mem_call_argrun: invalidmemory can't be passed to a callnone recorded
run/err_mem_in_call_bodyrun: invalidmemory can't be used inside a call bodymemory in call body ok
run/err_mem_stackrun: invalidmemory can't be stackedmemory as ALU operand ok
run/err_offset_f32run: invalidoffsets are i32none recorded
run/err_old_version_needed_laterun: invalidthe offset of a load from the old version depends on the new version: no order worksno ordering cycle check
run/err_shrink_no_shaperun: invalidshrink needs shape=none recorded
run/err_store_dtyperun: invalidthe stored value must have the view's dtypestore type unchecked
run/err_store_into_valuerun: invalidstore writes into memory, not into a valuenone recorded
run/err_store_shaperun: invalidthe stored value must have the view's shapestore type unchecked
run/err_two_stores_one_versionrun: invalidtwo stores into the same version are unorderedtwo stores per version
run/err_two_stores_unsequenced_secondrun: invalida second store into a version is invalid even if only one is sequencednone recorded
run/err_unsequenced_storerun: invalida store no after sequences has no effect, so it's an errorunsequenced store ok
run/err_view_alu_operandrun: invalida view isn't a value eithermemory as ALU operand ok
run/fail_memory_assertrun: assert_faila failing assert on a loaded valuenone recorded
run/load_after_values_in_callrun: passloaded values (not memory) can be call argsnone recorded
run/loaded_div_zerorun: invalida runtime error in a value an assert depends on: dividing by a loaded zeronone recorded
run/special_float_datarun: passdata can hold nan, inf, -inf and -0.0none recorded
run/swaprun: passswap two elements: both loads read the original versionnone recorded
run/unread_store_okrun: passa sequenced store that no assert reads is finenone recorded
run/view_rank1_loadrun: passshape=[k] views k elements starting at the offsetnone recorded
run/view_rank1_storerun: passstore a rank-1 value into a [k] viewrank-1 store writes one
run/view_shrink_of_shrinkrun: passoffsets add: shrink 1 then shrink 2 lands on element 3shrink offsets don't add
run/view_shrink_of_shrink_storerun: passa store through a nested view writes the right elementshrink offsets don't add
run/view_whole_load_indexrun: passload a whole buffer, then index the rank-1 valuenone recorded