lima/gpir: Don't emit movs when translating from NIR
[mesa.git] / src / gallium / drivers / lima / ir / gp / nir.c
index 8d9a5beb98a36e2c8fe72e281567365b6e9aee77..e405e1a6c6260efb1babe32f204b45615d5fb8d0 100644 (file)
@@ -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);