Stop counting non-returning trap clobbers against live ranges - #2107
Merged
Conversation
The runtime ABI manifest already declared which helpers never return; MIR lowering dropped that on the floor, so every checked add or mul's trap call sat inside the value's live range and disqualified it from caller-saved allocation. Call instructions now carry the helper's return behavior: a never-returning call has no successors (empty live-out), and ClobberIndex skips its clobber events -- the clobber is real but unreachable by any later use, since control only continues on the no-trap path. Live ranges are textual intervals, so the successors change alone is not sufficient; both pieces verified byte-level. Trap argument uses stay ordinary uses at the call index. Also adds the always-on pre-allocation guard that lowering never names an allocatable register as a physical operand, reusing the schedulers' exhaustive operand enumerations.
steveklabnik
marked this pull request as ready for review
August 5, 2026 06:18
steveklabnik
enabled auto-merge
August 5, 2026 06:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rue lowers each checked
+/*asjno .L; call __rue_overflow; .L:, and that trap call sat inside almost every arithmetic value's live range — disqualifying it from #2101's caller-saved allocation. Checked-arithmetic-heavy code kept spilling for a call that, if it executes, never comes back.The non-returning fact comes from the ABI manifest, not inference.
rue-runtime-abialready declaresReturnBehavior::Neverper helper (all nine verified to end inplatform::exit); MIR lowering dropped it. Call instructions now carry it: a never-returning call has no successors (empty live-out), andClobberIndexskips its clobber events — the clobber is real but unreachable by any later use, since control continues only on the no-trap path. Trap-argument uses stay ordinary uses at the call index, so the trap ABI's own live-in needs are untouched.Both pieces are necessary, verified empirically: live ranges are textual
[first, last]intervals, so with only the successors change applied the demo assembly was byte-identical to baseline — the index change is what unlocks allocation, the successors change is the honest model behind it. The demo function now holds a value inr11acrosscall __rue_overflowand drops a callee-saved push from the prologue (AArch64 mirrors withx13/x14acrossbl).Also lands the RUE-1146 follow-up guard: an always-on pre-allocation assertion (codegen has no debug-assert allowance per docs/process/ci.md) that lowering never names an allocatable register as a physical operand, reusing both schedulers' exhaustive operand enumerations rather than adding a third.
Fixes RUE-1224.
Two observations being filed as follow-up: preferring REX-prefixed
R11overRbxcosts +0.05% code size on arithmetic-heavy x86-64 (a size-aware tiebreak whenRbxis already saved would recover it), and the textual-interval range builder means future liveness refinements will always need this two-part treatment.Validation
Premerge (78/78), codegen units 657 (+9 new incl. per-backend
#[should_panic]guard tests), cfg 239, quick (re-run green; one transientrue-testbuild-race in the first run passed 213/213 in isolation), trap/overflow CLI suites (mul_overflow/intcast/panic_assert/subword/division/divergence),abi/borrow/multi, differential-oracle targets, 600-seed oracle fuzz (600/600 agree), 300 generated programs × -O0/-O1/-O2/-O3 self-consistency sweep (0 divergences), reproducible-programs, clippy, fmt. Trap behavior unchanged (same message, same exit code).Generated by Claude Code