Cleanup spill related code

This commit is contained in:
Dmitry Stogov 2023-06-21 23:20:58 +03:00
parent d67c212916
commit 99bcde9e1e
2 changed files with 42 additions and 46 deletions

View File

@ -873,6 +873,13 @@ static int32_t ir_ref_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
return IR_SPILL_POS_TO_OFFSET(offset); return IR_SPILL_POS_TO_OFFSET(offset);
} }
static bool ir_is_same_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg reg, int32_t offset)
{
ir_reg fp;
return ir_ref_spill_slot(ctx, ref, &fp) == offset && reg == fp;
}
static int32_t ir_var_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg) static int32_t ir_var_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
{ {
ir_insn *var_insn = &ctx->ir_base[ref]; ir_insn *var_insn = &ctx->ir_base[ref];
@ -2929,12 +2936,10 @@ static void ir_emit_load_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg); int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
if (op2_reg == IR_REG_NONE) { if (op2_reg == IR_REG_NONE) {
if (IR_REG_SPILLED(ctx->regs[def][0])) { if (IR_REG_SPILLED(ctx->regs[def][0]) && ir_is_same_spill_slot(ctx, def, op1_reg, offset)) {
ir_reg fp; /* avoid load to the same location (valid only when register is not reused) */
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op1_reg == fp) {
return; return;
} }
}
ir_emit_load_mem_int(ctx, type, def_reg, op1_reg, offset); ir_emit_load_mem_int(ctx, type, def_reg, op1_reg, offset);
} else { } else {
switch (ir_type_size[type]) { switch (ir_type_size[type]) {
@ -2996,12 +3001,10 @@ static void ir_emit_load_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg); int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
if (op2_reg == IR_REG_NONE) { if (op2_reg == IR_REG_NONE) {
if (IR_REG_SPILLED(ctx->regs[def][0])) { if (IR_REG_SPILLED(ctx->regs[def][0]) && ir_is_same_spill_slot(ctx, def, op1_reg, offset)) {
ir_reg fp; /* avoid load to the same location (valid only when register is not reused) */
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op1_reg == fp) {
return; return;
} }
}
ir_emit_load_mem_fp(ctx, type, def_reg, op1_reg, offset); ir_emit_load_mem_fp(ctx, type, def_reg, op1_reg, offset);
} else { } else {
if (type == IR_DOUBLE) { if (type == IR_DOUBLE) {
@ -3042,12 +3045,10 @@ static void ir_emit_store_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg); int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
if (op2_reg == IR_REG_NONE) { if (op2_reg == IR_REG_NONE) {
if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg)) { if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg) && ir_is_same_spill_slot(ctx, insn->op3, op1_reg, offset)) {
ir_reg fp; /* avoid store to the same location */
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op1_reg == fp) {
return; return;
} }
}
if (op3_reg == IR_REG_NONE) { if (op3_reg == IR_REG_NONE) {
IR_ASSERT(IR_IS_CONST_REF(insn->op3) && ctx->ir_base[insn->op3].val.i64 == 0); IR_ASSERT(IR_IS_CONST_REF(insn->op3) && ctx->ir_base[insn->op3].val.i64 == 0);
op3_reg = IR_REG_ZR; op3_reg = IR_REG_ZR;
@ -3113,12 +3114,10 @@ static void ir_emit_store_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg); int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
if (op2_reg == IR_REG_NONE) { if (op2_reg == IR_REG_NONE) {
if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg)) { if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg) && ir_is_same_spill_slot(ctx, insn->op3, op1_reg, offset)) {
ir_reg fp; /* avoid store to the same location */
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op1_reg == fp) {
return; return;
} }
}
if (IR_REG_SPILLED(op3_reg) || IR_IS_CONST_REF(insn->op3)) { if (IR_REG_SPILLED(op3_reg) || IR_IS_CONST_REF(insn->op3)) {
op3_reg = IR_REG_NUM(op3_reg); op3_reg = IR_REG_NUM(op3_reg);
ir_emit_load(ctx, type, op3_reg, insn->op3); ir_emit_load(ctx, type, op3_reg, insn->op3);
@ -3154,7 +3153,6 @@ static void ir_emit_rload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
{ {
ir_reg src_reg = insn->op2; ir_reg src_reg = insn->op2;
ir_type type = insn->type; ir_type type = insn->type;
ir_reg fp;
if (IR_REGSET_IN(IR_REGSET_UNION((ir_regset)ctx->fixed_regset, IR_REGSET_FIXED), src_reg)) { if (IR_REGSET_IN(IR_REGSET_UNION((ir_regset)ctx->fixed_regset, IR_REGSET_FIXED), src_reg)) {
if (ctx->vregs[def] if (ctx->vregs[def]
@ -3169,7 +3167,7 @@ static void ir_emit_rload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
/* op3 is used as a flag that the value is already stored in memory. /* op3 is used as a flag that the value is already stored in memory.
* If op3 is set we don't have to store the value once again (in case of spilling) * If op3 is set we don't have to store the value once again (in case of spilling)
*/ */
if (!insn->op3 || insn->op3 != ir_ref_spill_slot(ctx, def, &fp) || fp != ctx->spill_base) { if (!insn->op3 || !ir_is_same_spill_slot(ctx, def, ctx->spill_base, insn->op3)) {
ir_emit_store(ctx, type, def, src_reg); ir_emit_store(ctx, type, def, src_reg);
} }
} else { } else {
@ -3182,7 +3180,7 @@ static void ir_emit_rload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
} }
} }
if (IR_REG_SPILLED(ctx->regs[def][0]) if (IR_REG_SPILLED(ctx->regs[def][0])
&& (!insn->op3 || insn->op3 != ir_ref_spill_slot(ctx, def, &fp) || fp != ctx->spill_base)) { && (!insn->op3 || !ir_is_same_spill_slot(ctx, def, ctx->spill_base, insn->op3))) {
ir_emit_store(ctx, type, def, def_reg); ir_emit_store(ctx, type, def, def_reg);
} }
} }

View File

@ -1899,6 +1899,13 @@ static int32_t ir_ref_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
return IR_SPILL_POS_TO_OFFSET(offset); return IR_SPILL_POS_TO_OFFSET(offset);
} }
static bool ir_is_same_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg reg, int32_t offset)
{
ir_reg fp;
return ir_ref_spill_slot(ctx, ref, &fp) == offset && reg == fp;
}
static int32_t ir_var_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg) static int32_t ir_var_spill_slot(ir_ctx *ctx, ir_ref ref, ir_reg *reg)
{ {
ir_insn *var_insn = &ctx->ir_base[ref]; ir_insn *var_insn = &ctx->ir_base[ref];
@ -5303,12 +5310,10 @@ static void ir_emit_load_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
} }
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) { if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg); offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
if (IR_REG_SPILLED(ctx->regs[def][0])) { if (IR_REG_SPILLED(ctx->regs[def][0]) && ir_is_same_spill_slot(ctx, def, op2_reg, offset)) {
ir_reg fp; /* avoid load to the same location (valid only when register is not reused) */
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op2_reg == fp) {
return; return;
} }
}
} else if (IR_REG_SPILLED(op2_reg) || IR_IS_CONST_REF(insn->op2)) { } else if (IR_REG_SPILLED(op2_reg) || IR_IS_CONST_REF(insn->op2)) {
op2_reg = IR_REG_NUM(op2_reg); op2_reg = IR_REG_NUM(op2_reg);
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR); IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
@ -5350,12 +5355,10 @@ static void ir_emit_load_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
} }
} else if (op2_reg == IR_REG_NONE) { } else if (op2_reg == IR_REG_NONE) {
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg); offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
if (IR_REG_SPILLED(ctx->regs[def][0])) { if (IR_REG_SPILLED(ctx->regs[def][0]) && ir_is_same_spill_slot(ctx, def, op2_reg, offset)) {
ir_reg fp; /* avoid load to the same location (valid only when register is not reused) */
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op2_reg == fp) {
return; return;
} }
}
} else if (IR_REG_SPILLED(op2_reg)) { } else if (IR_REG_SPILLED(op2_reg)) {
op2_reg = IR_REG_NUM(op2_reg); op2_reg = IR_REG_NUM(op2_reg);
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR); IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
@ -5400,12 +5403,10 @@ static void ir_emit_store_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
} }
} else if (op2_reg == IR_REG_NONE) { } else if (op2_reg == IR_REG_NONE) {
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg); offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg)) { if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg) && ir_is_same_spill_slot(ctx, insn->op3, op2_reg, offset)) {
ir_reg fp; /* avoid store to the same location */
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op2_reg == fp) {
return; return;
} }
}
} else if (IR_REG_SPILLED(op2_reg)) { } else if (IR_REG_SPILLED(op2_reg)) {
op2_reg = IR_REG_NUM(op2_reg); op2_reg = IR_REG_NUM(op2_reg);
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR); IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
@ -5450,12 +5451,10 @@ static void ir_emit_store_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
} }
} else if (op2_reg == IR_REG_NONE) { } else if (op2_reg == IR_REG_NONE) {
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg); offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg)) { if (!IR_IS_CONST_REF(insn->op3) && IR_REG_SPILLED(op3_reg) && ir_is_same_spill_slot(ctx, insn->op3, op2_reg, offset)) {
ir_reg fp; /* avoid store to the same location */
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op2_reg == fp) {
return; return;
} }
}
} else if (IR_REG_SPILLED(op2_reg)) { } else if (IR_REG_SPILLED(op2_reg)) {
op2_reg = IR_REG_NUM(op2_reg); op2_reg = IR_REG_NUM(op2_reg);
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR); IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
@ -5473,7 +5472,6 @@ static void ir_emit_rload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
{ {
ir_reg src_reg = insn->op2; ir_reg src_reg = insn->op2;
ir_type type = insn->type; ir_type type = insn->type;
ir_reg fp;
if (IR_REGSET_IN(IR_REGSET_UNION((ir_regset)ctx->fixed_regset, IR_REGSET_FIXED), src_reg)) { if (IR_REGSET_IN(IR_REGSET_UNION((ir_regset)ctx->fixed_regset, IR_REGSET_FIXED), src_reg)) {
if (ctx->vregs[def] if (ctx->vregs[def]
@ -5488,7 +5486,7 @@ static void ir_emit_rload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
/* op3 is used as a flag that the value is already stored in memory. /* op3 is used as a flag that the value is already stored in memory.
* If op3 is set we don't have to store the value once again (in case of spilling) * If op3 is set we don't have to store the value once again (in case of spilling)
*/ */
if (!insn->op3 || insn->op3 != ir_ref_spill_slot(ctx, def, &fp) || fp != ctx->spill_base) { if (!insn->op3 || !ir_is_same_spill_slot(ctx, def, ctx->spill_base, insn->op3)) {
ir_emit_store(ctx, type, def, src_reg); ir_emit_store(ctx, type, def, src_reg);
} }
} else { } else {
@ -5501,7 +5499,7 @@ static void ir_emit_rload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
} }
} }
if (IR_REG_SPILLED(ctx->regs[def][0]) if (IR_REG_SPILLED(ctx->regs[def][0])
&& (!insn->op3 || insn->op3 != ir_ref_spill_slot(ctx, def, &fp) || fp != ctx->spill_base)) { && (!insn->op3 || !ir_is_same_spill_slot(ctx, def, ctx->spill_base, insn->op3))) {
ir_emit_store(ctx, type, def, def_reg); ir_emit_store(ctx, type, def, def_reg);
} }
} }