Skip to content

thumb2c tune: learn the HImode literal-pool respellings - #11

Open
wowwheaties wants to merge 2 commits into
PascalPixel:mainfrom
wowwheaties:wip/thumb2c-himode-pool
Open

thumb2c tune: learn the HImode literal-pool respellings#11
wowwheaties wants to merge 2 commits into
PascalPixel:mainfrom
wowwheaties:wip/thumb2c-himode-pool

Conversation

@wowwheaties

@wowwheaties wowwheaties commented Sep 5, 2026

Copy link
Copy Markdown

Summary

thumb2c tune learns the two HImode literal-pool respellings, so drafts whose only residue is an early literal pool can reach exact without hand editing. One site at a time, kept only on a strict differing_halfwords improvement, and only while the aligned report still shows the candidate's pool behind the reference's. Ordinary C89 source alternatives; no flags, no register or scheduling forcing; nothing outside tools/thumb2c/.

Mechanism (read from the compiler)

GCC 2.96 places a Thumb literal pool by the tightest pending fix, and each fix takes its range from the pattern alternative recog chose, not from the printed text (push_minipool_fix, arm.c:5367; entries sorted by max_address in add_minipool_forward_ref, arm.c:4829; the barrier chosen in create_fix_barrier, arm.c:5240). A symbol address spelled through SImode files a 1020-byte fix (*thumb_movsi_insn alt 6, arm.md:3838). Held in HImode it files a 64-byte one (*thumb_movhi_insn alt 1, arm.md:4318), which is where the ROM's pool sits in these functions. A plain u16 local does not help: PROMOTE_MODE (arm.h:618) widens it back to SImode.

  • Construct A, a symbol-valued local: s32 p8; p8 = (s32)Sym; (or the one-line s32 p8 = (s32)Sym;) → u16 p8[1]; p8[0] = (u16)(s32)Sym; with every read respelled p8[0]. Refused unless the local is declared once, assigned once from a symbol the unit declares extern, and read only into halfword-or-narrower stores.
  • Construct A′, a symbol value stored straight into a halfword-or-narrower target with no local (rec7[34] = (s32)Sym;): a one-element u16 temporary is declared beside the other locals and the store goes through it.
  • Construct B, a halfword store of a symbol-derived constant: *p = (u16)(s32)Data_00000e00;*p = 0xe00; (the lifter names such a word by the value the image holds; only values in 1..0xffff qualify).
  • Guard pool_is_late(report): an aligned row where both columns load a pool word and the candidate's is at the higher address.

Fixtures (overlay score <file> --owner <owner> --span <span>)

Owner span draft hand-tuned thumb2c tune from the draft
resource_3c9:0200423c 1692 114 0 0 (114 -> 0 himode p8[1])
resource_3a4:02001838 1236 531 21 20 (531 -> 111 himode p10[1], then two call respellings)
resource_371:020039fc 1296 513 66 98 (five himode *shown = 0x…; steps; the guard turns false after the fifth site, so it stops short of the hand file by design)
resource_3ba:02002aec 192 69 1 69 → 45 on the first step (himode data[1], the one-line initializer form); the rest of the hand file is a shared zero and store order
resource_3bb:02002d84 192 67 10 67 → 42 on the first step (himode store, the direct-store form); the residue is allocation-shaped

Sweep over the 20 remaining near-miss overlay drafts on 7d8a720 (thumb2c tune from each lane's best draft): resource_3af:02002618 312 → 43 in one himode store step, resource_3b9:02001298 346 → 218 and resource_3b7:02000e5c 838 → 729 through the existing call respellings; the other owners moved by 0–4.

The remaining residue on 3a4 and 371 is allocation and scheduling shaped and goes to the smart queue.

Gates

  • cargo test (thumb2c): 16 passed; five new unit tests beside respells_calls_both_ways.
  • make test, make lint (forbidden=0), make tooling-index-check (87 tools), make verify: green.
  • make tooling-size: 46,996 / 50,000.

Review notes

🤖 Generated with Claude Code

wowwheaties and others added 2 commits September 5, 2026 14:12
GCC 2.96 places a Thumb literal pool by the tightest pending fix, and each
fix takes its range from the pattern alternative recog chose rather than
from the printed text (push_minipool_fix, arm.c:5367; the entries stay
sorted by max_address in add_minipool_forward_ref, arm.c:4829). A symbol
address spelled through SImode files a 1020-byte fix (*thumb_movsi_insn
alt 6, arm.md:3838); held in HImode it files a 64-byte one
(*thumb_movhi_insn alt 1, arm.md:4318) and the pool lands where the
reference put it. tune now proposes both HImode spellings one site at a
time - a one-element u16 array for a symbol-valued local, and the bare
halfword constant for a store of a symbol-derived constant - guarded by
that early-pool signature in the alignment report and kept only on a
strict differing_halfwords improvement. Fixtures: resource_3c9:0200423c
114 -> 0, resource_3a4:02001838 531 -> 111, resource_371:020039fc
513 -> 98.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Two drafts where the HImode respelling is the fix drew no proposal at all:
a symbol-valued local written as `s32 data = (s32)Sym;` on one line, which
himode_local knew only in its split form, and a symbol value stored
straight into a narrow target with no local at all. himode_local now takes
the declaration-with-initializer, moving the value to the first statement
of the block the declaration opens; himode_store takes a direct
halfword-or-narrower store through a one-element u16 temporary declared
beside the other locals. Either way the fix files a 64-byte pool range
(*thumb_movhi_insn alt 1, arm.md:4318) instead of 1020 (*thumb_movsi_insn
alt 6, arm.md:3838), which is what push_minipool_fix records (arm.c:5367).
The early-pool guard needed no change: it fires on both reports, only the
rewrites were missing. Fixtures at span 192: resource_3ba:02002aec
69 -> 45, resource_3bb:02002d84 67 -> 42; resource_3c9:0200423c still
114 -> 0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant