diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 0e15e5d..d3752f8 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -19,6 +19,7 @@ jobs: shell: bash - name: Try compile run: | + git submodule update --init chmod +x build.sh ./build.sh shell: bash diff --git a/cg/x86_stupid/cg.c b/cg/x86_stupid/cg.c index cdad779..5ff43e8 100644 --- a/cg/x86_stupid/cg.c +++ b/cg/x86_stupid/cg.c @@ -671,6 +671,7 @@ static vx_IrOp* emiti(vx_IrOp *prev, vx_IrOp* op, FILE* file) { case VX_IR_OP_SHR: // "a", "b" { Location* o = varData[op->outs[0].var].location; + assert(o); Location* a = as_loc(o->bytesWidth, *vx_IrOp_param(op, VX_IR_NAME_OPERAND_A)); Location* b = as_loc(o->bytesWidth, *vx_IrOp_param(op, VX_IR_NAME_OPERAND_B)); @@ -698,6 +699,7 @@ static vx_IrOp* emiti(vx_IrOp *prev, vx_IrOp* op, FILE* file) { case VX_IR_OP_BITWISE_NOT: // "val" { Location* o = varData[op->outs[0].var].location; + assert(o); Location* v = as_loc(o->bytesWidth, *vx_IrOp_param(op, VX_IR_NAME_VALUE)); emiti_unary(v, o, "not", file); } break; @@ -712,6 +714,7 @@ static vx_IrOp* emiti(vx_IrOp *prev, vx_IrOp* op, FILE* file) { { vx_IrVar ov = op->outs[0].var; Location* o = varData[ov].location; + assert(o); Location* a = as_loc(o->bytesWidth, *vx_IrOp_param(op, VX_IR_NAME_OPERAND_A)); Location* b = as_loc(o->bytesWidth, *vx_IrOp_param(op, VX_IR_NAME_OPERAND_B)); @@ -917,6 +920,12 @@ void vx_cg_x86stupid_gen(vx_IrBlock* block, FILE* out) { varData[val.var].heat ++; } } + for (size_t i = 0; i < op->params_len; i ++) { + vx_IrValue val = op->params[i].val; + if (val.type == VX_IR_VAL_VAR) { + varData[val.var].heat ++; + } + } } /* ======================== VAR ALLOC ===================== */ diff --git a/ir/analysis.c b/ir/analysis.c index ff6f840..bb5e51d 100644 --- a/ir/analysis.c +++ b/ir/analysis.c @@ -32,19 +32,20 @@ bool vx_IrBlock_vardecl_is_in_ins(vx_IrBlock *block, vx_IrVar var) { // before // vx_IrOp *vx_IrBlock_vardecl_out_before(vx_IrBlock *block, vx_IrVar var, vx_IrOp *before) { - for (vx_IrOp *op = before->parent->first; op; op = op->next) { + if (before == NULL) { + before = vx_IrBlock_tail(block); + } + + for (vx_IrOp* op = vx_IrOp_predecessor(before); op; op = vx_IrOp_predecessor(op)) { for (size_t i = 0; i < op->outs_len; i ++) if (op->outs[i].var == var) return op; + } - if (op == before) { - if (before->parent->parent_op) - return vx_IrBlock_vardecl_out_before(block, var, before->parent->parent_op); + if (block->parent == NULL) + return NULL; - return NULL; - } - } - return NULL; + return vx_IrBlock_vardecl_out_before(block->parent, var, block->parent_op); } bool vx_IrOp_ends_flow(vx_IrOp *op) { @@ -174,9 +175,9 @@ bool vx_IrBlock_is_volatile(vx_IrBlock *block) return false; } -vx_IrType *vx_IrBlock_typeof_var(vx_IrBlock *block, vx_IrVar var) { - if (block->as_root.vars[var].ll_type) { - return block->as_root.vars[var].ll_type; +static vx_IrType* typeofvar(vx_IrBlock* block, vx_IrVar var) { + if (!block) { + return NULL; } for (size_t i = 0; i < block->ins_len; i ++) { @@ -185,19 +186,31 @@ vx_IrType *vx_IrBlock_typeof_var(vx_IrBlock *block, vx_IrVar var) { } } - vx_IrOp *decl = vx_IrBlock_root(block)->as_root.vars[var].decl; - if (decl == NULL) - goto warn; - - for (size_t i = 0; i < decl->outs_len; i ++) - if (decl->outs[i].var == var) - return decl->outs[i].type; + for (vx_IrOp* op = block->first; op; op = op->next) { + for (size_t i = 0; i < op->outs_len; i ++) + if (op->outs[i].var == var) + return op->outs[i].type; + + for (size_t i = 0; i < op->params_len; i ++) { + if (op->params[i].val.type == VX_IR_VAL_BLOCK) { + vx_IrType* ty = typeofvar(op->params[i].val.block, var); + if (ty) return ty; + } + } + } -warn: - fprintf(stderr, "VARIABLE %%%zu DECL ERROR (typeof_var)\n", var); return NULL; } +vx_IrType *vx_IrBlock_typeof_var(vx_IrBlock *block, vx_IrVar var) { + vx_IrBlock* root = vx_IrBlock_root(block); + if (root && root->is_root && root->as_root.vars[var].ll_type) { + return block->as_root.vars[var].ll_type; + } + + return typeofvar(root, var); +} + static size_t cost_lut[VX_IR_OP____END] = { [VX_IR_OP_IMM] = 1, [VX_IR_OP_FLATTEN_PLEASE] = 0, diff --git a/ir/builder.c b/ir/builder.c index 7e5f3ce..8f3a84f 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -103,6 +103,10 @@ static void root_block_put_var(vx_IrBlock *root, vx_IrVar var, vx_IrOp *decl) { root->as_root.vars[var].decl = decl; } +void vx_IrBlock_putVar(vx_IrBlock *root, vx_IrVar var, vx_IrOp *decl) { + root_block_put_var(root, var, decl); +} + static void root_block_put_label(vx_IrBlock *root, size_t label, vx_IrOp *decl) { assert(root->is_root); if (label >= root->as_root.labels_len) { diff --git a/ir/ir.c b/ir/ir.c index 3088e6d..82dee8a 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -30,6 +30,7 @@ void vx_IrBlock_llir_compact(vx_IrBlock *root) { } } +/* typedef struct { vx_IrVar var; vx_IrOp* decl; @@ -45,9 +46,25 @@ bool vx_CIrBlock_fix_iter(vx_IrOp* op, void* param) { } } return false; +}*/ + +void vx_CIrBlock_fix(vx_IrBlock* block) { + vx_IrBlock* root = vx_IrBlock_root(block); + + for (size_t i = 0; i < block->ins_len; i ++) + vx_IrBlock_putVar(root, block->ins[i].var, NULL); + + for (vx_IrOp* op = block->first; op; op = op->next) { + for (size_t i = 0; i < op->outs_len; i ++) + vx_IrBlock_putVar(root, op->outs[i].var, op); + + for (size_t i = 0; i < op->params_len; i ++) + if (op->params[i].val.type == VX_IR_VAL_BLOCK) + vx_CIrBlock_fix(op->params[i].val.block); + } } -void vx_CIrBlock_fix(vx_IrBlock *root) { +/*void vx_CIrBlock_fix(vx_IrBlock *root) { assert(root->is_root); for (vx_IrVar var = 0; var < root->as_root.vars_len; var ++) { @@ -59,7 +76,7 @@ void vx_CIrBlock_fix(vx_IrBlock *root) { root->as_root.vars[var].decl = state.decl; } -} +}*/ void vx_IrBlock_llir_fix_decl(vx_IrBlock *root) { assert(root->is_root); diff --git a/ir/ir.h b/ir/ir.h index a5bda13..32f74d7 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -287,6 +287,7 @@ void vx_IrBlock_swap_in_at(vx_IrBlock *block, size_t a, size_t b); void vx_IrBlock_swap_out_at(vx_IrBlock *block, size_t a, size_t b); void vx_IrBlock_remove_out_at(vx_IrBlock *block, size_t id); size_t vx_IrBlock_append_label_op(vx_IrBlock *block); +void vx_IrBlock_putVar(vx_IrBlock *root, vx_IrVar var, vx_IrOp *decl); static bool vx_IrBlock_empty(vx_IrBlock *block) { if (!block) diff --git a/ir/opt.c b/ir/opt.c index 3a56f50..95a3be2 100644 --- a/ir/opt.c +++ b/ir/opt.c @@ -26,6 +26,8 @@ static void opt_pre(vx_IrBlock *block) { } void opt(vx_IrBlock *block) { + assert(block != NULL); + for (vx_IrOp *op = block->first; op; op = op->next) for (size_t i = 0; i < op->params_len; i ++) if (op->params[i].val.type == VX_IR_VAL_BLOCK) @@ -37,20 +39,13 @@ void opt(vx_IrBlock *block) { vx_opt_reduce_if(block); } vx_opt_cmov(block); - opt_pre(block); - if (vx_g_optconfig.loop_simplify) { - vx_opt_reduce_loops(block); - vx_opt_loop_simplify(block); - } + //opt_pre(block); + //if (vx_g_optconfig.loop_simplify) { + // vx_opt_reduce_loops(block); + // vx_opt_loop_simplify(block); + //} - vx_opt_tailcall(block); - - for (vx_IrOp *op = block->first; op; op = op->next) { - if (op->id == VX_IR_OP_FLATTEN_PLEASE) { - vx_IrBlock *body = vx_IrOp_param(op, VX_IR_NAME_BLOCK)->block; - opt(body); - } - } + //vx_opt_tailcall(block); } void opt_ll(vx_IrBlock *block) { diff --git a/ir/opt/cmov.c b/ir/opt/cmov.c index a5704bc..87d9dd4 100644 --- a/ir/opt/cmov.c +++ b/ir/opt/cmov.c @@ -1,11 +1,12 @@ #include "../opt.h" static vx_IrVar block_res_as_var(vx_IrBlock *parent, vx_IrBlock *block) { + vx_IrBlock* root = vx_IrBlock_root(parent); vx_IrOp *op = vx_IrBlock_add_op_building(parent); vx_IrOp_init(op, VX_IR_OP_FLATTEN_PLEASE, parent); vx_IrVar dest = vx_IrBlock_new_var(parent, op); vx_IrOp_add_param_s(op, VX_IR_NAME_BLOCK, (vx_IrValue) { .type = VX_IR_VAL_BLOCK, .block = block }); - vx_IrOp_add_out(op, dest, vx_IrBlock_typeof_var(block, block->outs[0])); + vx_IrOp_add_out(op, dest, vx_IrBlock_typeof_var(root, block->outs[0])); return dest; } @@ -27,6 +28,7 @@ static vx_IrVar block_res_as_var(vx_IrBlock *parent, vx_IrBlock *block) { void vx_opt_cmov(vx_IrBlock *block) { + vx_IrBlock* root = vx_IrBlock_root(block); for (vx_IrOp *op = block->first; op; op = op->next) { if (op->id != VX_IR_OP_IF) continue; @@ -42,20 +44,24 @@ void vx_opt_cmov(vx_IrBlock *block) if (!pelse) continue; + assert(pthen->type == VX_IR_VAL_BLOCK); vx_IrBlock *then = pthen->block; if (vx_IrBlock_is_volatile(then)) continue; + assert(pelse->type == VX_IR_VAL_BLOCK); vx_IrBlock *els = pelse->block; if (vx_IrBlock_is_volatile(els)) continue; size_t total_cost = vx_IrBlock_inline_cost(then) + vx_IrBlock_inline_cost(els); + printf("cmov inline cost %zu\n", total_cost); if (total_cost > vx_g_optconfig.max_total_cmov_inline_cost) continue; - vx_IrBlock *cond = vx_IrOp_param(op, VX_IR_NAME_COND)->block; - + vx_IrValue condv = *vx_IrOp_param(op, VX_IR_NAME_COND); + assert(condv.type == VX_IR_VAL_BLOCK); + vx_IrBlock *cond = condv.block; vx_IrBlock *body = vx_IrBlock_init_heap(block, op); @@ -68,7 +74,7 @@ void vx_opt_cmov(vx_IrBlock *block) vx_IrOp_add_param_s(cmov, VX_IR_NAME_COND, (vx_IrValue) { .type = VX_IR_VAL_BLOCK, .block = cond }); vx_IrOp_add_param_s(cmov, VX_IR_NAME_COND_THEN, (vx_IrValue) { .type = VX_IR_VAL_VAR, .var = v0 }); vx_IrOp_add_param_s(cmov, VX_IR_NAME_COND_ELSE, (vx_IrValue) { .type = VX_IR_VAL_VAR, .var = v1 }); - vx_IrOp_add_out(cmov, dest, vx_IrBlock_typeof_var(then, then->outs[0])); + vx_IrOp_add_out(cmov, dest, vx_IrBlock_typeof_var(root, then->outs[0])); vx_IrBlock_add_out(body, dest); diff --git a/ir/transform/single_assign_conditional.c b/ir/transform/single_assign_conditional.c index 33a72e3..b791d07 100644 --- a/ir/transform/single_assign_conditional.c +++ b/ir/transform/single_assign_conditional.c @@ -57,7 +57,6 @@ static vx_IrVar megic(vx_IrBlock *outer, { // stage 1 const vx_IrVar manipulate = vx_IrBlock_new_var(outer, ifOp); - printf("var: %zu\nmanipulate: %zu\n", var, manipulate); { vx_IrOp *oldstart = outer->first; outer->first = orig_assign->next; @@ -152,7 +151,7 @@ vx_OptIrVar vx_CIrBlock_mksa_states(vx_IrBlock *block) for (size_t l = 0; l < condAssignOp->outs_len; l ++) { vx_IrVar var = condAssignOp->outs[l].var; - vx_IrOp *alwaysAssignOp = vx_IrBlock_vardecl_out_before(block, var, condAssignOp); + vx_IrOp *alwaysAssignOp = vx_IrBlock_vardecl_out_before(block, var, ifOp); if (alwaysAssignOp == NULL) continue; rvar = VX_IRVAR_OPT_SOME(megic(alwaysAssignOp->parent, alwaysAssignOp, conditional, condAssignOp, ifOp, var, manip)); diff --git a/test.c b/test.c index 39d2083..5432c48 100644 --- a/test.c +++ b/test.c @@ -108,7 +108,7 @@ static vx_IrBlock * build_test_cmov(void) { vx_IrBlock_add_op(block, &op); } - vx_IrBlock_make_root(block, 1); + vx_IrBlock_make_root(block, 2); return block; } @@ -177,9 +177,9 @@ static int cir_test(vx_IrBlock *block) { if (vx_cir_verify(block) != 0) return 1; - vx_CIrBlock_mksa_states(block); - // vx_CIrBlock_mksa_final(block); vx_CIrBlock_fix(block); // TODO: why... + vx_CIrBlock_mksa_states(block); + vx_CIrBlock_mksa_final(block); printf("After C IR lower:\n"); vx_IrBlock_dump(block, stdout, 0); @@ -227,6 +227,8 @@ static int cir_test(vx_IrBlock *block) { } int main(void) { + vx_g_optconfig.if_eval = false; + ty_int = vx_IrType_heap(); ty_int->debugName = "i32"; ty_int->kind = VX_IR_TYPE_KIND_BASE;