kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit e27a288d3c9368f4d151a39394fd6119ca284daf
parent e5ae84b06a498b7da427ad94d04cf816ac1a6f63
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  1 Jun 2026 17:52:00 -0700

cg: remove dead SCOPE_IF/scope_else surface and CFREE_CG_TAIL_NEVER (Track 1a/1d)

The public CfreeCg API only ever produces SCOPE_LOOP/SCOPE_BLOCK, so the
scope_else CgTarget hook, the SCOPE_IF scope kind, and CGScopeDesc.cond were
unreachable end-to-end: nothing called scope_else, so the recorder never
emitted CG_IR_SCOPE_ELSE, so no backend replay fired. Remove:
  - SCOPE_IF / CGScopeDesc.cond / scope_else vtable member (cgtarget.h)
  - all 5 scope_else impls (native_direct, ir_recorder, c_emit, wasm, check)
  - the CG_IR_SCOPE_ELSE and IR_SCOPE_ELSE opcodes + every replay/pass arm
  - the SCOPE_IF-only NativeDirectScope/IRScopeAux/wasm-WIR fields and the
    desc.cond operand walkers across the opt passes

CFREE_CG_TAIL_NEVER was a second spelling of TAIL_DEFAULT; remove it (toy
maps notail/tail_never to TAIL_DEFAULT). No behavior change.

Track 1 of doc/plan/CODEGEN.md.

Diffstat:
Minclude/cfree/cg.h | 2--
Mlang/toy/builtins.c | 2+-
Msrc/arch/c_target/c_emit.c | 18------------------
Msrc/arch/c_target/c_emit.h | 1-
Msrc/arch/c_target/ir_emit.c | 3---
Msrc/arch/check_target.c | 6------
Msrc/arch/wasm/emit.c | 56++------------------------------------------------------
Msrc/arch/wasm/internal.h | 4+---
Msrc/arch/wasm/ir_emit.c | 11-----------
Msrc/cg/cgtarget.h | 10+++-------
Msrc/cg/ir.h | 1-
Msrc/cg/ir_dump.c | 2--
Msrc/cg/ir_recorder.c | 5-----
Msrc/cg/native_direct_target.c | 24------------------------
Msrc/cg/native_direct_target.h | 5+----
Msrc/interp/lower.c | 1-
Msrc/opt/cg_ir_lower.c | 6------
Msrc/opt/ir.h | 14++++----------
Msrc/opt/ir_print.c | 2--
Msrc/opt/opt_util.c | 5+----
Msrc/opt/pass_addr_fold.c | 14++++----------
Msrc/opt/pass_analysis.c | 10++--------
Msrc/opt/pass_cfg.c | 8--------
Msrc/opt/pass_combine.c | 5+----
Msrc/opt/pass_dce.c | 1-
Msrc/opt/pass_hard_live.c | 5+----
Msrc/opt/pass_jump.c | 1-
Msrc/opt/pass_native_emit.c | 1-
Msrc/opt/pass_o2.c | 1-
Msrc/opt/pass_ssa.c | 11+++--------
Mtest/cg/ir_recorder_test.c | 5++---
31 files changed, 26 insertions(+), 214 deletions(-)

