Files
BFM-decomp/docs
Drew T 4adb559a29 docs(phase-31): cookbook §177 — the epilogue return-delay slot is decided by the SAVED-REGISTER SET
Eleven wave-Q functions in 800c/800c3 sat at closeness 1-3 with the same epilogue residual, and
every agent independently filed it as intrinsic ("epilogue-delay-slot-unfillable", "gcc/maspsx
structural wall"). It is neither intrinsic nor a scheduling problem.

Source-confirmed at gcc-2.7.2/config/mips/mips.c:5376 --

  int mips_epilogue_delay_slots () {
    if (current_frame_info.total_size == 0) return 1;                        /* no frame  */
    if (current_frame_info.mask == RA_MASK && current_frame_info.fmask == 0) return 1;  /* only $ra */
    return 0;
  }

gcc offers the epilogue a delay slot ONLY when the function allocates no stack, or saves nothing
but $ra. Otherwise the slot is never offered to the scheduler and the emitter puts the stack
restore there instead (mips.c:5276, the tsize > 0 path).

So the lever is the CALLEE-SAVED SET, steerable from C: the first value whose live range spans a
jal costs an $s register and flips the switch. To gain a filled slot, hold nothing across a call
(recompute or re-read after it); to lose one, hoist a load above the call. Register pins are the
WRONG tool here -- §176-C already established a pin cannot schedule across a call.

~600 instructions were three instructions from banked and about to be written off. The meta-lesson
(R17): when N independent agents call one residual "structural", read the compiler -- the answer
was forty lines of mips.c already sitting in tools/reference/gcc-2.7.2/.
2026-08-16 14:17:09 -06:00
..