lima/ppir: improve regalloc spill cost calculation

Now that spilling ops can be inserted into existing instructions, it
makes sense to increase cost to spill registers that would cause the
creation of a new instruction.
Experimental results showed that penalizing too much due to this caused
worse results, however it is beneficial as a tie resolver between
registers with the same number of components.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
This commit is contained in:
Erico Nunes 2019-08-28 01:09:12 +02:00
parent 7b2f195d0b
commit 17bb437ac2
1 changed files with 49 additions and 5 deletions

View File

@ -479,27 +479,71 @@ static bool ppir_regalloc_spill_reg(ppir_compiler *comp, ppir_reg *chosen)
static ppir_reg *ppir_regalloc_choose_spill_node(ppir_compiler *comp,
struct ra_graph *g)
{
int i = 0;
ppir_reg *chosen = NULL;
float spill_costs[list_length(&comp->reg_list)];
/* experimentally determined, it seems to be worth scaling cost of
* regs in instructions that have used uniform/store_temp slots,
* but not too much as to offset the num_components base cost. */
const float slot_scale = 1.1f;
list_for_each_entry(ppir_reg, reg, &comp->reg_list, list) {
if (reg->spilled || reg->live_out == INT_MAX) {
/* not considered for spilling */
ra_set_node_spill_cost(g, i++, 0.0f);
spill_costs[reg->regalloc_index] = 0.0f;
continue;
}
/* It is beneficial to spill registers with higher component number,
* so increase the cost of spilling registers with few components */
float spill_cost = 4.0f / (float)reg->num_components;
ra_set_node_spill_cost(g, i++, spill_cost);
spill_costs[reg->regalloc_index] = spill_cost;
}
list_for_each_entry(ppir_block, block, &comp->block_list, list) {
list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
if (instr->slots[PPIR_INSTR_SLOT_UNIFORM]) {
for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
ppir_node *node = instr->slots[i];
if (!node)
continue;
for (int j = 0; j < ppir_node_get_src_num(node); j++) {
ppir_src *src = ppir_node_get_src(node, j);
if (!src)
continue;
ppir_reg *reg = ppir_src_get_reg(src);
if (!reg)
continue;
spill_costs[reg->regalloc_index] *= slot_scale;
}
}
}
if (instr->slots[PPIR_INSTR_SLOT_STORE_TEMP]) {
for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
ppir_node *node = instr->slots[i];
if (!node)
continue;
ppir_dest *dest = ppir_node_get_dest(node);
if (!dest)
continue;
ppir_reg *reg = ppir_dest_get_reg(dest);
if (!reg)
continue;
spill_costs[reg->regalloc_index] *= slot_scale;
}
}
}
}
for (int i = 0; i < list_length(&comp->reg_list); i++)
ra_set_node_spill_cost(g, i, spill_costs[i]);
int r = ra_get_best_spill_node(g);
if (r == -1)
return NULL;
i = 0;
ppir_reg *chosen = NULL;
int i = 0;
list_for_each_entry(ppir_reg, reg, &comp->reg_list, list) {
if (i++ == r) {
chosen = reg;