lima/ppir: Add undef handling

Add a ppir dummy node for nir_ssa_undef_instr, create a reg for it and mark
it as undefined, so that regalloc can set it non-interfering to avoid
register pressure.

Signed-off-by: Andreas Baierl <ichgeh@imkreisrum.de>
Reviewed-by: Vasily Khozuzhick <anarsoul@gmail.com>
Reviewed-by: Erico Nunes <nunes.erico@gmail.com>
This commit is contained in:
Andreas Baierl 2019-08-20 18:19:55 +02:00 committed by Erico Nunes
parent 4ddadd6370
commit 4b1a14fd47
4 changed files with 24 additions and 4 deletions

View file

@ -142,7 +142,8 @@ static void ppir_node_add_src(ppir_compiler *comp, ppir_node *node,
break;
}
ppir_node_add_dep(node, child);
if (child->op != ppir_op_undef)
ppir_node_add_dep(node, child);
}
else {
nir_register *reg = ns->reg.reg;
@ -418,8 +419,19 @@ static ppir_node *ppir_emit_load_const(ppir_block *block, nir_instr *ni)
static ppir_node *ppir_emit_ssa_undef(ppir_block *block, nir_instr *ni)
{
ppir_error("nir_ssa_undef_instr not support\n");
return NULL;
nir_ssa_undef_instr *undef = nir_instr_as_ssa_undef(ni);
ppir_node *node = ppir_node_create_ssa(block, ppir_op_undef, &undef->def);
if (!node)
return NULL;
ppir_alu_node *alu = ppir_node_to_alu(node);
ppir_dest *dest = &alu->dest;
dest->ssa.undef = true;
ppir_reg *ssa = &dest->ssa;
list_add(&ssa->list, &block->comp->reg_list);
return node;
}
static ppir_node *ppir_emit_tex(ppir_block *block, nir_instr *ni)

View file

@ -66,6 +66,10 @@ static bool ppir_do_one_node_to_instr(ppir_block *block, ppir_node *node, ppir_n
switch (node->type) {
case ppir_node_type_alu:
{
/* don't create an instr for undef node */
if (node->op == ppir_op_undef)
break;
/* merge pred mul and succ add in the same instr can save a reg
* by using pipeline reg ^vmul/^fmul */
ppir_alu_node *alu = ppir_node_to_alu(node);

View file

@ -181,6 +181,7 @@ typedef struct ppir_reg {
/* instr live range */
int live_in, live_out;
bool spilled;
bool undef;
} ppir_reg;
typedef enum {

View file

@ -612,7 +612,10 @@ static bool ppir_regalloc_prog_try(ppir_compiler *comp, bool *spilled)
list_for_each_entry_from(ppir_reg, reg2, reg1->list.next,
&comp->reg_list, list) {
bool interference = false;
if (reg1->live_in < reg2->live_in) {
if (reg1->undef || reg2->undef)
interference = false;
else if (reg1->live_in < reg2->live_in) {
if (reg1->live_out > reg2->live_in)
interference = true;
}