[Mesa-dev] [RFC] nir: compiler options for addressing modes

Rob Clark robdclark at gmail.com
Tue Apr 14 09:42:23 PDT 2015


From: Rob Clark <robclark at freedesktop.org>

Add compiler options so driver can request the units for address value,
for the various _indirect intrinsics.  This way, the front end can
insert the appropriate multiply/shift operations to get the address into
the units that the driver needs, avoiding need for driver to insert
these on the backend (and loose out on some optimizing potential).

The addressing modes are specified per var/input/output/uniform/ubo.
I'm not sure about other drivers, but for freedreno we want byte
addressing for ubo's and register addressing for the rest.

NOTE: so far just updated ttn and freedreno, and included everything in
one commit to make it easier to see how it fits together.  The driver
patches would naturally be separate (since drivers not setting these
options get the current/default behavior, ie. splitting out won't hurt
bisectability).  Also the ttn part could be split out as long as it
comes before freedreno or vc4 parts.

As for gtn or intel backends, I guess there are enough others who
actually know their way around that code to add support, if appropriate.
---
 src/gallium/auxiliary/nir/tgsi_to_nir.c            | 54 +++++++++++++++++++---
 .../drivers/freedreno/ir3/ir3_compiler_nir.c       | 20 +++-----
 src/glsl/nir/nir.h                                 | 27 +++++++++++
 3 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c
index 0d4bd7c..a370a01 100644
--- a/src/gallium/auxiliary/nir/tgsi_to_nir.c
+++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c
@@ -257,7 +257,21 @@ ttn_emit_immediate(struct ttn_compile *c)
 }
 
 static nir_src *
-ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect);
+ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect,
+                     unsigned file);
+
+/* everything in tgsi-land is vec4's, so we can convert to left-shift: */
+static unsigned ttn_addr_mode_to_shift(nir_addressing_mode mode)
+{
+   switch (mode) {
+   case nir_addressing_mode_none:      return 0;
+   case nir_addressing_mode_register:  return 2;
+   case nir_addressing_mode_byte:      return 4;
+   default:
+      unreachable("bad addressing mode");
+      return ~0;
+   }
+}
 
 /* generate either a constant or indirect deref chain for accessing an
  * array variable.
@@ -275,7 +289,8 @@ ttn_array_deref(struct ttn_compile *c, nir_intrinsic_instr *instr,
 
    if (indirect) {
       arr->deref_array_type = nir_deref_array_type_indirect;
-      arr->indirect = *ttn_src_for_indirect(c, indirect);
+      arr->indirect = *ttn_src_for_indirect(c, indirect,
+                                            TGSI_FILE_TEMPORARY);
    } else {
       arr->deref_array_type = nir_deref_array_type_direct;
    }
@@ -383,7 +398,7 @@ ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
       load->const_index[0] = index;
       load->const_index[1] = 1;
       if (indirect) {
-         load->src[0] = *ttn_src_for_indirect(c, indirect);
+         load->src[0] = *ttn_src_for_indirect(c, indirect, file);
       }
       nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
       nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
@@ -400,8 +415,24 @@ ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
    return src;
 }
 
+static nir_addressing_mode
+ttn_addr_mode_for_file(struct ttn_compile *c, unsigned file)
+{
+   const struct nir_shader_compiler_options *options = c->s->options;
+   switch (file) {
+   case TGSI_FILE_CONSTANT:  return options->uniform_addressing_mode;
+   case TGSI_FILE_INPUT:     return options->input_addressing_mode;
+   case TGSI_FILE_OUTPUT:    return options->output_addressing_mode;
+   case TGSI_FILE_TEMPORARY: return options->var_addressing_mode;
+   default:
+      unreachable("invalid file");
+      return 0;
+   }
+}
+
 static nir_src *
-ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect)
+ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect,
+                     unsigned file)
 {
    nir_builder *b = &c->build;
    nir_alu_src src;
@@ -411,8 +442,18 @@ ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect)
    src.src = ttn_src_for_file_and_index(c,
                                         indirect->File,
                                         indirect->Index, NULL);
+
+   nir_ssa_def *addr = nir_imov_alu(b, src, 1);
+
+   /* do we need to convert address from vec4? */
+   nir_addressing_mode addr_mode = ttn_addr_mode_for_file(c, file);
+   unsigned shift = ttn_addr_mode_to_shift(addr_mode);
+
+   if (shift)
+      addr = nir_ishl(b, addr, nir_imm_int(b, shift));
+
    nir_src *result = ralloc(b->shader, nir_src);
