commit cec5aeab9c5d70fee51c0e90ae8cf9f673fade85
parent 04a7d100199049a9550ce78eaee8a5835c571c64
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Mon, 18 May 2026 21:19:28 -0700
Fix x64 atomic compare-exchange register pressure
Diffstat:
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/api/cg.c b/src/api/cg.c
@@ -4421,6 +4421,33 @@ void cfree_cg_atomic_rmw(CfreeCg *g, CfreeCgMemAccess access,
api_push(g, api_make_sv(dst, val_ty));
}
+static int api_take_dead_owned_reg(ApiSValue *sv, u8 cls, Reg avoid, Reg *out) {
+ Reg r;
+ if (sv->res != RES_REG || sv->pinned)
+ return 0;
+ if (api_class_of_sv(sv) != cls)
+ return 0;
+ r = api_reg_of_sv(sv);
+ if (r == (Reg)REG_NONE || r == avoid)
+ return 0;
+ sv->res = RES_INHERENT;
+ *out = r;
+ return 1;
+}
+
+static Reg api_alloc_dead_input_or_spill(CfreeCg *g, ApiSValue *a,
+ ApiSValue *b, ApiSValue *c, u8 cls,
+ CfreeCgTypeId ty, Reg avoid) {
+ Reg r;
+ if (api_take_dead_owned_reg(a, cls, avoid, &r))
+ return r;
+ if (api_take_dead_owned_reg(b, cls, avoid, &r))
+ return r;
+ if (api_take_dead_owned_reg(c, cls, avoid, &r))
+ return r;
+ return api_alloc_reg_or_spill(g, cls, ty);
+}
+
void cfree_cg_atomic_cmpxchg(CfreeCg *g, CfreeCgMemAccess access,
CfreeCgMemOrder success, CfreeCgMemOrder failure,
int weak) {
@@ -4444,7 +4471,6 @@ void cfree_cg_atomic_cmpxchg(CfreeCg *g, CfreeCgMemAccess access,
api_sv_type(&expected));
api_validate_memory_value(g, "atomic_cmpxchg desired", val_ty,
api_sv_type(&desired));
- bool_ty = builtin_id(CFREE_CG_BUILTIN_BOOL);
addr = api_force_reg(g, &ptr, pty);
exp_op = api_sv_op_is_reg_or_imm(&expected)
? expected.op
@@ -4452,8 +4478,12 @@ void cfree_cg_atomic_cmpxchg(CfreeCg *g, CfreeCgMemAccess access,
des_op = api_sv_op_is_reg_or_imm(&desired)
? desired.op
: api_force_reg(g, &desired, val_ty);
- pr = api_alloc_reg_or_spill(g, api_type_class(val_ty), val_ty);
- kr = api_alloc_reg_or_spill(g, RC_INT, bool_ty);
+ bool_ty = builtin_id(CFREE_CG_BUILTIN_BOOL);
+ pr = api_alloc_dead_input_or_spill(g, &ptr, &expected, &desired,
+ api_type_class(val_ty), val_ty,
+ (Reg)REG_NONE);
+ kr = api_alloc_dead_input_or_spill(g, &ptr, &expected, &desired, RC_INT,
+ bool_ty, pr);
prior = api_op_reg(pr, val_ty);
ok = api_op_reg(kr, bool_ty);
g->target->atomic_cas(g->target, prior, ok, addr, exp_op, des_op,