On Tue, 2026-10-20 at 09:19 -0700, Vineet Gupta wrote: > A spill narrower than its source stores the source's low 32 bits, so the > slot is their zero-extension -- the mov relation, in the store direction: > > r6 = ... /* full 64-bit unknown */ > *(u32 *)(r10 - 8) = r6; /* slot holds r6's low 32 bits */ > if w6 != 0 goto ... /* not taken: r6's low 32 bits are 0 */ > r2 = *(u32 *)(r10 - 8); > if r2 == 0 goto ... /* not deduced today */ > > A store never sign-extends, so BPF_REG_LINK_ZEXT is the only kind that > arises. save_register_state() copies the source whole, including bounds > for bits the store did not write, so the slot must be truncated before > the kind goes on it -- otherwise the first sync_linked_regs() intersects > the correctly rebuilt low half against those stale bounds and empties > the slot. > > Only one order pays. sync_linked_regs() walks spilled slots, so narrowing > while the value is still on the stack narrows the slot and the fill copies > an already narrowed value. Filling first does not benefit: the fill is a > mov, and a mov drops a zero-extending link. > > Posted, not proposed. This is the direction asked for, implemented and > measured, and the measurement says do not take it. Against the ten patches > before it, on 441 cilium/katran/fb/sched_ext objects, 1467 programs: > > verdicts no change at all > total_insns 102 changed, 63 worse, +84,450 (+0.34%) > +59,616 (+57.2%) 104,160 -> 163,776 test_file_open > +19,784 (+89.7%) 22,053 -> 41,837 rusty_enqueue > +2,688 (+40.6%) 6,626 -> 9,314 layered_enqueue > total_states 64 changed, 63 worse
I'd still prefer to keep things symmetric. Instruction budget should be less of a concert for 7.5, as far as I understand. ...
