[PATCH 11/21] etnaviv: compiler: add code emitter for alu operations

Philipp Zabel p.zabel at pengutronix.de
Tue Jun 5 14:38:35 UTC 2018


From: Michael Tretter <m.tretter at pengutronix.de>

Start emitting ALU instructions for nir_alu_instr structures from the
NIR shader's main function implementation.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 .../drivers/etnaviv/etnaviv_compiler.c        | 290 ++++++++++++++++++
 1 file changed, 290 insertions(+)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
index 59caff435e64..129c9115e783 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_compiler.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
@@ -1937,6 +1937,293 @@ etna_compile_pass_generate_code(struct etna_compile *c)
    tgsi_parse_free(&ctx);
 }
 
+static void
+translate_alu_sources(struct etna_compile *c, struct nir_alu_instr *instr,
+                      struct etna_inst_src src[3])
+{
+   const nir_op_info *info = &nir_op_infos[instr->op];
+
+   for (unsigned i = 0; i < info->num_inputs; i++) {
+      nir_alu_src nir_src = instr->src[i];
+      if (nir_src.src.is_ssa) {
+         nir_const_value *val = NULL;
+         if (nir_src.src.ssa->parent_instr->type == nir_instr_type_intrinsic) {
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(nir_src.src.ssa->parent_instr);
+            // int indirect_offset = intr->src[0];
+            src[i].use = 1;
+            src[i].swiz = INST_SWIZ(nir_src.swizzle[0], nir_src.swizzle[1],
+               nir_src.swizzle[2], nir_src.swizzle[3]);
+            src[i].reg = nir_intrinsic_base(intr);
+            src[i].rgroup = INST_RGROUP_UNIFORM_0;
+         } else {
+            val = nir_src_as_const_value(nir_src.src);
+            src[i] = alloc_imm_vec4u(c, ETNA_IMMEDIATE_CONSTANT, val->u32);
+            src[i].swiz = INST_SWIZ(nir_src.swizzle[0], nir_src.swizzle[1],
+               nir_src.swizzle[2], nir_src.swizzle[3]);
+         }
+      } else {
+         src[i].use = 1;
+         src[i].swiz = INST_SWIZ(nir_src.swizzle[0], nir_src.swizzle[1],
+               nir_src.swizzle[2], nir_src.swizzle[3]);
+         src[i].rgroup = INST_RGROUP_TEMP;
+         src[i].reg = nir_src.src.reg.reg->index;
+         src[i].amode = INST_AMODE_DIRECT;
+         src[i].neg = nir_src.negate;
+      }
+   }
+}
+
+static void
+etna_emit_alu(struct etna_compile *c, nir_alu_instr *instr)
+{
+   const nir_op_info *info = &nir_op_infos[instr->op];
+
+   struct etna_inst_dst dst;
+   struct etna_inst_src src[3] = {};
+
+   nir_alu_dest nir_dest = instr->dest;
+
+   dst.use = 1;
+   dst.reg = nir_dest.dest.reg.reg->index;
+   dst.comps = nir_dest.write_mask;
+
+   translate_alu_sources(c, instr, src);
+
+   switch (instr->op) {
+   case nir_op_fceil:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_CEIL,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_ffloor:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_FLOOR,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_fmov:
+   case nir_op_imov:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_MOV,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_frcp:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_RCP,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_frsq:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_RSQ,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_fmul:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_MUL,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   case nir_op_fadd:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_ADD,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[2] = src[1],
+      });
+      break;
+   case nir_op_fdot2:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_DP2,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   case nir_op_fdot3:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_DP3,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   case nir_op_ffma:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_MAD,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+         .src[2] = src[2],
+      });
+      break;
+   case nir_op_fmin:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SELECT,
+         .cond = INST_CONDITION_GT,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_fmax:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SELECT,
+         .cond = INST_CONDITION_LT,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_ffract:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_FRC,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_fsqrt:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SQRT,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_fexp2:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_EXP,
+         .dst = dst,
+         .src[2] = src[0],
+      });
+      break;
+   case nir_op_seq:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SET,
+         .cond = INST_CONDITION_EQ,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   case nir_op_sge:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SET,
+         .cond = INST_CONDITION_GE,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   case nir_op_slt:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SET,
+         .cond = INST_CONDITION_LT,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   case nir_op_sne:
+      emit_inst(c, &(struct etna_inst) {
+         .opcode = INST_OPCODE_SET,
+         .cond = INST_CONDITION_NE,
+         .dst = dst,
+         .src[0] = src[0],
+         .src[1] = src[1],
+      });
+      break;
+   default:
+      BUG("Unhandled nir_alu_instr: %s\n", info->name);
+      assert(0);
+      break;
+   }
+
+   return;
+}
+
+static void
+etna_emit_intr(struct etna_compile *c, nir_intrinsic_instr *intr)
+{
+   switch (intr->intrinsic) {
+   case nir_intrinsic_nop:
+      emit_inst(c, &(struct etna_inst) {
+            .opcode = INST_OPCODE_NOP,
+      });
+      break;
+   default:
+      /* Nothing to do */
+      break;
+   }
+}
+
+static void
+etna_emit_instr(struct etna_compile *c, nir_instr *instr)
+{
+   switch (instr->type) {
+   case nir_instr_type_alu:
+      etna_emit_alu(c, nir_instr_as_alu(instr));
+      break;
+   case nir_instr_type_intrinsic:
+      etna_emit_intr(c, nir_instr_as_intrinsic(instr));
+      break;
+   case nir_instr_type_load_const:
+      /* Nothing to do */
+      break;
+   default:
+      BUG("Unhandled nir_instr: %d", instr->type);
+      assert(0);
+      break;
+   }
+}
+
+static void
+etna_emit_block(struct etna_compile *c, nir_block *nblock)
+{
+   nir_foreach_instr(instr, nblock) {
+      etna_emit_instr(c, instr);
+   }
+}
+
+static void
+etna_emit_cf_list(struct etna_compile *c, struct exec_list *list)
+{
+   foreach_list_typed(nir_cf_node, node, node, list) {
+      switch (node->type) {
+      case nir_cf_node_block:
+         etna_emit_block(c, nir_cf_node_as_block(node));
+         break;
+      default:
+         BUG("Unhandled nir node type %d\n", node->type);
+         assert(0);
+         break;
+      }
+   }
+}
+
+static void
+etna_emit_function(struct etna_compile *c, nir_function_impl *func_impl)
+{
+   /* Handle only main function */
+   assert(strcmp(func_impl->function->name, "main") == 0);
+
+   etna_emit_cf_list(c, &func_impl->body);
+   etna_emit_block(c, func_impl->end_block);
+
+   return;
+}
+
 static void
 etna_setup_registers_from_nir(struct etna_compile *c, struct etna_shader_variant *v)
 {
@@ -2117,6 +2404,9 @@ etna_compile_shader_nir(struct etna_compile *c, struct etna_shader_variant *v)
    etna_setup_uniforms_from_nir(c, v);
    etna_setup_inputs_from_nir(c, v);
    etna_setup_outputs_from_nir(c, v);
+
+   impl = nir_shader_get_entrypoint(c->s);
+   etna_emit_function(c, impl);
 }
 
 /* Look up register by semantic */
-- 
2.17.1



More information about the etnaviv mailing list