-   *result = nir_src_for_ssa(nir_imov_alu(b, src, 1));
+   *result = nir_src_for_ssa(addr);
    return result;
 }
 
@@ -481,7 +522,8 @@ ttn_get_dest(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst)
    dest.saturate = false;
 
    if (tgsi_dst->Indirect && (tgsi_dst->File != TGSI_FILE_TEMPORARY))
-      dest.dest.reg.indirect = ttn_src_for_indirect(c, &tgsi_fdst->Indirect);
+      dest.dest.reg.indirect = ttn_src_for_indirect(c, &tgsi_fdst->Indirect,
+                                                    tgsi_dst->File);
 
    return dest;
 }
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
index f7ea879..3f0aae6 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
@@ -125,6 +125,11 @@ static struct nir_shader *to_nir(const struct tgsi_token *tokens)
 			.lower_scmp = true,
 			.lower_flrp = true,
 			.native_integers = true,
+			.var_addressing_mode     = nir_addressing_mode_register,
+			.input_addressing_mode   = nir_addressing_mode_register,
+			.output_addressing_mode  = nir_addressing_mode_register,
+			.uniform_addressing_mode = nir_addressing_mode_register,
+			.ubo_addressing_mode     = nir_addressing_mode_byte,
 	};
 	bool progress;
 
@@ -378,22 +383,9 @@ create_addr(struct ir3_block *block, struct ir3_instruction *src)
 {
 	struct ir3_instruction *instr, *immed;
 
-	/* TODO in at least some cases, the backend could probably be
-	 * made clever enough to propagate IR3_REG_HALF..
-	 */
+	/* mov to address register: */
 	instr = ir3_COV(block, src, TYPE_U32, TYPE_S16);
-	instr->regs[0]->flags |= IR3_REG_HALF;
-
-	immed = create_immed(block, 2);
-	immed->regs[0]->flags |= IR3_REG_HALF;
-
-	instr = ir3_SHL_B(block, instr, 0, immed, 0);
-	instr->regs[0]->flags |= IR3_REG_HALF;
-	instr->regs[1]->flags |= IR3_REG_HALF;
-
-	instr = ir3_MOV(block, instr, TYPE_S16);
 	instr->regs[0]->flags |= IR3_REG_ADDR | IR3_REG_HALF;
-	instr->regs[1]->flags |= IR3_REG_HALF;
 
 	return instr;
 }
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
index 6531237..e8bce9f 100644
--- a/src/glsl/nir/nir.h
+++ b/src/glsl/nir/nir.h
@@ -1374,6 +1374,23 @@ typedef struct nir_function {
    exec_node_data(nir_function_overload, \
                   exec_list_get_head(&(func)->overload_list), node)
 
+/**
+ * Addressing mode used by the backend for various sorts of indirect
+ * access.  This allows the frontend to generate the appropriate
+ * multiply or shift operations to convert the address param for the
+ * corresponding _indirect intrinsic, rather than relying on the
+ * driver to insert them after the various other NIR optimization
+ * passes.
+ */
+typedef enum {
+   /** No address conversion, units in elements of array member: */
+   nir_addressing_mode_none = 0,
+   /** Address converted to units of registers (ie. float/int32): */
+   nir_addressing_mode_register = 1,
+   /** Address converted to units of bytes: */
+   nir_addressing_mode_byte = 2,
+} nir_addressing_mode;
+
 typedef struct nir_shader_compiler_options {
    bool lower_ffma;
    bool lower_flrp;
@@ -1393,6 +1410,16 @@ typedef struct nir_shader_compiler_options {
     * are simulated by floats.)
     */
    bool native_integers;
+
+   /**
+    * Addressing mode for corresponding _indirect intrinsics:
+    */
+   nir_addressing_mode var_addressing_mode;
+   nir_addressing_mode input_addressing_mode;
+   nir_addressing_mode output_addressing_mode;
+   nir_addressing_mode uniform_addressing_mode;
+   nir_addressing_mode ubo_addressing_mode;
+
 } nir_shader_compiler_options;
 
 typedef struct nir_shader {
-- 
2.1.0



More information about the mesa-dev mailing list