From ef38a659fbcc5eb22ad653e6d557d39e2b7b5fe8 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Wed, 18 Sep 2019 18:13:08 +0700 Subject: [PATCH] lima/gpir: Don't emit movs when translating from NIR The scheduler doesn't expect them. To do this, I had to refactor the registration part of gpir_node_create_dest() to be separate from creating and inserting the node, since the last two now aren't done when handling moves. This adds more code but creates the possibility of automatically inserting input dependencies when inserting nodes, similar to what's done in NIR with the use-def lists (this isn't done yet). Reviewed-by: Vasily Khoruzhick --- src/gallium/drivers/lima/ir/gp/nir.c | 86 ++++++++++++++++------------ 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/src/gallium/drivers/lima/ir/gp/nir.c b/src/gallium/drivers/lima/ir/gp/nir.c index 8d9a5beb98a..e405e1a6c62 100644 --- a/src/gallium/drivers/lima/ir/gp/nir.c +++ b/src/gallium/drivers/lima/ir/gp/nir.c @@ -49,17 +49,13 @@ static gpir_reg *reg_for_nir_reg(gpir_compiler *comp, nir_register *nir_reg) return reg; } -static inline gpir_node *gpir_node_create_ssa(gpir_block *block, gpir_op op, nir_ssa_def *ssa) +static void register_node_ssa(gpir_block *block, gpir_node *node, nir_ssa_def *ssa) { - int index = ssa->index; - gpir_node *node = gpir_node_create(block, op); + block->comp->node_for_ssa[ssa->index] = node; + snprintf(node->name, sizeof(node->name), "ssa%d", ssa->index); - block->comp->node_for_ssa[index] = node; - snprintf(node->name, sizeof(node->name), "ssa%d", index); - list_addtail(&node->list, &block->node_list); - - /* If any uses are outside the current block, we'll need to create a store - * instruction for them. + /* If any uses are outside the current block, we'll need to create a + * register and store to it. */ bool needs_register = false; nir_foreach_use(use, ssa) { @@ -87,37 +83,36 @@ static inline gpir_node *gpir_node_create_ssa(gpir_block *block, gpir_op op, nir list_addtail(&store->node.list, &block->node_list); block->comp->reg_for_ssa[ssa->index] = store->reg; } - - return node; } -static inline void *gpir_node_create_reg(gpir_block *block, gpir_op op, nir_reg_dest *nir_reg) +static void register_node_reg(gpir_block *block, gpir_node *node, nir_reg_dest *nir_reg) { - int index = nir_reg->reg->index; - gpir_node *node = gpir_node_create(block, op); - block->comp->node_for_reg[index] = node; + block->comp->node_for_reg[nir_reg->reg->index] = node; gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg); - snprintf(node->name, sizeof(node->name), "reg%d", index); + snprintf(node->name, sizeof(node->name), "reg%d", nir_reg->reg->index); store->child = node; store->reg = reg_for_nir_reg(block->comp, nir_reg->reg); gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT); - list_addtail(&node->list, &block->node_list); list_addtail(&store->node.list, &block->node_list); - return node; } -static void *gpir_node_create_dest(gpir_block *block, gpir_op op, nir_dest *dest) +/* Register the given gpir_node as providing the given NIR destination, so + * that gpir_node_find() will return it. Also insert any stores necessary if + * the destination will be used after the end of this basic block. The node + * must already be inserted. + */ +static void register_node(gpir_block *block, gpir_node *node, nir_dest *dest) { if (dest->is_ssa) - return gpir_node_create_ssa(block, op, &dest->ssa); + register_node_ssa(block, node, &dest->ssa); else - return gpir_node_create_reg(block, op, &dest->reg); + register_node_reg(block, node, &dest->reg); } -static gpir_node *gpir_node_find(gpir_block *block, gpir_node *succ, nir_src *src, +static gpir_node *gpir_node_find(gpir_block *block, nir_src *src, int channel) { gpir_reg *reg = NULL; @@ -137,7 +132,7 @@ static gpir_node *gpir_node_find(gpir_block *block, gpir_node *succ, nir_src *sr } } else { pred = block->comp->node_for_reg[src->reg.reg->index]; - if (pred && pred->block == block && pred != succ) + if (pred && pred->block == block) return pred; reg = reg_for_nir_reg(block->comp, src->reg.reg); } @@ -146,7 +141,7 @@ static gpir_node *gpir_node_find(gpir_block *block, gpir_node *succ, nir_src *sr pred = gpir_node_create(block, gpir_op_load_reg); gpir_load_node *load = gpir_node_to_load(pred); load->reg = reg; - list_addtail(&pred->list, &succ->list); + list_addtail(&pred->list, &block->node_list); return pred; } @@ -172,12 +167,25 @@ static int nir_to_gpir_opcodes[nir_num_opcodes] = { [nir_op_seq] = gpir_op_eq, [nir_op_sne] = gpir_op_ne, [nir_op_fabs] = gpir_op_abs, - [nir_op_mov] = gpir_op_mov, }; static bool gpir_emit_alu(gpir_block *block, nir_instr *ni) { nir_alu_instr *instr = nir_instr_as_alu(ni); + + /* gpir_op_mov is useless before the final scheduler, and the scheduler + * currently doesn't expect us to emit it. Just register the destination of + * this instruction with its source. This will also emit any necessary + * register loads/stores for things like "r0 = mov ssa_0" or + * "ssa_0 = mov r0". + */ + if (instr->op == nir_op_mov) { + gpir_node *child = gpir_node_find(block, &instr->src[0].src, + instr->src[0].swizzle[0]); + register_node(block, child, &instr->dest.dest); + return true; + } + int op = nir_to_gpir_opcodes[instr->op]; if (op < 0) { @@ -185,7 +193,7 @@ static bool gpir_emit_alu(gpir_block *block, nir_instr *ni) return false; } - gpir_alu_node *node = gpir_node_create_dest(block, op, &instr->dest.dest); + gpir_alu_node *node = gpir_node_create(block, op); if (unlikely(!node)) return false; @@ -197,24 +205,29 @@ static bool gpir_emit_alu(gpir_block *block, nir_instr *ni) nir_alu_src *src = instr->src + i; node->children_negate[i] = src->negate; - gpir_node *child = gpir_node_find(block, &node->node, &src->src, src->swizzle[0]); + gpir_node *child = gpir_node_find(block, &src->src, src->swizzle[0]); node->children[i] = child; gpir_node_add_dep(&node->node, child, GPIR_DEP_INPUT); } + list_addtail(&node->node.list, &block->node_list); + register_node(block, &node->node, &instr->dest.dest); + return true; } static gpir_node *gpir_create_load(gpir_block *block, nir_dest *dest, int op, int index, int component) { - gpir_load_node *load = gpir_node_create_dest(block, op, dest); + gpir_load_node *load = gpir_node_create(block, op); if (unlikely(!load)) return NULL; load->index = index; load->component = component; + list_addtail(&load->node.list, &block->node_list); + register_node(block, &load->node, dest); return &load->node; } @@ -266,14 +279,13 @@ static bool gpir_emit_intrinsic(gpir_block *block, nir_instr *ni) gpir_store_node *store = gpir_node_create(block, gpir_op_store_varying); if (unlikely(!store)) return false; - list_addtail(&store->node.list, &block->node_list); - + gpir_node *child = gpir_node_find(block, instr->src, 0); + store->child = child; store->index = nir_intrinsic_base(instr); store->component = nir_intrinsic_component(instr); - gpir_node *child = gpir_node_find(block, &store->node, instr->src, 0); - store->child = child; gpir_node_add_dep(&store->node, child, GPIR_DEP_INPUT); + list_addtail(&store->node.list, &block->node_list); return true; } @@ -287,8 +299,7 @@ static bool gpir_emit_intrinsic(gpir_block *block, nir_instr *ni) static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni) { nir_load_const_instr *instr = nir_instr_as_load_const(ni); - gpir_const_node *node = - gpir_node_to_const(gpir_node_create_ssa(block, gpir_op_const, &instr->def)); + gpir_const_node *node = gpir_node_create(block, gpir_op_const); if (unlikely(!node)) return false; @@ -297,6 +308,8 @@ static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni) node->value.i = instr->value[0].i32; + list_addtail(&node->node.list, &block->node_list); + register_node_ssa(block, &node->node, &instr->def); return true; } @@ -362,9 +375,10 @@ static bool gpir_emit_function(gpir_compiler *comp, nir_function_impl *impl) if (block_nir->successors[1] != NULL) { nir_if *nif = nir_cf_node_as_if(nir_cf_node_next(&block_nir->cf_node)); gpir_alu_node *cond = gpir_node_create(block, gpir_op_not); - list_addtail(&cond->node.list, &block->node_list); - cond->children[0] = gpir_node_find(block, &cond->node, &nif->condition, 0); + cond->children[0] = gpir_node_find(block, &nif->condition, 0); + gpir_node_add_dep(&cond->node, cond->children[0], GPIR_DEP_INPUT); + list_addtail(&cond->node.list, &block->node_list); gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_cond); list_addtail(&branch->node.list, &block->node_list); -- 2.30.2