More accurate reslution of a register allocation conflict

This commit is contained in:
Dmitry Stogov 2023-06-28 16:17:21 +03:00
parent 1b88d998c8
commit b1e6ae66e3

34
ir_ra.c
View File

@ -2187,6 +2187,16 @@ static ir_live_pos ir_first_use_pos_after(ir_live_interval *ival, ir_live_pos po
return p ? p->pos : 0x7fffffff;
}
static ir_live_pos ir_first_use_pos(ir_live_interval *ival, uint8_t flags)
{
ir_use_pos *p = ival->use_pos;
while (p && !(p->flags & flags)) {
p = p->next;
}
return p ? p->pos : 0x7fffffff;
}
static ir_block *ir_block_from_live_pos(ir_ctx *ctx, ir_live_pos pos)
{
ir_ref ref = IR_LIVE_POS_TO_REF(pos);
@ -3012,6 +3022,7 @@ spill_current:
return IR_REG_NONE;
}
if (split_pos >= blockPos[reg]) {
try_next_available_register:
IR_REGSET_EXCL(available, reg);
if (IR_REGSET_IS_EMPTY(available)) {
fprintf(stderr, "LSRA Internal Error: Unsolvable conflict. Allocation is not possible\n");
@ -3052,13 +3063,22 @@ spill_current:
child = ir_split_interval_at(ctx, other, split_pos);
IR_LOG_LSRA(" ---- Finish", other, "");
} else {
if (ir_first_use_pos_after(other, other->range.start, IR_USE_MUST_BE_IN_REG) < other->end) {
if (next_use_pos > ival->range.start && !(ival->flags & IR_LIVE_INTERVAL_TEMP)) {
goto spill_current;
}
fprintf(stderr, "LSRA Internal Error: Unsolvable conflict. Allocation is not possible\n");
IR_ASSERT(0);
exit(-1);
if (ir_first_use_pos(other, IR_USE_MUST_BE_IN_REG) <= other->end) {
if (!(ival->flags & IR_LIVE_INTERVAL_TEMP)) {
next_use_pos = ir_first_use_pos(ival, IR_USE_MUST_BE_IN_REG);
if (next_use_pos == ival->range.start) {
IR_ASSERT(ival->use_pos && ival->use_pos->op_num == 0);
/* split right after definition */
split_pos = next_use_pos + 1;
} else {
split_pos = ir_find_optimal_split_position(ctx, ival, ival->range.start, next_use_pos - 1, 1);
}
if (split_pos > ival->range.start) {
goto spill_current;
}
}
goto try_next_available_register;
}
child = other;
other->reg = IR_REG_NONE;