Add vreg hints

This commit is contained in:
Dmitry Stogov 2022-04-15 16:02:23 +03:00
parent f04433999f
commit 0922b7cd7f
4 changed files with 53 additions and 7 deletions

1
ir.h
View File

@ -505,6 +505,7 @@ typedef struct _ir_live_interval ir_live_interval;
struct _ir_use_pos {
uint16_t op_num; /* 0 - means result */
int8_t hint;
uint32_t hint_vreg;
ir_live_pos pos;
ir_use_pos *next;
};

View File

@ -312,6 +312,9 @@ void ir_dump_live_ranges(ir_ctx *ctx, FILE *f)
if (use_pos->hint >= 0) {
fprintf(f, ", hint=%%%s", ir_reg_name(use_pos->hint, ival->type));
}
if (use_pos->hint_vreg) {
fprintf(f, ", hint=R%d", use_pos->hint_vreg);
}
fprintf(f, ")");
use_pos = use_pos->next;
}

35
ir_ra.c
View File

@ -168,7 +168,6 @@ static void ir_add_use_pos(ir_ctx *ctx, int v, ir_use_pos *use_pos)
p = p->next;
}
if (prev) {
use_pos->next = prev->next;
prev->next = use_pos;
@ -178,13 +177,14 @@ static void ir_add_use_pos(ir_ctx *ctx, int v, ir_use_pos *use_pos)
}
}
static void ir_add_use(ir_ctx *ctx, int v, int op_num, ir_live_pos pos, ir_reg hint)
static void ir_add_use(ir_ctx *ctx, int v, int op_num, ir_live_pos pos, ir_reg hint, uint32_t hint_vreg)
{
ir_use_pos *use_pos;
use_pos = ir_mem_malloc(sizeof(ir_use_pos));
use_pos->op_num = op_num;
use_pos->hint = hint;
use_pos->hint_vreg = hint_vreg;
use_pos->pos = pos;
ir_add_use_pos(ctx, v, use_pos);
@ -269,6 +269,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
if (ctx->vregs[i] && ir_bitset_in(live, ctx->vregs[i])) {
if (insn->op != IR_PHI) {
ir_live_pos def_pos;
uint32_t hint_vreg = 0;
reg = ctx->rules ? ir_uses_fixed_reg(ctx, i, 0) : IR_REG_NONE;
if (reg != IR_REG_NONE) {
@ -283,15 +284,16 @@ int ir_compute_live_ranges(ir_ctx *ctx)
}
} else if (ctx->rules && ir_result_reuses_op1_reg(ctx, i)) {
def_pos = IR_GAP_LIVE_POS_FROM_REF(i);
hint_vreg = ctx->vregs[insn->op1];
} else {
def_pos = IR_DEF_LIVE_POS_FROM_REF(i);
}
/* intervals[opd].setFrom(op.id) */
ir_fix_live_range(ctx, ctx->vregs[i],
IR_START_LIVE_POS_FROM_REF(bb->start), def_pos);
ir_add_use(ctx, ctx->vregs[i], 0, def_pos, reg);
ir_add_use(ctx, ctx->vregs[i], 0, def_pos, reg, hint_vreg);
} else {
ir_add_use(ctx, ctx->vregs[i], 0, IR_DEF_LIVE_POS_FROM_REF(i), reg);
ir_add_use(ctx, ctx->vregs[i], 0, IR_DEF_LIVE_POS_FROM_REF(i), IR_REG_NONE, 0);
}
/* live.remove(opd) */
ir_bitset_excl(live, ctx->vregs[i]);
@ -307,6 +309,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
if (ctx->rules && j == 1 && ir_result_reuses_op1_reg(ctx, i)) {
use_pos = IR_START_LIVE_POS_FROM_REF(i); // TODO: ???
reg = IR_REG_NONE;
} else {
reg = ctx->rules ? ir_uses_fixed_reg(ctx, i, j) : IR_REG_NONE;
if (reg != IR_REG_NONE) {
@ -320,7 +323,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
/* intervals[opd].addRange(b.from, op.id) */
ir_add_live_range(ctx, ctx->vregs[input], ctx->ir_base[input].type,
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
ir_add_use(ctx, ctx->vregs[input], j, use_pos, reg);
ir_add_use(ctx, ctx->vregs[input], j, use_pos, reg, 0);
/* live.add(opd) */
ir_bitset_incl(live, ctx->vregs[input]);
}
@ -472,6 +475,9 @@ static void ir_vregs_join(ir_ctx *ctx, uint32_t r1, uint32_t r2)
use_pos = ival->use_pos;
while (use_pos) {
ir_use_pos *next_use_pos = use_pos->next;
if (use_pos->hint_vreg == r1) {
use_pos->hint_vreg = 0;
}
ir_add_use_pos(ctx, r1, use_pos);
use_pos = next_use_pos;
}
@ -841,7 +847,7 @@ static void ir_allocate_spill_slot(ir_ctx *ctx, int current, ir_lsra_data *data)
}
}
static ir_reg ir_try_allocate_preferred_reg(ir_live_interval *ival, ir_live_pos *freeUntilPos)
static ir_reg ir_try_allocate_preferred_reg(ir_ctx *ctx, ir_live_interval *ival, ir_live_pos *freeUntilPos)
{
ir_use_pos *use_pos;
@ -855,6 +861,21 @@ static ir_reg ir_try_allocate_preferred_reg(ir_live_interval *ival, ir_live_pos
}
use_pos = use_pos->next;
}
use_pos = ival->use_pos;
while (use_pos) {
if (use_pos->hint_vreg) {
ir_reg reg = ctx->live_intervals[use_pos->hint_vreg]->reg;
if (reg >= 0) {
if (ir_live_range_end(ival) <= freeUntilPos[reg]) {
/* register available for the whole interval */
return reg;
}
}
}
use_pos = use_pos->next;
}
return IR_REG_NONE;
}
@ -929,7 +950,7 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, int current, uint32_t len, i
} IR_BITSET_FOREACH_END();
/* Try to use hint */
reg = ir_try_allocate_preferred_reg(ival, freeUntilPos);
reg = ir_try_allocate_preferred_reg(ctx, ival, freeUntilPos);
if (reg != IR_REG_NONE) {
ival->reg = reg;
return reg;

21
tests/x86_64/ra_015.irt Normal file
View File

@ -0,0 +1,21 @@
--TEST--
015: Register Allocation (SHL + SHL + reuse/vreg hint)
--ARGS--
-S
--CODE--
{
l_1 = START(l_4);
uint32_t x = PARAM(l_1, "x", 1);
uint32_t y = PARAM(l_1, "y", 2);
uint32_t ret = SHL(x, y);
uint32_t ret2 = SHL(y, ret);
l_4 = RETURN(l_1, ret2);
}
--EXPECT--
test:
movl %esi, %ecx
shll %cl, %edi
movl %esi, %eax
movl %edi, %ecx
shll %cl, %eax
retq