mirror of
https://github.com/danog/ir.git
synced 2024-11-26 20:34:53 +01:00
Ceanup ir_compute_live_ranges() implementation
This commit is contained in:
parent
5c2023fd7f
commit
d3640495a2
@ -453,7 +453,10 @@ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constrain
|
|||||||
break;
|
break;
|
||||||
case IR_PI:
|
case IR_PI:
|
||||||
case IR_PHI:
|
case IR_PHI:
|
||||||
|
flags = IR_USE_SHOULD_BE_IN_REG;
|
||||||
|
break;
|
||||||
case IR_RLOAD:
|
case IR_RLOAD:
|
||||||
|
constraints->def_reg = ctx->ir_base[ref].op2;
|
||||||
flags = IR_USE_SHOULD_BE_IN_REG;
|
flags = IR_USE_SHOULD_BE_IN_REG;
|
||||||
break;
|
break;
|
||||||
case IR_EXITCALL:
|
case IR_EXITCALL:
|
||||||
|
198
ir_ra.c
198
ir_ra.c
@ -702,30 +702,16 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
if (v) {
|
if (v) {
|
||||||
IR_ASSERT(ir_bitset_in(live, v));
|
IR_ASSERT(ir_bitset_in(live, v));
|
||||||
|
|
||||||
if (insn->op == IR_RLOAD) {
|
if (insn->op != IR_PHI) {
|
||||||
/* live.remove(opd) */
|
|
||||||
ir_bitset_excl(live, v);
|
|
||||||
ival = ir_fix_live_range(ctx, v,
|
|
||||||
IR_START_LIVE_POS_FROM_REF(bb->start), IR_DEF_LIVE_POS_FROM_REF(ref));
|
|
||||||
ival->type = insn->type;
|
|
||||||
/* Fixed RLOADs are handled without live-ranges */
|
|
||||||
IR_ASSERT(!IR_REGSET_IN(IR_REGSET_UNION(ctx->fixed_regset, IR_REGSET_FIXED), insn->op2));
|
|
||||||
ir_add_use(ctx, ival, 0, IR_DEF_LIVE_POS_FROM_REF(ref), insn->op2, IR_USE_SHOULD_BE_IN_REG, 0);
|
|
||||||
continue;
|
|
||||||
} else if (insn->op != IR_PHI) {
|
|
||||||
ir_live_pos def_pos;
|
ir_live_pos def_pos;
|
||||||
ir_ref hint_ref = 0;
|
ir_ref hint_ref = 0;
|
||||||
ir_reg reg = constraints.def_reg;
|
ir_reg reg = constraints.def_reg;
|
||||||
|
|
||||||
if (reg != IR_REG_NONE) {
|
if (reg != IR_REG_NONE) {
|
||||||
def_pos = IR_SAVE_LIVE_POS_FROM_REF(ref);
|
def_pos = IR_SAVE_LIVE_POS_FROM_REF(ref);
|
||||||
if (insn->op == IR_PARAM) {
|
if (insn->op == IR_PARAM || insn->op == IR_RLOAD) {
|
||||||
/* parameter register must be kept before it's copied */
|
/* parameter register must be kept before it's copied */
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
ir_add_fixed_live_range(ctx, reg, IR_START_LIVE_POS_FROM_REF(bb->start), def_pos);
|
||||||
IR_START_LIVE_POS_FROM_REF(bb->start), def_pos);
|
|
||||||
} else {
|
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
|
||||||
IR_DEF_LIVE_POS_FROM_REF(ref), def_pos);
|
|
||||||
}
|
}
|
||||||
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
|
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
|
||||||
if (!IR_IS_CONST_REF(insn->op1) && ctx->vregs[insn->op1]) {
|
if (!IR_IS_CONST_REF(insn->op1) && ctx->vregs[insn->op1]) {
|
||||||
@ -773,57 +759,48 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
}
|
}
|
||||||
for (; j <= n; j++, p++) {
|
for (; j <= n; j++, p++) {
|
||||||
ir_ref input = *p;
|
ir_ref input = *p;
|
||||||
uint8_t use_flags = IR_USE_FLAGS(def_flags, j);
|
|
||||||
ir_reg reg = (j < constraints.hints_count) ? constraints.hints[j] : IR_REG_NONE;
|
ir_reg reg = (j < constraints.hints_count) ? constraints.hints[j] : IR_REG_NONE;
|
||||||
|
ir_live_pos use_pos;
|
||||||
|
ir_ref hint_ref = 0;
|
||||||
|
uint32_t v;
|
||||||
|
|
||||||
if (input > 0 && ctx->vregs[input]) {
|
if (input > 0) {
|
||||||
ir_live_pos use_pos;
|
v = ctx->vregs[input];
|
||||||
ir_ref hint_ref = 0;
|
if (v) {
|
||||||
|
use_pos = IR_USE_LIVE_POS_FROM_REF(ref);
|
||||||
if ((def_flags & IR_DEF_REUSES_OP1_REG) && j == 1) {
|
|
||||||
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
|
||||||
IR_ASSERT(ctx->vregs[ref]);
|
|
||||||
hint_ref = ref;
|
|
||||||
if (reg != IR_REG_NONE) {
|
if (reg != IR_REG_NONE) {
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
use_pos, IR_USE_LIVE_POS_FROM_REF(ref));
|
ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF);
|
||||||
|
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
|
||||||
|
if (j == 1) {
|
||||||
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
|
IR_ASSERT(ctx->vregs[ref]);
|
||||||
|
hint_ref = ref;
|
||||||
|
} else if (input == insn->op1) {
|
||||||
|
/* Input is the same as "op1" */
|
||||||
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (!ir_bitset_in(live, v)) {
|
||||||
if (reg != IR_REG_NONE) {
|
/* live.add(opd) */
|
||||||
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
ir_bitset_incl(live, v);
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
/* intervals[opd].addRange(b.from, op.id) */
|
||||||
use_pos, IR_USE_LIVE_POS_FROM_REF(ref));
|
ival = ir_add_live_range(ctx, v, IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
|
||||||
} else if ((def_flags & IR_DEF_REUSES_OP1_REG) && input == insn->op1) {
|
|
||||||
/* Input is the same as "op1" */
|
|
||||||
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
|
||||||
} else {
|
} else {
|
||||||
use_pos = IR_USE_LIVE_POS_FROM_REF(ref);
|
ival = ctx->live_intervals[v];
|
||||||
|
}
|
||||||
|
ir_add_use(ctx, ival, j, use_pos, reg, IR_USE_FLAGS(def_flags, j), hint_ref);
|
||||||
|
} else {
|
||||||
|
IR_ASSERT(ctx->rules);
|
||||||
|
if (ctx->rules[input] & IR_FUSED) {
|
||||||
|
ir_add_fusion_ranges(ctx, ref, input, bb, live);
|
||||||
|
} else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) {
|
||||||
|
ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (reg != IR_REG_NONE) {
|
||||||
uint32_t v = ctx->vregs[input];
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
if (!ir_bitset_in(live, v)) {
|
ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF);
|
||||||
/* live.add(opd) */
|
|
||||||
ir_bitset_incl(live, v);
|
|
||||||
/* intervals[opd].addRange(b.from, op.id) */
|
|
||||||
ival = ir_add_live_range(ctx, v,
|
|
||||||
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
|
|
||||||
} else {
|
|
||||||
ival = ctx->live_intervals[v];
|
|
||||||
}
|
|
||||||
ir_add_use(ctx, ival, j, use_pos, reg, use_flags, hint_ref);
|
|
||||||
} else if (input > 0) {
|
|
||||||
IR_ASSERT(ctx->rules);
|
|
||||||
if (ctx->rules[input] & IR_FUSED) {
|
|
||||||
ir_add_fusion_ranges(ctx, ref, input, bb, live);
|
|
||||||
} else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) {
|
|
||||||
ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (reg != IR_REG_NONE) {
|
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
|
||||||
IR_LOAD_LIVE_POS_FROM_REF(ref), IR_USE_LIVE_POS_FROM_REF(ref));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1325,30 +1302,17 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
insn = &ctx->ir_base[ref];
|
insn = &ctx->ir_base[ref];
|
||||||
v = ctx->vregs[ref];
|
v = ctx->vregs[ref];
|
||||||
if (v) {
|
if (v) {
|
||||||
if (insn->op == IR_RLOAD) {
|
if (insn->op != IR_PHI) {
|
||||||
ival = ir_fix_live_range(ctx, v,
|
|
||||||
IR_START_LIVE_POS_FROM_REF(bb->start), IR_DEF_LIVE_POS_FROM_REF(ref));
|
|
||||||
ival->type = insn->type;
|
|
||||||
/* Fixed RLOADs are handled without live-ranges */
|
|
||||||
IR_ASSERT(!IR_REGSET_IN(IR_REGSET_UNION(ctx->fixed_regset, IR_REGSET_FIXED), insn->op2));
|
|
||||||
ir_add_use(ctx, ival, 0, IR_DEF_LIVE_POS_FROM_REF(ref), insn->op2, IR_USE_SHOULD_BE_IN_REG, 0);
|
|
||||||
continue;
|
|
||||||
} else if (insn->op != IR_PHI) {
|
|
||||||
ir_live_pos def_pos;
|
ir_live_pos def_pos;
|
||||||
ir_ref hint_ref = 0;
|
ir_ref hint_ref = 0;
|
||||||
ir_reg reg = constraints.def_reg;
|
ir_reg reg = constraints.def_reg;
|
||||||
|
|
||||||
if (reg != IR_REG_NONE) {
|
if (reg != IR_REG_NONE) {
|
||||||
ir_live_pos start_pos;
|
|
||||||
|
|
||||||
def_pos = IR_SAVE_LIVE_POS_FROM_REF(ref);
|
def_pos = IR_SAVE_LIVE_POS_FROM_REF(ref);
|
||||||
if (insn->op == IR_PARAM) {
|
if (insn->op == IR_PARAM || insn->op == IR_RLOAD) {
|
||||||
/* parameter register must be kept before it's copied */
|
/* parameter register must be kept before it's copied */
|
||||||
start_pos = IR_START_LIVE_POS_FROM_REF(bb->start);
|
ir_add_fixed_live_range(ctx, reg, IR_START_LIVE_POS_FROM_REF(bb->start), def_pos);
|
||||||
} else {
|
|
||||||
start_pos = IR_DEF_LIVE_POS_FROM_REF(ref);
|
|
||||||
}
|
}
|
||||||
ir_add_fixed_live_range(ctx, reg, start_pos, def_pos);
|
|
||||||
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
|
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
|
||||||
if (!IR_IS_CONST_REF(insn->op1) && ctx->vregs[insn->op1]) {
|
if (!IR_IS_CONST_REF(insn->op1) && ctx->vregs[insn->op1]) {
|
||||||
hint_ref = insn->op1;
|
hint_ref = insn->op1;
|
||||||
@ -1392,57 +1356,47 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
for (; j <= n; j++, p++) {
|
for (; j <= n; j++, p++) {
|
||||||
ir_ref input = *p;
|
ir_ref input = *p;
|
||||||
ir_reg reg = (j < constraints.hints_count) ? constraints.hints[j] : IR_REG_NONE;
|
ir_reg reg = (j < constraints.hints_count) ? constraints.hints[j] : IR_REG_NONE;
|
||||||
|
ir_live_pos use_pos;
|
||||||
|
ir_ref hint_ref = 0;
|
||||||
|
uint32_t v;
|
||||||
|
|
||||||
if (input > 0 && ctx->vregs[input]) {
|
if (input > 0) {
|
||||||
ir_live_pos use_pos;
|
v = ctx->vregs[input];
|
||||||
ir_ref hint_ref = 0;
|
if (v) {
|
||||||
|
use_pos = IR_USE_LIVE_POS_FROM_REF(ref);
|
||||||
if ((def_flags & IR_DEF_REUSES_OP1_REG) && j == 1) {
|
|
||||||
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
|
||||||
IR_ASSERT(ctx->vregs[ref]);
|
|
||||||
hint_ref = ref;
|
|
||||||
if (reg != IR_REG_NONE) {
|
if (reg != IR_REG_NONE) {
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
use_pos, IR_USE_LIVE_POS_FROM_REF(ref));
|
ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF);
|
||||||
|
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
|
||||||
|
if (j == 1) {
|
||||||
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
|
IR_ASSERT(ctx->vregs[ref]);
|
||||||
|
hint_ref = ref;
|
||||||
|
} else if (input == insn->op1) {
|
||||||
|
/* Input is the same as "op1" */
|
||||||
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (!IS_LIVE_IN_BLOCK(v, b)) {
|
||||||
if (reg != IR_REG_NONE) {
|
/* live.add(opd) */
|
||||||
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
SET_LIVE_IN_BLOCK(v, b);
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
/* intervals[opd].addRange(b.from, op.id) */
|
||||||
use_pos, IR_USE_LIVE_POS_FROM_REF(ref));
|
ival = ir_add_live_range(ctx, v, IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
|
||||||
} else if ((def_flags & IR_DEF_REUSES_OP1_REG) && input == insn->op1) {
|
|
||||||
/* Input is the same as "op1" */
|
|
||||||
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
|
||||||
} else {
|
} else {
|
||||||
use_pos = IR_USE_LIVE_POS_FROM_REF(ref);
|
ival = ctx->live_intervals[v];
|
||||||
|
}
|
||||||
|
ir_add_use(ctx, ival, j, use_pos, reg, IR_USE_FLAGS(def_flags, j), hint_ref);
|
||||||
|
} else {
|
||||||
|
IR_ASSERT(ctx->rules);
|
||||||
|
if (ctx->rules[input] & IR_FUSED) {
|
||||||
|
ir_add_fusion_ranges(ctx, ref, input, bb, live_in_block, b);
|
||||||
|
} else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) {
|
||||||
|
ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (reg != IR_REG_NONE) {
|
||||||
uint32_t v = ctx->vregs[input];
|
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
|
||||||
if (!IS_LIVE_IN_BLOCK(v, b)) {
|
ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF);
|
||||||
/* live.add(opd) */
|
|
||||||
SET_LIVE_IN_BLOCK(v, b);
|
|
||||||
/* intervals[opd].addRange(b.from, op.id) */
|
|
||||||
ival = ir_add_live_range(ctx, v,
|
|
||||||
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
|
|
||||||
} else {
|
|
||||||
ival = ctx->live_intervals[v];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t use_flags = IR_USE_FLAGS(def_flags, j);
|
|
||||||
ir_add_use(ctx, ival, j, use_pos, reg, use_flags, hint_ref);
|
|
||||||
} else if (input > 0) {
|
|
||||||
IR_ASSERT(ctx->rules);
|
|
||||||
if (ctx->rules[input] & IR_FUSED) {
|
|
||||||
ir_add_fusion_ranges(ctx, ref, input, bb, live_in_block, b);
|
|
||||||
} else if (ctx->rules[input] == (IR_SKIPPED|IR_RLOAD)) {
|
|
||||||
ir_set_alocated_reg(ctx, ref, j, ctx->ir_base[input].op2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (reg != IR_REG_NONE) {
|
|
||||||
ir_add_fixed_live_range(ctx, reg,
|
|
||||||
IR_LOAD_LIVE_POS_FROM_REF(ref), IR_USE_LIVE_POS_FROM_REF(ref));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
ir_x86.dasc
11
ir_x86.dasc
@ -567,7 +567,8 @@ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constrain
|
|||||||
constraints->hints_count = 2;
|
constraints->hints_count = 2;
|
||||||
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
|
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
|
||||||
constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RDX, IR_USE_SUB_REF, IR_DEF_SUB_REF);
|
constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RDX, IR_USE_SUB_REF, IR_DEF_SUB_REF);
|
||||||
n = 1;
|
constraints->tmp_regs[1] = IR_SCRATCH_REG(IR_REG_RAX, IR_LOAD_SUB_REF, IR_LOAD_SUB_REF);
|
||||||
|
n = 2;
|
||||||
break;
|
break;
|
||||||
case IR_DIV_INT:
|
case IR_DIV_INT:
|
||||||
/* %rax - used as input and result */
|
/* %rax - used as input and result */
|
||||||
@ -576,7 +577,8 @@ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constrain
|
|||||||
constraints->hints_count = 2;
|
constraints->hints_count = 2;
|
||||||
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
|
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
|
||||||
constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RDX, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RDX, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
||||||
n = 1;
|
constraints->tmp_regs[1] = IR_SCRATCH_REG(IR_REG_RAX, IR_LOAD_SUB_REF, IR_SAVE_SUB_REF);
|
||||||
|
n = 2;
|
||||||
goto op2_const;
|
goto op2_const;
|
||||||
case IR_MOD_INT:
|
case IR_MOD_INT:
|
||||||
constraints->def_reg = IR_REG_RDX;
|
constraints->def_reg = IR_REG_RDX;
|
||||||
@ -584,7 +586,7 @@ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constrain
|
|||||||
constraints->hints_count = 2;
|
constraints->hints_count = 2;
|
||||||
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
|
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
|
||||||
constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RAX, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
constraints->tmp_regs[0] = IR_SCRATCH_REG(IR_REG_RAX, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
||||||
constraints->tmp_regs[1] = IR_SCRATCH_REG(IR_REG_RDX, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
constraints->tmp_regs[1] = IR_SCRATCH_REG(IR_REG_RDX, IR_LOAD_SUB_REF, IR_SAVE_SUB_REF);
|
||||||
n = 2;
|
n = 2;
|
||||||
goto op2_const;
|
goto op2_const;
|
||||||
case IR_MIN_MAX_INT:
|
case IR_MIN_MAX_INT:
|
||||||
@ -775,7 +777,10 @@ op2_const:
|
|||||||
break;
|
break;
|
||||||
case IR_PI:
|
case IR_PI:
|
||||||
case IR_PHI:
|
case IR_PHI:
|
||||||
|
flags = IR_USE_SHOULD_BE_IN_REG;
|
||||||
|
break;
|
||||||
case IR_RLOAD:
|
case IR_RLOAD:
|
||||||
|
constraints->def_reg = ctx->ir_base[ref].op2;
|
||||||
flags = IR_USE_SHOULD_BE_IN_REG;
|
flags = IR_USE_SHOULD_BE_IN_REG;
|
||||||
break;
|
break;
|
||||||
case IR_EXITCALL:
|
case IR_EXITCALL:
|
||||||
|
Loading…
Reference in New Issue
Block a user