diff --git a/src/_debug/dump_ir.c b/src/_debug/dump_ir.c index a545a28a4..cec2c29df 100644 --- a/src/_debug/dump_ir.c +++ b/src/_debug/dump_ir.c @@ -169,8 +169,6 @@ static void dump_func_ir(Function *func) { case LI_SPILL: fprintf(fp, " V%3d (flag=%x): live %3d - %3d (spilled, offset=%d)\n", li->virt, vreg->flag, li->start, li->end, vreg->frame.offset); break; - case LI_CONST: - continue; } } } diff --git a/src/cc/backend/codegen.c b/src/cc/backend/codegen.c index c147798a5..446be875b 100644 --- a/src/cc/backend/codegen.c +++ b/src/cc/backend/codegen.c @@ -737,8 +737,8 @@ static void map_virtual_to_physical_registers(RegAlloc *ra) { VReg *vreg = ra->vregs->data[i]; if (vreg == NULL) continue; - if (!(vreg->flag & VRF_CONST)) - vreg->phys = ra->intervals[vreg->virt].phys; + assert(!(vreg->flag & VRF_CONST) && vreg->virt >= 0); + vreg->phys = ra->intervals[vreg->virt].phys; } } diff --git a/src/cc/backend/ir.c b/src/cc/backend/ir.c index 9a0b2aff4..9b31c43c1 100644 --- a/src/cc/backend/ir.c +++ b/src/cc/backend/ir.c @@ -35,9 +35,7 @@ static IR *new_ir(enum IrKind kind) { } VReg *new_const_vreg(int64_t value, enum VRegSize vsize, int vflag) { - VReg *vreg = reg_alloc_spawn(curra, vsize, vflag | VRF_CONST); - vreg->fixnum = value; - return vreg; + return reg_alloc_spawn_const(curra, value, vsize, vflag); } VReg *new_ir_bop(enum IrKind kind, VReg *opr1, VReg *opr2, enum VRegSize vsize) { diff --git a/src/cc/backend/optimize.c b/src/cc/backend/optimize.c index 7bac9a30e..2615a8ecc 100644 --- a/src/cc/backend/optimize.c +++ b/src/cc/backend/optimize.c @@ -155,7 +155,7 @@ static void remove_unused_vregs(RegAlloc *ra, BBContainer *bbcon) { VReg *operands[] = {ir->opr1, ir->opr2}; for (int k = 0; k < 2; ++k) { VReg *vreg = operands[k]; - if (vreg != NULL) + if (vreg != NULL && !(vreg->flag & VRF_CONST)) vreg_read[vreg->virt] = true; } } diff --git a/src/cc/backend/regalloc.c b/src/cc/backend/regalloc.c index 34d4864a3..899eb84f0 100644 --- a/src/cc/backend/regalloc.c +++ b/src/cc/backend/regalloc.c @@ -16,6 +16,7 @@ RegAlloc *new_reg_alloc(const RegAllocSettings *settings) { assert(settings->phys_max < (int)(sizeof(ra->used_reg_bits) * CHAR_BIT)); ra->settings = settings; ra->vregs = new_vector(); + ra->consts = new_vector(); ra->intervals = NULL; ra->sorted_intervals = NULL; ra->used_reg_bits = 0; @@ -24,19 +25,39 @@ RegAlloc *new_reg_alloc(const RegAllocSettings *settings) { return ra; } -VReg *reg_alloc_spawn(RegAlloc *ra, enum VRegSize vsize, int vflag) { - int vreg_no = ra->vregs->len; - +static VReg *alloc_vreg(enum VRegSize vsize, int vflag) { VReg *vreg = malloc_or_die(sizeof(*vreg)); - vreg->virt = vreg_no; + vreg->virt = -1; vreg->phys = -1; vreg->fixnum = 0; vreg->vsize = vsize; vreg->flag = vflag; vreg->reg_param_index = -1; vreg->frame.offset = 0; + return vreg; +} + +VReg *reg_alloc_spawn(RegAlloc *ra, enum VRegSize vsize, int vflag) { + VReg *vreg = alloc_vreg(vsize, vflag); + if (!(vflag & VRF_CONST)) { + vreg->virt = ra->vregs->len; + vec_push(ra->vregs, vreg); + } else { + vec_push(ra->consts, vreg); + } + return vreg; +} - vec_push(ra->vregs, vreg); +VReg *reg_alloc_spawn_const(RegAlloc *ra, int64_t value, enum VRegSize vsize, int vflag) { + vflag |= VRF_CONST; + for (int i = 0; i < ra->consts->len; ++i) { + VReg *v = ra->consts->data[i]; + if (v->fixnum == value && v->vsize == vsize && v->flag == vflag) + return v; + } + + VReg *vreg = reg_alloc_spawn(ra, vsize, vflag); + vreg->fixnum = value; return vreg; } @@ -385,20 +406,20 @@ static int insert_load_store_spilled_irs(RegAlloc *ra, BBContainer *bbcon) { continue; } - if (ir->opr1 != NULL && (flag & 1) != 0 && - !(ir->opr1->flag & VRF_CONST) && (ir->opr1->flag & VRF_SPILLED)) { + if (ir->opr1 != NULL && (flag & 1) != 0 && (ir->opr1->flag & VRF_SPILLED)) { + assert(!(ir->opr1->flag & VRF_CONST)); j = insert_tmp_reg(ra, irs, j, ir->opr1); ++inserted; } - if (ir->opr2 != NULL && (flag & 2) != 0 && - !(ir->opr2->flag & VRF_CONST) && (ir->opr2->flag & VRF_SPILLED)) { + if (ir->opr2 != NULL && (flag & 2) != 0 && (ir->opr2->flag & VRF_SPILLED)) { + assert(!(ir->opr2->flag & VRF_CONST)); j = insert_tmp_reg(ra, irs, j, ir->opr2); ++inserted; } - if (ir->dst != NULL && (flag & 4) != 0 && - !(ir->dst->flag & VRF_CONST) && (ir->dst->flag & VRF_SPILLED)) { + if (ir->dst != NULL && (flag & 4) != 0 && (ir->dst->flag & VRF_SPILLED)) { + assert(!(ir->dst->flag & VRF_CONST)); j = insert_tmp_reg(ra, irs, j, ir->dst); ++inserted; } @@ -424,10 +445,7 @@ void alloc_physical_registers(RegAlloc *ra, BBContainer *bbcon) { if (vreg == NULL) continue; - if (vreg->flag & VRF_CONST) { - li->state = LI_CONST; - continue; - } + assert(!(vreg->flag & VRF_CONST)); if (vreg->flag & VRF_SPILLED) { li->state = LI_SPILL; diff --git a/src/cc/backend/regalloc.h b/src/cc/backend/regalloc.h index 00924bd21..fd9cc04ae 100644 --- a/src/cc/backend/regalloc.h +++ b/src/cc/backend/regalloc.h @@ -16,7 +16,6 @@ typedef struct Vector Vector; enum LiveIntervalState { LI_NORMAL, LI_SPILL, - LI_CONST, }; typedef struct LiveInterval { @@ -41,7 +40,8 @@ typedef struct RegAllocSettings { typedef struct RegAlloc { const RegAllocSettings *settings; - Vector *vregs; // + Vector *vregs; // , non-const vregs + Vector *consts; // , const vregs LiveInterval *intervals; // size=vregs->len LiveInterval **sorted_intervals; @@ -52,4 +52,5 @@ typedef struct RegAlloc { RegAlloc *new_reg_alloc(const RegAllocSettings *settings); VReg *reg_alloc_spawn(RegAlloc *ra, enum VRegSize vsize, int vflag); +VReg *reg_alloc_spawn_const(RegAlloc *ra, int64_t value, enum VRegSize vsize, int vflag); void alloc_physical_registers(RegAlloc *ra, BBContainer *bbcon);