diff --git a/include/cfree/cg.h b/include/cfree/cg.h @@ -809,8 +809,6 @@ typedef enum CfreeCgTailPolicy { * diagnostic naming the reason. Never silently degrades to an ordinary * call. */ CFREE_CG_TAIL_MUST, - /* Ordinary call even in tail position. Treated as DEFAULT. */ - CFREE_CG_TAIL_NEVER, } CfreeCgTailPolicy; typedef enum CfreeCgCallFlag { diff --git a/lang/toy/builtins.c b/lang/toy/builtins.c @@ -245,7 +245,7 @@ static int toy_parse_call_attr(ToyParser* p, CfreeCgCallAttrs* attrs) { attrs->tail = CFREE_CG_TAIL_MUST; } else if (toy_sym_is(p, name, "notail") || toy_sym_is(p, name, "tail_never")) { - attrs->tail = CFREE_CG_TAIL_NEVER; + attrs->tail = CFREE_CG_TAIL_DEFAULT; } else if (toy_sym_is(p, name, "inline")) { attrs->inline_policy = CFREE_CG_INLINE_HINT; } else if (toy_sym_is(p, name, "always_inline")) { diff --git a/src/arch/c_target/c_emit.c b/src/arch/c_target/c_emit.c @@ -1550,27 +1550,9 @@ CGScope c_emit_scope_begin(CTarget* t, const CGScopeDesc* d) { t->last_was_terminator = 0; return (CGScope)(idx + 1u); } - /* SCOPE_IF carries a cond consumed here. The public CfreeCg API always - * emits SCOPE_LOOP, so this branch only fires for internal callers. */ - if (d->kind == SCOPE_IF) { - char buf[24]; - c_label_name(d->break_label, buf, sizeof buf); - cbuf_puts(&t->body, " if (!("); - c_emit_operand(t, d->cond); - cbuf_puts(&t->body, ")) goto "); - cbuf_puts(&t->body, buf); - cbuf_puts(&t->body, ";\n"); - } return (CGScope)(idx + 1u); } -void c_emit_scope_else(CTarget* t, CGScope s) { - (void)t; - (void)s; - /* Public API doesn't emit SCOPE_IF; if it ever does, the frontend is - * responsible for placing the else label and the break_label itself. */ -} - void c_emit_scope_end(CTarget* t, CGScope s) { if (s == 0 || (u32)s > t->nscopes) { compiler_panic(t->c, t->cur_fn ? t->cur_fn->loc : (SrcLoc){0, 0, 0}, diff --git a/src/arch/c_target/c_emit.h b/src/arch/c_target/c_emit.h @@ -226,7 +226,6 @@ void c_emit_local_static_data_write(CTarget*, const u8*, u64); void c_emit_local_static_data_label_addr(CTarget*, Label, i64, u32, u32); void c_emit_local_static_data_end(CTarget*); CGScope c_emit_scope_begin(CTarget*, const CGScopeDesc*); -void c_emit_scope_else(CTarget*, CGScope); void c_emit_scope_end(CTarget*, CGScope); void c_emit_break_to(CTarget*, CGScope); void c_emit_continue_to(CTarget*, CGScope); diff --git a/src/arch/c_target/ir_emit.c b/src/arch/c_target/ir_emit.c @@ -177,9 +177,6 @@ static void ir_emit_inst(CIrEmitter* e, const CgIrInst* in) { ir_scope_bind(e, aux->scope, emitted, in->loc); return; } - case CG_IR_SCOPE_ELSE: - c_emit_scope_else(t, ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc)); - return; case CG_IR_SCOPE_END: c_emit_scope_end(t, ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc)); return; diff --git a/src/arch/check_target.c b/src/arch/check_target.c @@ -129,11 +129,6 @@ static CGScope check_scope_begin(CgTarget* t, const CGScopeDesc* d) { return x->next_scope; } -static void check_scope_else(CgTarget* t, CGScope s) { - (void)t; - (void)s; -} - static void check_scope_end(CgTarget* t, CGScope s) { (void)t; (void)s; @@ -386,7 +381,6 @@ static CgTarget* check_backend_make(Compiler* c, ObjBuilder* o, t->local_static_data_label_addr = check_local_static_data_label_addr; t->local_static_data_end = check_local_static_data_end; t->scope_begin = check_scope_begin; - t->scope_else = check_scope_else; t->scope_end = check_scope_end; t->break_to = check_scope_xfer; t->continue_to = check_scope_xfer; diff --git a/src/arch/wasm/emit.c b/src/arch/wasm/emit.c @@ -409,28 +409,11 @@ CGScope wasm_scope_begin(CGTarget* tg, const CGScopeDesc* d) { } } - if (d->kind == SCOPE_IF) { - /* SCOPE_IF receives a precomputed condition operand. */ - if (d->cond.kind == OPK_REG) { - s->cond_reg = d->cond.v.reg; - } else if (d->cond.kind == OPK_IMM) { - /* Materialize via a synthetic load_imm to keep the lowering uniform. */ - WIR* w = wir_push(t); - w->op = WIR_LOAD_IMM; - w->dst = (Reg)1; /* placeholder — emitted inline; no register needed */ - w->imm = d->cond.v.imm; - w->type = d->cond.type; - s->cond_reg = REG_NONE; - } else { - wfail(t, "wasm: scope_begin(SCOPE_IF) with unsupported cond kind"); - } - } - WIR* open = wir_push(t); open->op = WIR_SCOPE_OPEN; open->scope_id = s->id; open->cgop = d->kind; - open->dst = s->cond_reg; + open->dst = REG_NONE; s->placed_in_wir = 1; t->nscopes++; @@ -444,17 +427,6 @@ static WScope* scope_by_id(WTarget* t, u32 id) { return NULL; } -void wasm_scope_else(CGTarget* tg, CGScope sc) { - WTarget* t = (WTarget*)tg; - WScope* s = scope_by_id(t, (u32)sc); - if (!s) wfail(t, "wasm: scope_else on unknown scope"); - if (s->cg_kind != SCOPE_IF) wfail(t, "wasm: scope_else on non-if scope"); - WIR* w = wir_push(t); - w->op = WIR_SCOPE_ELSE; - w->scope_id = s->id; - t->dead = 0; -} - void wasm_scope_end(CGTarget* tg, CGScope sc) { WTarget* t = (WTarget*)tg; WScope* s = scope_by_id(t, (u32)sc); @@ -3825,35 +3797,11 @@ static void linearize_range(WTarget* t, LoweringState* L, u32 start, u32 end) { L->cur_depth++; s->break_depth = L->cur_depth; s->cont_depth = L->cur_depth; /* unused */ - } else if (w->cgop == SCOPE_IF) { - /* For SCOPE_IF the cond should already be on the value stack; CG - * passes it via desc.cond, which we recorded as w->dst (cond_reg) - * or via the preceding WIR_LOAD_IMM. */ - if (w->dst != REG_NONE) { - emit_push_operand_reg(t, w->dst); - } - /* Implicit i32 cond from a prior WIR_LOAD_IMM is already on - * the wasm value stack via the LOAD_IMM emission above — but - * actually LOAD_IMM does emit_local_set, so the value isn't on - * the stack. This path isn't used today; diagnose if we hit - * it. */ - if (w->dst == REG_NONE) { - wfail(t, "wasm: SCOPE_IF cond materialization not implemented"); - } - emit_insn(t, WASM_INSN_IF, 0); - L->cur_depth++; - s->break_depth = L->cur_depth; - s->cont_depth = L->cur_depth; } else { wfail(t, "wasm: unknown scope kind %d", (int)w->cgop); } break; } - case WIR_SCOPE_ELSE: { - if (L->nstack == 0) wfail(t, "wasm: scope_else without open scope"); - emit_insn(t, WASM_INSN_ELSE, 0); - break; - } case WIR_SCOPE_CLOSE: { if (L->nstack == 0) wfail(t, "wasm: scope_close without open scope"); LoweringScope* s = &L->stack[L->nstack - 1u]; @@ -4075,7 +4023,7 @@ static void linearize(WTarget* t) { for (u32 i = t->nwir; i > 0; --i) { WIR* w = &t->wir[i - 1u]; if (w->op == WIR_LABEL || w->op == WIR_SCOPE_OPEN || - w->op == WIR_SCOPE_CLOSE || w->op == WIR_SCOPE_ELSE) + w->op == WIR_SCOPE_CLOSE) continue; if (w->op == WIR_RET || w->op == WIR_JUMP || w->op == WIR_SWITCH || w->op == WIR_UNREACHABLE) { diff --git a/src/arch/wasm/internal.h b/src/arch/wasm/internal.h @@ -66,9 +66,8 @@ typedef enum WIROp { WIR_CALL_INDIRECT, /* callee in `a` (i32 table index), typeidx in `imm`, nargs/args[]/ret_reg same shape as WIR_CALL */ WIR_RET, /* val (or REG_NONE) */ - WIR_SCOPE_OPEN, /* scope_id; kind == SCOPE_LOOP/BLOCK/IF; cond reg for IF */ + WIR_SCOPE_OPEN, /* scope_id; kind == SCOPE_LOOP/BLOCK */ WIR_SCOPE_CLOSE, /* scope_id */ - WIR_SCOPE_ELSE, /* scope_id */ WIR_UNREACHABLE, WIR_SWITCH, /* selector operand + dense label table at lowering */ WIR_LOAD_LOCAL, /* dst, frame_slot in `imm`, type */ @@ -191,7 +190,6 @@ typedef struct WScope { u32 id; Label break_lbl; Label cont_lbl; - Reg cond_reg; /* SCOPE_IF: condition operand carried by scope_begin */ CfreeCgTypeId result_type; } WScope; diff --git a/src/arch/wasm/ir_emit.c b/src/arch/wasm/ir_emit.c @@ -23,7 +23,6 @@ void wasm_jump(CGTarget*, Label); void wasm_cmp_branch(CGTarget*, CmpOp, Operand, Operand, Label); void wasm_switch(CGTarget*, const CGSwitchDesc*); CGScope wasm_scope_begin(CGTarget*, const CGScopeDesc*); -void wasm_scope_else(CGTarget*, CGScope); void wasm_scope_end(CGTarget*, CGScope); void wasm_break_to(CGTarget*, CGScope); void wasm_continue_to(CGTarget*, CGScope); @@ -682,19 +681,9 @@ static void wasm_ir_emit_inst(WasmIrEmitter* e, const CgIrFunc* f, d.break_label = aux->desc.break_label; d.continue_label = aux->desc.continue_label; d.result_type = aux->desc.result_type; - /* Only SCOPE_IF consumes cond; source_op (not value_op) so an - * address-taken local condition is loaded from memory, not read as a - * bare wasm local. */ - d.cond = aux->desc.kind == SCOPE_IF - ? wasm_ir_source_op(e, aux->desc.cond, in->loc) - : wasm_ir_value_op(e, aux->desc.cond); wasm_ir_bind_scope(e, aux->scope, wasm_scope_begin(t, &d), in->loc); return; } - case CG_IR_SCOPE_ELSE: - wasm_scope_else(t, - wasm_ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc)); - return; case CG_IR_SCOPE_END: wasm_scope_end(t, wasm_ir_scope_lookup(e, (CGScope)in->extra.imm, in->loc)); diff --git a/src/cg/cgtarget.h b/src/cg/cgtarget.h @@ -324,7 +324,6 @@ typedef u32 Label; typedef enum ScopeKind { SCOPE_BLOCK, /* break exits forward */ SCOPE_LOOP, /* break exits forward; continue uses explicit target */ - SCOPE_IF, /* cond consumed at scope_begin */ } ScopeKind; typedef u32 CGScope; @@ -337,7 +336,6 @@ typedef struct CGScopeDesc { one */ Label continue_label; /* explicit target for continue; LABEL_NONE for non-loops */ - Operand cond; /* SCOPE_IF condition; ignored otherwise */ CfreeCgTypeId result_type; /* reserved for structured expression results */ } CGScopeDesc; @@ -525,14 +523,12 @@ struct CgTarget { * Mirrors CG's scope ops. CG passes explicit break/continue targets so C * `for` continues can land on the increment expression rather than the loop * header. Real backends shim these onto label_new/label_place/jump. - * The WASM backend consumes them natively to emit block/loop/if with + * The WASM backend consumes them natively to emit block/loop with * structurally-bounded br targets, which is what gives WASM its CFI. * - * For SCOPE_IF, `cond` is the i1 operand; ignored for BLOCK/LOOP. - * `result_type` is reserved for if-as-expression on WASM (NULL for the - * statement case used by C); other backends ignore it. */ + * `result_type` is reserved for structured expression results on WASM (NULL + * for the statement case used by C); other backends ignore it. */ CGScope (*scope_begin)(CgTarget*, const CGScopeDesc*); - void (*scope_else)(CgTarget*, CGScope); void (*scope_end)(CgTarget*, CGScope); void (*break_to)(CgTarget*, CGScope); void (*continue_to)(CgTarget*, CGScope); diff --git a/src/cg/ir.h b/src/cg/ir.h @@ -41,7 +41,6 @@ typedef enum CgIrOp { CG_IR_LOCAL_STATIC_DATA_LABEL_ADDR, CG_IR_LOCAL_STATIC_DATA_END, CG_IR_SCOPE_BEGIN, - CG_IR_SCOPE_ELSE, CG_IR_SCOPE_END, CG_IR_BREAK_TO, CG_IR_CONTINUE_TO, diff --git a/src/cg/ir_dump.c b/src/cg/ir_dump.c @@ -49,7 +49,6 @@ static const char* cg_ir_op_name(CgIrOp op) { case CG_IR_LOCAL_STATIC_DATA_LABEL_ADDR: return "local_static_data_label_addr"; case CG_IR_LOCAL_STATIC_DATA_END: return "local_static_data_end"; case CG_IR_SCOPE_BEGIN: return "scope_begin"; - case CG_IR_SCOPE_ELSE: return "scope_else"; case CG_IR_SCOPE_END: return "scope_end"; case CG_IR_BREAK_TO: return "break_to"; case CG_IR_CONTINUE_TO: return "continue_to"; @@ -228,7 +227,6 @@ static void put_inst_extra(StrBuf* sb, const CgIrFunc* f, const CgIrInst* in) { strbuf_put_slice(sb, SLICE_LIT(" Lbl")); strbuf_put_u64(sb, (u64)in->extra.imm); break; - case CG_IR_SCOPE_ELSE: case CG_IR_SCOPE_END: case CG_IR_BREAK_TO: case CG_IR_CONTINUE_TO: diff --git a/src/cg/ir_recorder.c b/src/cg/ir_recorder.c @@ -259,10 +259,6 @@ static void rec_scope_id_op(CgTarget* t, CgIrOp op, CGScope scope) { in->extra.imm = (i64)scope; } -static void rec_scope_else(CgTarget* t, CGScope scope) { - rec_scope_id_op(t, CG_IR_SCOPE_ELSE, scope); -} - static void rec_scope_end(CgTarget* t, CGScope scope) { rec_scope_id_op(t, CG_IR_SCOPE_END, scope); } @@ -622,7 +618,6 @@ CgTarget* cg_ir_recorder_new(Compiler* c, ObjBuilder* obj, r->base.local_static_data_end = rec_local_static_data_end; r->base.data_label_addr_unsupported_msg = rec_data_label_addr_unsupported_msg; r->base.scope_begin = rec_scope_begin; - r->base.scope_else = rec_scope_else; r->base.scope_end = rec_scope_end; r->base.break_to = rec_break_to; r->base.continue_to = rec_continue_to; diff --git a/src/cg/native_direct_target.c b/src/cg/native_direct_target.c @@ -1157,16 +1157,6 @@ static CGScope nd_scope_begin(CgTarget* t, const CGScopeDesc* desc) { s->continue_label = desc->continue_label; if (desc->kind == SCOPE_LOOP && s->continue_label == LABEL_NONE) s->continue_label = nd_label_new_raw(d); - if (desc->kind == SCOPE_IF) { - Operand zero; - s->else_label = nd_label_new_raw(d); - s->end_label = nd_label_new_raw(d); - memset(&zero, 0, sizeof zero); - zero.kind = OPK_IMM; - zero.type = desc->cond.type; - zero.v.imm = 0; - nd_cmp_branch(t, CMP_EQ, desc->cond, zero, s->else_label); - } return id; } @@ -1175,22 +1165,9 @@ static NativeDirectScope* nd_scope(NativeDirectTarget* d, CGScope scope) { return &d->scopes[scope - 1u]; } -static void nd_scope_else(CgTarget* t, CGScope scope) { - NativeDirectTarget* d = nd_of(t); - NativeDirectScope* s = nd_scope(d, scope); - if (s->kind != SCOPE_IF) nd_panic(d, "scope_else on non-if scope"); - s->has_else = 1; - nd_jump(t, s->end_label); - nd_label_place(t, s->else_label); -} - static void nd_scope_end(CgTarget* t, CGScope scope) { NativeDirectTarget* d = nd_of(t); NativeDirectScope* s = nd_scope(d, scope); - if (s->kind == SCOPE_IF) { - if (!s->has_else) nd_label_place(t, s->else_label); - nd_label_place(t, s->end_label); - } if (s->owns_break) nd_label_place(t, s->break_label); } @@ -1789,7 +1766,6 @@ CgTarget* native_direct_target_new(Compiler* c, ObjBuilder* obj, d->base.local_static_data_end = nd_local_static_data_end; d->base.data_label_addr_unsupported_msg = nd_data_label_addr_unsupported_msg; d->base.scope_begin = nd_scope_begin; - d->base.scope_else = nd_scope_else; d->base.scope_end = nd_scope_end; d->base.break_to = nd_break_to; d->base.continue_to = nd_continue_to; diff --git a/src/cg/native_direct_target.h b/src/cg/native_direct_target.h @@ -13,13 +13,10 @@ typedef struct NativeDirectTarget NativeDirectTarget; typedef struct NativeDirectScope { u8 kind; /* ScopeKind */ - u8 has_else; u8 owns_break; - u8 pad; + u8 pad[2]; Label break_label; Label continue_label; - Label else_label; - Label end_label; } NativeDirectScope; typedef enum NativeDirectBarrier { diff --git a/src/interp/lower.c b/src/interp/lower.c @@ -53,7 +53,6 @@ static int inst_emits(u16 op) { case IR_PHI: case IR_PARAM_DECL: case IR_SCOPE_BEGIN: - case IR_SCOPE_ELSE: case IR_SCOPE_END: return 0; default: diff --git a/src/opt/cg_ir_lower.c b/src/opt/cg_ir_lower.c @@ -342,7 +342,6 @@ static void mark_leaders(CgIrLower* l, u32* label_place) { case CG_IR_SCOPE_BEGIN: if (i + 1u < f->ninsts) l->leader[i + 1u] = 1; break; - case CG_IR_SCOPE_ELSE: case CG_IR_SCOPE_END: l->leader[i] = 1; if (i + 1u < f->ninsts) l->leader[i + 1u] = 1; @@ -878,9 +877,6 @@ static void lower_one_inst(CgIrLower* l, u32 idx) { case CG_IR_SCOPE_BEGIN: op = IR_SCOPE_BEGIN; break; - case CG_IR_SCOPE_ELSE: - op = IR_SCOPE_ELSE; - break; case CG_IR_SCOPE_END: op = IR_SCOPE_END; break; @@ -1115,12 +1111,10 @@ static void lower_one_inst(CgIrLower* l, u32 idx) { aux->desc.break_label = src->desc.break_label; aux->desc.continue_label = src->desc.continue_label; aux->desc.result_type = src->desc.result_type; - aux->desc.cond = lower_operand_value(l, &src->desc.cond, in->loc); } out->extra.aux = aux; break; } - case CG_IR_SCOPE_ELSE: case CG_IR_SCOPE_END: case CG_IR_BREAK_TO: case CG_IR_CONTINUE_TO: diff --git a/src/opt/ir.h b/src/opt/ir.h @@ -295,7 +295,6 @@ typedef enum IROp { IR_LOCAL_STATIC_DATA_END, IR_RET, /* extra.aux = IRRetAux* (NULL for void). */ IR_SCOPE_BEGIN, /* extra.aux = IRScopeAux. */ - IR_SCOPE_ELSE, /* extra.imm = scope id (Val). */ IR_SCOPE_END, /* extra.imm = scope id (Val). */ IR_BREAK_TO, /* extra.imm = scope id (Val). */ IR_CONTINUE_TO, /* extra.imm = scope id (Val). */ @@ -407,16 +406,11 @@ typedef struct IRRetAux { typedef struct IRScopeAux { CGScopeDesc desc; u32 scope_id; /* 1-based; the CGScope handed back to the caller */ - /* For SCOPE_IF: blocks for then-arm, else-arm, and join after end. - * For SCOPE_LOOP/SCOPE_BLOCK: the caller-supplied break/continue - * labels translated to block ids; if the desc passed LABEL_NONE we - * leave 0 (unused — break_to/continue_to is illegal in that case). */ - u32 if_then_block; - u32 if_else_block; - u32 if_end_block; + /* The caller-supplied break/continue labels translated to block ids; if the + * desc passed LABEL_NONE we leave 0 (unused — break_to/continue_to is + * illegal in that case). */ u32 loop_break_block; u32 loop_continue_block; - u8 if_has_else; } IRScopeAux; typedef struct IRAtomicAux { @@ -673,7 +667,7 @@ typedef struct Func { /* Scope id table. Indexed by scope_id (1-based). Values map to * IRScopeAux entries (via the IR_SCOPE_BEGIN inst). Stored as a flat - * pointer table for O(1) lookup during scope_else/end/break/continue + * pointer table for O(1) lookup during scope_end/break/continue * recording and replay. */ Inst** scope_aux_inst; u32 nscopes, scopes_cap; diff --git a/src/opt/ir_print.c b/src/opt/ir_print.c @@ -90,8 +90,6 @@ static const char* op_name(IROp op) { return "ret"; case IR_SCOPE_BEGIN: return "scope_begin"; - case IR_SCOPE_ELSE: - return "scope_else"; case IR_SCOPE_END: return "scope_end"; case IR_BREAK_TO: diff --git a/src/opt/opt_util.c b/src/opt/opt_util.c @@ -103,11 +103,8 @@ void opt_walk_inst_operands(Func* f, Inst* in, OptOperandWalkFn fn, void* ctx) { if (aux && aux->present) opt_walk_abivalue(f, in, &aux->val, 0, fn, ctx); break; } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux) opt_walk_operand(f, in, &aux->desc.cond, 0, fn, ctx); + case IR_SCOPE_BEGIN: break; - } case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) break; diff --git a/src/opt/pass_addr_fold.c b/src/opt/pass_addr_fold.c @@ -117,11 +117,8 @@ static int addr_xform_pregs_aux_uses(Inst* in, PReg p) { if (!aux || !aux->present) return 0; return addr_xform_pregs_abivalue_uses(&aux->val, p); } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (!aux) return 0; - return addr_xform_pregs_op_uses(&aux->desc.cond, p); - } + case IR_SCOPE_BEGIN: + return 0; case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) return 0; @@ -334,11 +331,8 @@ static int promote_aux_uses_slot(const Inst* in, FrameSlot slot) { if (!aux || !aux->present) return 0; return promote_abivalue_uses_slot(&aux->val, slot); } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (!aux) return 0; - return promote_op_uses_slot(&aux->desc.cond, slot); - } + case IR_SCOPE_BEGIN: + return 0; case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) return 0; diff --git a/src/opt/pass_analysis.c b/src/opt/pass_analysis.c @@ -161,11 +161,8 @@ static void verify_aux_shapes(Func* f, const char* stage, Inst* in, verify_abivalue_shape(f, stage, &aux->val, physical_regs); break; } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux) verify_operand_shape(f, stage, &aux->desc.cond, physical_regs); + case IR_SCOPE_BEGIN: break; - } case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) break; @@ -465,11 +462,8 @@ static void opt_collect_inst_uses(Func* f, u32 b, u32 i, Inst* in) { if (aux && aux->present) opt_use_add_abivalue(f, b, i, &aux->val, 0); break; } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux) opt_use_add_operand(f, b, i, OPT_USE_NONE, &aux->desc.cond, 0); + case IR_SCOPE_BEGIN: break; - } case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) break; diff --git a/src/opt/pass_cfg.c b/src/opt/pass_cfg.c @@ -51,17 +51,9 @@ static int scope_control_succ_count(const Block* bl, const Inst* in, u8* nsucc_out) { switch ((IROp)in->op) { case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux && aux->desc.kind == SCOPE_IF) { - *nsucc_out = 2; - return 1; - } *nsucc_out = bl->nsucc; return bl->nsucc != 0; } - case IR_SCOPE_ELSE: - *nsucc_out = 1; - return 1; case IR_SCOPE_END: *nsucc_out = bl->nsucc; return bl->nsucc != 0; diff --git a/src/opt/pass_combine.c b/src/opt/pass_combine.c @@ -179,11 +179,8 @@ static int inst_uses_phys_reg(const Inst* in, const Operand* r) { if (aux && aux->present) n += abi_uses_phys_reg(&aux->val, r); break; } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux) n += count_operand_phys_uses(&aux->desc.cond, r); + case IR_SCOPE_BEGIN: break; - } case IR_ALLOCA: if (in->nopnds >= 2) n += count_operand_phys_uses(&in->opnds[1], r); break; diff --git a/src/opt/pass_dce.c b/src/opt/pass_dce.c @@ -54,7 +54,6 @@ int opt_inst_has_side_effect(Func* f, const Inst* in) { case IR_LOCAL_STATIC_DATA_END: case IR_RET: case IR_SCOPE_BEGIN: - case IR_SCOPE_ELSE: case IR_SCOPE_END: case IR_BREAK_TO: case IR_CONTINUE_TO: diff --git a/src/opt/pass_hard_live.c b/src/opt/pass_hard_live.c @@ -162,11 +162,8 @@ void opt_hard_inst_use_def(Func* f, const Inst* in, OptHardRegSet* use, if (aux && aux->present) hard_use_abivalue(use, &aux->val); break; } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux) hard_use_operand(use, &aux->desc.cond); + case IR_SCOPE_BEGIN: break; - } case IR_ALLOCA: if (in->nopnds >= 1) hard_def_operand(def, &in->opnds[0]); if (in->nopnds >= 2) hard_use_operand(use, &in->opnds[1]); diff --git a/src/opt/pass_jump.c b/src/opt/pass_jump.c @@ -123,7 +123,6 @@ static int passthrough_succ_block(const JumpCleanupCtx* c, u32 block, switch ((IROp)bl->insts[0].op) { case IR_NOP: case IR_SCOPE_BEGIN: - case IR_SCOPE_ELSE: case IR_SCOPE_END: break; default: diff --git a/src/opt/pass_native_emit.c b/src/opt/pass_native_emit.c @@ -749,7 +749,6 @@ static void emit_inst(NativeEmitCtx* e, u32 block, u32 order_index, Inst* in, case IR_CONST_BYTES: case IR_PHI: case IR_SCOPE_BEGIN: - case IR_SCOPE_ELSE: case IR_SCOPE_END: return; case IR_PARAM_DECL: diff --git a/src/opt/pass_o2.c b/src/opt/pass_o2.c @@ -2549,7 +2549,6 @@ static int pressure_barrier(const Inst* in) { case IR_BITFIELD_STORE: case IR_CALL: case IR_SCOPE_BEGIN: - case IR_SCOPE_ELSE: case IR_SCOPE_END: case IR_BREAK_TO: case IR_CONTINUE_TO: diff --git a/src/opt/pass_ssa.c b/src/opt/pass_ssa.c @@ -90,10 +90,8 @@ static int aux_has_slot(const Inst* in, u32 slot_id) { IRRetAux* aux = (IRRetAux*)in->extra.aux; return aux && aux->present && abivalue_has_slot(&aux->val, slot_id); } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - return aux && operand_has_slot(&aux->desc.cond, slot_id); - } + case IR_SCOPE_BEGIN: + return 0; case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) return 0; @@ -378,11 +376,8 @@ static void reg_replace_inst_uses(RegRenameCtx* ctx, Inst* in) { if (aux && aux->present) reg_replace_abivalue_uses(ctx, &aux->val); break; } - case IR_SCOPE_BEGIN: { - IRScopeAux* aux = (IRScopeAux*)in->extra.aux; - if (aux) reg_replace_use(ctx, &aux->desc.cond); + case IR_SCOPE_BEGIN: break; - } case IR_ASM_BLOCK: { IRAsmAux* aux = (IRAsmAux*)in->extra.aux; if (!aux) break; diff --git a/test/cg/ir_recorder_test.c b/test/cg/ir_recorder_test.c @@ -271,8 +271,7 @@ static void test_labels_scopes_and_address_taken_locals(void) { t->load_label_addr(t, op_local(ptr, tc.ptr), label); t->addr_of(t, op_local(ptr, tc.ptr), op_local(value, tc.i32)); memset(&sd, 0, sizeof sd); - sd.kind = SCOPE_IF; - sd.cond = op_imm(1, tc.i32); + sd.kind = SCOPE_BLOCK; scope = t->scope_begin(t, &sd); t->break_to(t, scope); t->scope_end(t, scope); @@ -289,7 +288,7 @@ static void test_labels_scopes_and_address_taken_locals(void) { "scope table should preserve semantic scope ids"); scope_aux = (CgIrScopeAux*)f->insts[3].extra.aux; EXPECT(scope_aux && scope_aux->scope == scope && - scope_aux->desc.kind == SCOPE_IF, + scope_aux->desc.kind == SCOPE_BLOCK, "scope_begin inst should carry scope metadata"); tc_fini(&tc); }