commit b8de5c0b45f3724531f7f6a797f82cb719da4e87
parent 6f48bfde8f810cd7e705dc9c31f7391da7607acc
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 2 Jun 2026 04:09:15 -0700
cg: re-enable SV_ARITH delayed-arith -O0 peephole (Track 6.3)
Diffstat:
3 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/doc/CODEGEN.md b/doc/CODEGEN.md
@@ -90,10 +90,14 @@ one of an operand (immediate / constant / semantic local / lvalue address), a
branch can fuse a compare instead of materializing a 0/1, or so a small
immediate can flow straight into a `binop`. These delayed forms and the
constant folding around them are the `-O0` peephole; it lives in `fold.c`
-(contract in `fold.h`), kept isolated from the stack discipline. The delayed
-*compare* is live; the delayed *arith* machinery is present but currently gated
-off (`api_can_delay_int_arith` returns 0) pending the place/value rework that
-removes the load/store addressing rider which forced it off. The stack does
+(contract in `fold.h`), kept isolated from the stack discipline. Both delayed
+forms are live: the delayed *compare* fuses into a following branch, and the
+delayed *arith* (admitted by `api_can_delay_int_arith` for an unflagged foldable
+integer op) flows an unmaterialized binop/unop into a following op so an
+immediate chain folds or an identity collapses, materializing only when a
+consumer needs a value. (The delayed *arith* was gated off while the load/store
+addressing rider existed; the strict place/value rework removed the rider and
+re-enabled it.) The stack does
**not** own registers, frame slots, spill policy, or caller-saved preservation;
those moved down into the target realizations. When an operation needs a value
emitted, the stack calls the corresponding `g->target->op(...)` semantic hook
diff --git a/src/cg/fold.c b/src/cg/fold.c
@@ -285,11 +285,12 @@ void api_materialize_cmp_to(CfreeCg* g, ApiSValue* sv, Operand dst) {
/* ============================================================
* 2b. Delayed arith (SV_ARITH) lifecycle
*
- * Currently gated off: api_can_delay_int_arith returns 0, so nothing builds an
- * SV_ARITH today. The machinery is kept here (rather than deleted) because
- * Track 6.3 re-enables it once Track 7 removes the load/store EA rider that
- * forced it off. Re-enabling is then a gate flip in api_can_delay_int_arith,
- * not a code move.
+ * Live: api_can_delay_int_arith admits a non-flagged foldable integer op, so an
+ * unflagged int binop/unop is held un-emitted as an SV_ARITH. A following op can
+ * then fuse it (fold an imm chain, collapse an identity) and a consumer that
+ * needs a value materializes it via api_materialize_arith_to. This was gated off
+ * while the load/store EA rider existed (Track 7 removed it); Track 6.3 flipped
+ * the gate back on.
* ============================================================ */
ApiSValue api_make_arith_unop(UnOp op, Operand a, CfreeCgTypeId ty,
@@ -383,10 +384,8 @@ int api_arith_rhs_reusable(const ApiSValue* sv) {
}
int api_can_delay_int_arith(CfreeCg* g, CfreeCgTypeId ty, u32 flags) {
- (void)g;
- (void)ty;
- (void)flags;
- return 0;
+ u32 width;
+ return g && !flags && api_foldable_int_type(g->c, ty, &width);
}
int api_op_is_int_identity(CfreeCg* g, BinOp op, CfreeCgTypeId ty, i64 imm) {
diff --git a/src/cg/fold.h b/src/cg/fold.h
@@ -26,10 +26,10 @@
* consumer is api_branch_if (control.c); api_ensure_local
* materializes it to a 0/1 when used as a value. LIVE.
* - SV_ARITH — a small immediate/local arith held so it can flow into a
- * following binop or collapse via identities. Currently
- * gated off (api_can_delay_int_arith returns 0); re-enabled
- * by Track 6.3 once Track 7 removes the EA rider. The code
- * lives here so 6.3 is a gate flip, not a move.
+ * following binop or collapse via identities. LIVE: admitted
+ * by api_can_delay_int_arith for an unflagged foldable int
+ * op. It was gated off while the load/store EA rider existed;
+ * Track 7 removed the rider and Track 6.3 re-enabled it.
* Each delayed form has make / release / materialize-to-dst entry points,
* plus the fold-chain and identity-collapse helpers for SV_ARITH.
*
@@ -66,7 +66,7 @@ void api_release_cmp(CfreeCg* g, ApiSValue* sv);
void api_materialize_cmp_to(CfreeCg* g, ApiSValue* sv, Operand dst);
CmpOp api_invert_cmp(CmpOp op);
-/* ---- 2b. delayed arith (SV_ARITH) lifecycle — gated off pending 6.3 ---- */
+/* ---- 2b. delayed arith (SV_ARITH) lifecycle — live (Track 6.3) ---- */
ApiSValue api_make_arith_unop(UnOp op, Operand a, CfreeCgTypeId ty, int a_owned);
ApiSValue api_make_arith_binop(BinOp op, Operand a, Operand b, CfreeCgTypeId ty,