3.1 KiB
§172b — THREE MORE TELLS FROM THE GCC READ (P30 S50-Max, banked on Drew's ask)
LANE ALIASES (grep bait — added P31 S59). The atlas lever labels a drafting card carries
(tools/atlas.py) do not appear anywhere else in this cookbook, so an agent that greps the label it
was handed finds NOTHING: measured over the tells waves, 108 failure transcripts grepped
extend-tell and 28 grepped swaprepeat against zero hits while the knowledge sat here under
different words. The map:
extend-tell → §172b-1 (+ the C recipes in §264) · swaprepeat-tell → §172a (macro-vs-inline
repeats) + §172b-2 · s16-div-tell → §172b-4. If you arrived by grepping a card label, this
is your section.
1. The sll/sra-16 pair tell (extendhisi2 is MEM-only). The single-insn sign-extending load
(extendhisi2_internal) exists ONLY for memory operands. A visible sll X,Y,16; sra X,X,16 pair
in the target is therefore a promotion of a REGISTER-held short — a multi-def s16 variable (a
branch-merged value like mw), never a fresh memory read. Conversely, if your draft emits the
pair where the target has a plain lh, your operand is living in a register (a temp/var) where
the original read memory — drop the temp. Extends to QImode (extendqisi2 same shape): a real
sll/sra 24 pair = register-held s8.
2. The swapped-arm select tell (cse comparison canonicalization is HALF-complete). b > a
canonicalizes to a < b at expand — the compare slt is SHARED — but the select around it is
not: (b > a) ? b : a and (a < b) ? a : b emit SEPARATE branch+move structures that cse never
merges (byte-measured: each swapped-arm recompute adds its own select code and its own spill
slots, vars up to +112 across a sweep). Forward tell: TARGET code with a re-evaluated select on
an already-computed compare = the source repeated the expression with SWAPPED arms (macro args in
the other order). Reverse tell: your draft emitting duplicate selects the target lacks = your
repeats disagree in arm order with the first mention — make every textual repeat of a ?:
operand-identical.
3. The ?: accumulator-order tell. Expand reuses the FIRST operand's register as a ?:
result accumulator, clobbering it — so in chained selects, exactly the first-operand values must
RE-LOAD when used again later, and second-operand values stay live in registers. From bytes:
which operands freshly re-load in a later pass tells you the operand ORDER of every inner ?: in
the original source, mechanically. (This is how func_8017CE58's max-chain reload pattern pins
its min-chain spelling end to end.)
4. Division-by-constant sign-correction reuse. In s16 / K via magic-multiply, the sign
correction can read the PRE-truncation intermediate (sra $r, (x<<16), 31 — shift counts folded
16+31→31) rather than the extended value. When hand-writing such a division and the sign sra
reads an "impossible" register, the compiler reused the promotion's <<16 intermediate — keep
the promotion as an expression (not a separate temp) so the intermediate exists to reuse.