[Mesa-dev] [PATCH 22/22] nvir/nir: implement variable indexing

Karol Herbst kherbst at redhat.com
Thu Dec 21 15:51:40 UTC 2017


we store those arrays in local memory and reserve some space for each of the
arrays. Tthe arrays are stored in a packed format, because we know quite easily
the context of each index. We don't do that in TGSI so far.

This causes various issues to come up in the MemoryOpt pass, because ld/st with
indirects aren't guarenteed to be aligned to 0x10 anymore.

Signed-off-by: Karol Herbst <kherbst at redhat.com>
---
 .../drivers/nouveau/codegen/nv50_ir_from_nir.cpp   | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
index dda7507d76..3052c57d3c 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
@@ -48,6 +48,7 @@ public:
    typedef decltype(nir_ssa_def().index) NirSSADefIdx;
    typedef decltype(nir_ssa_def().bit_size) NirSSADefBitSize;
    typedef std::unordered_map<NirSSADefIdx, LValues> NirDefMap;
+   typedef std::unordered_map<NirSSADefIdx, uint32_t> NirArrayLMemOffsets;
    typedef std::unordered_map<decltype(nir_block().index), BasicBlock*> NirBlockMap;
 
    Converter(Program *, nir_shader *, nv50_ir_prog_info *);
@@ -110,6 +111,7 @@ private:
 
    NirDefMap ssaDefs;
    NirDefMap regDefs;
+   NirArrayLMemOffsets regToLmemOffset;
    NirBlockMap blocks;
    unsigned int curLoopDepth;
 
@@ -935,6 +937,7 @@ bool Converter::assignSlots() {
 bool
 Converter::parseNIR()
 {
+   info->bin.tlsSpace = 0;
    info->io.clipDistances = nir->info.clip_distance_array_size;
    info->io.cullDistances = nir->info.cull_distance_array_size;
 
@@ -990,6 +993,15 @@ Converter::visit(nir_function *function)
       break;
    }
 
+   nir_foreach_register(reg, &function->impl->registers) {
+      if (reg->num_array_elems) {
+         uint32_t size = reg->num_components * reg->num_array_elems * (reg->bit_size / 8);
+         // reserve some lmem
+         regToLmemOffset[reg->index] = info->bin.tlsSpace;
+         info->bin.tlsSpace += size;
+      }
+   }
+
    nir_index_ssa_defs(function->impl);
    foreach_list_typed(nir_cf_node, node, node, &function->impl->body) {
       if (!visit(node))
@@ -1530,6 +1542,51 @@ Converter::visit(nir_alu_instr *insn)
     *   2. they basically just merge multiple values into one data type
     */
    CASE_OP(mov):
+      if (!insn->dest.dest.is_ssa && insn->dest.dest.reg.reg->num_array_elems) {
+         nir_reg_dest& reg = insn->dest.dest.reg;
+         auto goffset = regToLmemOffset[reg.reg->index];
+         auto comps = reg.reg->num_components;
+         auto size = reg.reg->bit_size / 8;
+         auto csize = comps * size;
+         auto aoffset = csize * reg.base_offset;
+         Value *indirect = nullptr;
+
+         if (reg.indirect)
+            indirect = mkOp2v(OP_MUL, TYPE_U32, getSSA(4, FILE_ADDRESS), getSrc(reg.indirect, 0), mkImm(csize));
+
+         for (auto i = 0u; i < comps; ++i) {
+            if (!((1u << i) & insn->dest.write_mask))
+               continue;
+
+            Symbol *sym = mkSymbol(FILE_MEMORY_LOCAL, 0, dType, goffset + aoffset + i * size);
+            mkStore(OP_STORE, dType, sym, indirect, getSrc(&insn->src[0], i));
+         }
+         break;
+      } else if (!insn->src[0].src.is_ssa && insn->src[0].src.reg.reg->num_array_elems) {
+         LValues &newDefs = convert(&insn->dest);
+         nir_reg_src& reg = insn->src[0].src.reg;
+         auto goffset = regToLmemOffset[reg.reg->index];
+         auto comps = reg.reg->num_components;
+         auto size = reg.reg->bit_size / 8;
+         auto csize = comps * size;
+         auto aoffset = csize * reg.base_offset;
+         Value *indirect = nullptr;
+
+         if (reg.indirect)
+            indirect = mkOp2v(OP_MUL, TYPE_U32, getSSA(4, FILE_ADDRESS), getSrc(reg.indirect, 0), mkImm(csize));
+
+         for (auto i = 0u; i < newDefs.size(); ++i) {
+            Symbol *sym = mkSymbol(FILE_MEMORY_LOCAL, 0, dType, goffset + aoffset + i * size);
+            mkLoad(dType, newDefs[i], sym, indirect);
+         }
+         break;
+      } else {
+         LValues &newDefs = convert(&insn->dest);
+         for (LValues::size_type c = 0u; c < newDefs.size(); ++c) {
+            mkMov(newDefs[c], getSrc(&insn->src[0], c), dType);
+         }
+      }
+      break;
    case nir_op_vec2:
    case nir_op_vec3:
    case nir_op_vec4: {
@@ -1907,6 +1964,7 @@ Converter::run()
       NIR_PASS(progress, nir, nir_opt_dead_cf);
    } while (progress);
 
+   NIR_PASS_V(nir, nir_lower_locals_to_regs);
    NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_local);
    NIR_PASS_V(nir, nir_convert_from_ssa, true);
 
-- 
2.14.3



More information about the mesa-dev mailing list