diff --git a/ir_ra.c b/ir_ra.c index 2ebf8c9..d5d33da 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -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;