aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-03-27 13:58:44 +0100
committerlemon <lsof@mailbox.org>2026-03-27 13:58:44 +0100
commitb8dea129488959adeadc2e444d769f2a2ac709d8 (patch)
tree98508423f9a952e6dea1001d7032b7be324abcd6
parent20dc93c4473a5d5a53462fff09a74b2839d10d6b (diff)
x86-64: redzone optimization for leaf functions
Don't use frame pointer or explicitly modify stack pointer for these
-rw-r--r--src/t_x86-64_emit.c17
-rw-r--r--test/11-abi.c4
2 files changed, 12 insertions, 9 deletions
diff --git a/src/t_x86-64_emit.c b/src/t_x86-64_emit.c
index 0da27d8..39dbf3f 100644
--- a/src/t_x86-64_emit.c
+++ b/src/t_x86-64_emit.c
@@ -374,10 +374,11 @@ encode(uchar **pcode, const EncDesc *tab, int ntab, enum irclass k, Oper dst, Op
bool sib = 0;
if (mem.base == RBP) {
if (!usebp) {
- /* if RBP isn't being set up (leaf functions with no stack allocations),
- * access thru RSP (function arguments in the stack) */
mem.base = RSP;
- mem.disp -= 8;
+ if (mem.disp > 0) {
+ /* function stack parameters */
+ mem.disp -= 8;
+ }
} else if (mem.disp <= 0) {
mem.disp += rbpoff;
}
@@ -1313,6 +1314,8 @@ nops(uchar **pcode, int align)
}
}
+enum { STACKREDZONE = 128 };
+
static void
emitbin(Function *fn)
{
@@ -1327,9 +1330,9 @@ emitbin(Function *fn)
/** prologue **/
- /* only use frame pointer in non-leaf functions and functions that use the stack */
+ /* only use frame pointer in non-leaf functions and functions with large stack frames */
usebp = 0;
- if (!fn->isleaf || fn->stksiz) {
+ if (!fn->isleaf || fn->stksiz >= STACKREDZONE) {
usebp = 1;
/* push rbp; mov rbp, rsp */
DS("\x55\x48\x89\xE5");
@@ -1349,7 +1352,7 @@ emitbin(Function *fn)
}
}
- if (fn->stksiz != 0) {
+ if (usebp && fn->stksiz > 0) {
/* sub rsp, <stack size> */
if (fn->stksiz < 128)
DS("\x48\x83\xEC"), B(fn->stksiz);
@@ -1414,7 +1417,7 @@ emitbin(Function *fn)
if (blk->lnext != fn->entry && blk->lnext->jmp.t == Jret && blk->lnext->ins.n == 0)
continue; /* fallthru to next blk's RET */
/* epilogue */
- if (fn->stksiz && (saverestore || !usebp))
+ if (fn->stksiz && saverestore)
Xadd(pcode, KPTR, mkoper(OREG, .reg = RSP), mkoper(OIMM, .imm = fn->stksiz));
if (saverestore)
calleerestore(pcode, fn);
diff --git a/test/11-abi.c b/test/11-abi.c
index fcda498..5f9324f 100644
--- a/test/11-abi.c
+++ b/test/11-abi.c
@@ -24,7 +24,7 @@ union fi { float f; int i; };
struct hs { float x[10]; };
-struct hs g(float a, float b, float c, struct f2 d, union fi e, double z) {
+struct hs g(float a, float b, float c, struct f2 d, union fi e, double q, double qq, double qqq, double z) {
printf("%f %f %f {%f,%f} ", a, b, c, d.f[0], d.f[1]);
printf("%f(%xh) %f\n", e.f, e.i, z);
return (struct hs){-1.0f};
@@ -33,7 +33,7 @@ struct hs g(float a, float b, float c, struct f2 d, union fi e, double z) {
int main() {
struct ll a = f(1,2,(struct l){3},4,5,6, NULL, (struct x){9}, "abcdef");
printf(": %ld, %ld\n", a.a, a.b);
- struct hs h = g(1.0f, 2.0, 3.0f, (struct f2){4.0,5.0}, (union fi){-0.0f}, 99.f);
+ struct hs h = g(1.0f, 2.0, 3.0f, (struct f2){4.0,5.0}, (union fi){-0.0f}, 0,0,0, 99.f);
printf(": %f\n", h.x[0]);
}