commit 1e0bc91f3e6f1089e6fa38b438a86b7c38b4b5ab
parent f617d98f6d820de190abcc74d1a07d1ceb0ee19f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 13 Jun 2026 12:41:26 -0700
perf(cg): aa64 -O0 2-insn epilogue for top-record frames (Lever 2)
The fat single-pass epilogue used a 3-insn x16 dance:
add x16,x29,#0 ; ldp x29,x30,[x16] ; add sp,x16,#16
Replace it, when CFA == 16 (top-record, no Windows GP home area), with the
2-insn tcc-style form:
mov sp,x29 ; ldp x29,x30,[sp],#16
No scratch register; correct under alloca (mov sp,x29 resets sp from the fp
anchor before the post-index pops the saved pair). The Windows-variadic
home-area case (CFA > 16) keeps the fat path.
sqlite3.c -O0 .text: -2,633 insns (1.3291x -> 1.3215x tcc).
Gate: determinism + sqlite e2e O0/O1 (golden+vs-clang) + toy/parse/smoke/
dwarf/debug all green; alloca + far-slot clang-differential probes pass.
Diffstat:
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/arch/aa64/native.c b/src/arch/aa64/native.c
@@ -1418,11 +1418,23 @@ static void aa_words_restore_frame(AANativeTarget* a, u32* words, u32 cap,
words[(*n)++] = aa64_add_imm(1, AA_SP, AA_SP, imm12, sh);
return;
}
+ if (aa_cfa_off(a) == AA_FRAME_SAVE_SIZE) {
+ /* Common top-record case (CFA == 16: no Windows-variadic GP home area). The
+ * saved pair sits at [fp] and the caller's sp is fp+16, so `mov sp,x29`
+ * followed by a post-indexed `ldp x29,x30,[sp],#16` restores the pair and sp
+ * in two insns with no scratch — vs the fat path's three (`mov x16,fp; ldp
+ * [x16]; add sp,x16,#16`). Correct under alloca: `mov sp,x29` resets sp from
+ * the fp anchor before the post-index pops the pair. */
+ if (*n + 2u > cap) aa_panic(a, "instruction patch too small");
+ words[(*n)++] = aa64_add_imm(1, AA_SP, AA_FP, 0, 0);
+ words[(*n)++] = aa64_ldp64_post(AA_FP, AA_LR, AA_SP, 2);
+ return;
+ }
if (*n + 3u > cap) aa_panic(a, "instruction patch too small");
/* AAPCS64: fp is the saved-pair address. Reload pair from [fp], then restore
* sp to fp + CFA-offset (= caller's original sp = CFA). The CFA offset is
* AA_FRAME_SAVE_SIZE normally, plus the Windows-variadic GP home area when
- * present. */
+ * present (the only case that still reaches here). */
words[(*n)++] = aa64_add_imm(1, AA_TMP0, AA_FP, 0, 0);
words[(*n)++] = aa64_ldp64_soff(AA_FP, AA_LR, AA_TMP0, 0);
words[(*n)++] = aa64_add_imm(1, AA_SP, AA_TMP0, (u32)aa_cfa_off(a), 0);