Three expr::computed_store_rooting_tests cases fail intermittently when perry-runtime and perry-codegen are tested in one cargo invocation under RUST_TEST_THREADS=1:
expr::computed_store_rooting_tests::collecting_masked_window_index_declines_the_hoisted_pointer_tier
expr::computed_store_rooting_tests::collecting_rhs_between_masked_reads_declines_the_hoisted_pointer_tier
expr::computed_store_rooting_tests::collecting_rhs_declines_the_straight_line_masked_region
Measured rates
Command, identical in every run:
RUST_TEST_THREADS=1 cargo test --profile perry-dev -p perry-runtime -p perry-codegen --lib
| tree |
failures |
main @ c2da03439 |
0 / 12 |
| the #8657 stack (pre-merge) |
3 / 12 |
| each of #8647, #8652, #8650 alone |
0 / 4 each |
Machine load was 52-68 across both sets, so load alone does not separate them.
It is a combination trigger, not the tests themselves
-p perry-codegen --lib alone, with RUST_TEST_THREADS=1: passes on both trees.
-p perry-codegen --lib alone, unfiltered, no flag: passes, repeatedly.
- Filtering to
-- computed_store_rooting_tests always passes — the filter changes the experiment, so a filtered re-run is not a valid reproduction attempt.
Only "both crates in one invocation + RUST_TEST_THREADS=1" reproduces it.
Why this is worth a look beyond test hygiene
These assertions are about which optimization tier codegen selected — e.g. inert.contains("masked_region.ta_i32.preheader"), !collecting.contains(...). They compile a snippet and inspect the emitted IR; no runtime code executes. A runtime-only change cannot affect them semantically.
So a tier choice that flips depending on what else is running on the machine implies codegen is not fully deterministic under load. That is the part worth understanding: a compiler whose optimization tier depends on ambient load will produce different binaries on a busy CI runner than on a quiet one, and any A/B measurement across such a boundary is unreliable.
Two possibilities worth separating:
- a compile-time budget or timing-sensitive heuristic in the tier decision (would explain load sensitivity directly); or
- shared mutable state between the two test binaries — though they are separate processes, so this needs a concrete mechanism.
Note
Reported at merge time of #8657 rather than silently: main was 0/12 and the stack 3/12, so I could not honestly call it pre-existing, and each constituent PR was clean alone. If it turns out to be (1), it predates all of them.
Three
expr::computed_store_rooting_testscases fail intermittently whenperry-runtimeandperry-codegenare tested in one cargo invocation underRUST_TEST_THREADS=1:Measured rates
Command, identical in every run:
RUST_TEST_THREADS=1 cargo test --profile perry-dev -p perry-runtime -p perry-codegen --libmain@c2da03439Machine load was 52-68 across both sets, so load alone does not separate them.
It is a combination trigger, not the tests themselves
-p perry-codegen --libalone, withRUST_TEST_THREADS=1: passes on both trees.-p perry-codegen --libalone, unfiltered, no flag: passes, repeatedly.-- computed_store_rooting_testsalways passes — the filter changes the experiment, so a filtered re-run is not a valid reproduction attempt.Only "both crates in one invocation +
RUST_TEST_THREADS=1" reproduces it.Why this is worth a look beyond test hygiene
These assertions are about which optimization tier codegen selected — e.g.
inert.contains("masked_region.ta_i32.preheader"),!collecting.contains(...). They compile a snippet and inspect the emitted IR; no runtime code executes. A runtime-only change cannot affect them semantically.So a tier choice that flips depending on what else is running on the machine implies codegen is not fully deterministic under load. That is the part worth understanding: a compiler whose optimization tier depends on ambient load will produce different binaries on a busy CI runner than on a quiet one, and any A/B measurement across such a boundary is unreliable.
Two possibilities worth separating:
Note
Reported at merge time of #8657 rather than silently:
mainwas 0/12 and the stack 3/12, so I could not honestly call it pre-existing, and each constituent PR was clean alone. If it turns out to be (1), it predates all of them.