LSRA optimization

This commit is contained in:
Dmitry Stogov 2023-04-13 20:56:49 +03:00
parent e5c01495da
commit 2a17b87219
2 changed files with 65 additions and 55 deletions

View File

@ -1043,6 +1043,8 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy);
#if defined(IR_REGSET_64BIT)
typedef enum _ir_reg ir_reg;
/*** Register Sets ***/
#if IR_REGSET_64BIT
typedef uint64_t ir_regset;
@ -1100,13 +1102,21 @@ typedef uint32_t ir_regset;
# define IR_REGSET_LAST(set) ((ir_reg)(ir_nlz(set)^31))
#endif
IR_ALWAYS_INLINE ir_reg ir_regset_pop_first(ir_regset *set)
{
ir_reg reg;
IR_ASSERT(!IR_REGSET_IS_EMPTY(*set));
reg = IR_REGSET_FIRST(*set);
*set = (*set) & ((*set) - 1);
return reg;
}
#define IR_REGSET_FOREACH(set, reg) \
do { \
ir_regset _tmp = (set); \
while (!IR_REGSET_IS_EMPTY(_tmp)) { \
ir_reg _reg = IR_REGSET_FIRST(_tmp); \
IR_REGSET_EXCL(_tmp, _reg); \
reg = _reg; \
reg = ir_regset_pop_first(&_tmp);
#define IR_REGSET_FOREACH_END() \
} \
@ -1152,7 +1162,6 @@ IR_ALWAYS_INLINE int8_t ir_get_alocated_reg(const ir_ctx *ctx, ir_ref ref, int o
#define IR_RULE_MASK 0xff
typedef enum _ir_reg ir_reg;
typedef struct _ir_target_constraints ir_target_constraints;
#define IR_TMP_REG(_num, _type, _start, _end) \

65
ir_ra.c
View File

@ -2015,19 +2015,14 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l
reg = other->reg;
IR_ASSERT(reg >= 0);
if (reg >= IR_REG_SCRATCH) {
ir_regset regset;
if (reg == IR_REG_SCRATCH) {
regset = IR_REGSET_INTERSECTION(available, IR_REGSET_SCRATCH);
available = IR_REGSET_DIFFERENCE(available, IR_REGSET_SCRATCH);
} else {
IR_ASSERT(reg == IR_REG_ALL);
regset = available;
available = IR_REGSET_EMPTY;
}
IR_REGSET_FOREACH(regset, reg) {
freeUntilPos[reg] = 0;
} IR_REGSET_FOREACH_END();
} else if (IR_REGSET_IN(available, reg)) {
freeUntilPos[reg] = 0;
} else {
IR_REGSET_EXCL(available, reg);
}
other = other->list_next;
}
@ -2038,13 +2033,15 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l
* but it is still necessary after coalescing and splitting
*/
other = inactive;
pos = ival->end;
while (other) {
/* freeUntilPos[it.reg] = next intersection of it with current */
if (other->current_range->start < pos) {
next = ir_ivals_overlap(&ival->range, other->current_range);
if (next) {
reg = other->reg;
IR_ASSERT(reg >= 0);
if (reg >= IR_REG_SCRATCH) {
next = ir_ivals_overlap(&ival->range, other->current_range);
if (next) {
ir_regset regset;
if (reg == IR_REG_SCRATCH) {
@ -2058,13 +2055,13 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l
freeUntilPos[reg] = next;
}
} IR_REGSET_FOREACH_END();
}
} else if (IR_REGSET_IN(available, reg)) {
next = ir_ivals_overlap(&ival->range, other->current_range);
if (next && next < freeUntilPos[reg]) {
if (next < freeUntilPos[reg]) {
freeUntilPos[reg] = next;
}
}
}
}
other = other->list_next;
}
@ -2102,9 +2099,8 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l
pos = freeUntilPos[i];
reg = i;
} else if (freeUntilPos[i] == pos
&& (reg == IR_REG_NONE
|| (!IR_REGSET_IN(IR_REGSET_SCRATCH, reg)
&& IR_REGSET_IN(IR_REGSET_SCRATCH, i)))) {
&& !IR_REGSET_IN(IR_REGSET_SCRATCH, reg)
&& IR_REGSET_IN(IR_REGSET_SCRATCH, i)) {
/* prefer caller-saved registers to avoid save/restore in prologue/epilogue */
pos = freeUntilPos[i];
reg = i;
@ -2699,21 +2695,24 @@ static int ir_linear_scan(ir_ctx *ctx)
while (other) {
ir_live_range *r = other->current_range;
if (r && r->end <= position) {
IR_ASSERT(r);
if (r->end <= position) {
do {
r = r->next;
} while (r && r->end <= position);
other->current_range = r;
}
/* if (ir_ival_end(other) <= position) {*/
if (!r) {
/* move i from active to handled */
other = other->list_next;
if (prev) {
prev->list_next = other->list_next;
prev->list_next = other;
} else {
active = other->list_next;
active = other;
}
} else if (position < r->start) {
continue;
}
other->current_range = r;
}
if (position < r->start) {
/* move i from active to inactive */
if (prev) {
prev->list_next = other->list_next;
@ -2734,22 +2733,24 @@ static int ir_linear_scan(ir_ctx *ctx)
while (other) {
ir_live_range *r = other->current_range;
if (r && r->end <= position) {
IR_ASSERT(r);
if (r->end <= position) {
do {
r = r->next;
} while (r && r->end <= position);
other->current_range = r;
}
/* if (ir_ival_end(other) <= position) {*/
if (!r) {
/* move i from inactive to handled */
other = other->list_next;
if (prev) {
prev->list_next = other->list_next;
prev->list_next = other;
} else {
inactive = other->list_next;
inactive = other;
}
/* } else if (ir_ival_covers(other, position)) {*/
} else if (position >= r->start) {
continue;
}
other->current_range = r;
}
if (position >= r->start) {
/* move i from active to inactive */
if (prev) {
prev->list_next = other->list_next;