[Mesa-dev] [PATCH v4 08/10] mesa/st/glsl_to_tgsi: Add tracking of indirect addressing registers

Gert Wollny gw.fossdev at gmail.com
Tue Dec 12 13:40:58 UTC 2017


So far indirect addressing was not tracked to estimate the temporary
life time, and it was not needed, because code to load the address
registers was always emitted eliminating the reladdr* handles in the
past glsl-to.tgsi stages. Now, with Mareks patch allowing any 1D register
to be used for addressing n some hardware this changed, and
the tracking becomes necessary.

Because the registers have no direct indication on whether the reladdr* was
already loaded into an address register, the temporaries in reladdr* are
always tracked as reads. This may result in a slight over-estimation of the
lifetime in the cases when the load to the address register was emitted.

v2: no changes
v3: Use debug_log variable instead of directly writing to std::err in debugging
    output.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com> (v1)
---
 .../state_tracker/st_glsl_to_tgsi_temprename.cpp   | 108 ++++++++++++++-------
 1 file changed, 74 insertions(+), 34 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
index 574e43bfe1..8a2e6fc646 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
@@ -873,6 +873,69 @@ public:
    }
 };
 
+class access_recorder {
+public:
+   access_recorder(int _ntemps);
+   ~access_recorder();
+
+   void record_read(const st_src_reg& src, int line, prog_scope *scope);
+   void record_write(const st_dst_reg& src, int line, prog_scope *scope);
+
+   void get_required_lifetimes(struct lifetime *lifetimes);
+private:
+
+   int ntemps;
+   temp_access *acc;
+
+};
+
+access_recorder::access_recorder(int _ntemps):
+   ntemps(_ntemps)
+{
+   acc = new temp_access[ntemps];
+}
+
+access_recorder::~access_recorder()
+{
+   delete[] acc;
+}
+
+void access_recorder::record_read(const st_src_reg& src, int line,
+                                  prog_scope *scope)
+{
+   if (src.file == PROGRAM_TEMPORARY)
+      acc[src.index].record_read(line, scope, src.swizzle);
+
+   if (src.reladdr)
+      record_read(*src.reladdr, line, scope);
+   if (src.reladdr2)
+      record_read(*src.reladdr2, line, scope);
+}
+
+void access_recorder::record_write(const st_dst_reg& dst, int line,
+                                   prog_scope *scope)
+{
+   if (dst.file == PROGRAM_TEMPORARY)
+      acc[dst.index].record_write(line, scope, dst.writemask);
+
+   if (dst.reladdr)
+      record_read(*dst.reladdr, line, scope);
+   if (dst.reladdr2)
+      record_read(*dst.reladdr2, line, scope);
+}
+
+void access_recorder::get_required_lifetimes(struct lifetime *lifetimes)
+{
+   RENAME_DEBUG(debug_log << "========= lifetimes ==============\n");
+   for(int i = 0; i < ntemps; ++i) {
+      RENAME_DEBUG(debug_log<< setw(4) << i);
+      lifetimes[i] = acc[i].get_required_lifetime();
+      RENAME_DEBUG(debug_log << ": [" << lifetimes[i].begin << ", "
+                        << lifetimes[i].end << "]\n");
+   }
+   RENAME_DEBUG(debug_log << "==================================\n\n");
+}
+
 }
 
 #ifndef NDEBUG
@@ -893,7 +956,6 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
    int if_id = 1;
    int switch_id = 0;
    bool is_at_end = false;
-   bool ok = true;
    int n_scopes = 1;
 
    /* Count scopes to allocate the needed space without the need for
@@ -911,7 +973,8 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
    }
 
    prog_scope_storage scopes(mem_ctx, n_scopes);
-   temp_access *acc = new temp_access[ntemps];
+
+   access_recorder access(ntemps);
 
    prog_scope *cur_scope = scopes.create(nullptr, outer_scope, 0, 0, line);
 
@@ -940,9 +1003,7 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
       case TGSI_OPCODE_IF:
       case TGSI_OPCODE_UIF: {
          assert(num_inst_src_regs(inst) == 1);
-         const st_src_reg& src = inst->src[0];
-         if (src.file == PROGRAM_TEMPORARY)
-            acc[src.index].record_read(line, cur_scope, src.swizzle);
+         access.record_read(inst->src[0], line, cur_scope);
          cur_scope = scopes.create(cur_scope, if_branch, if_id++,
                                    cur_scope->nesting_depth() + 1, line + 1);
          break;
@@ -968,14 +1029,12 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
       }
       case TGSI_OPCODE_SWITCH: {
          assert(num_inst_src_regs(inst) == 1);
-         const st_src_reg& src = inst->src[0];
          prog_scope *scope = scopes.create(cur_scope, switch_body, switch_id++,
                                            cur_scope->nesting_depth() + 1, line);
          /* We record the read only for the SWITCH statement itself, like it
           * is used by the only consumer of TGSI_OPCODE_SWITCH in tgsi_exec.c.
           */
-         if (src.file == PROGRAM_TEMPORARY)
-            acc[src.index].record_read(line, cur_scope, src.swizzle);
+         access.record_read(inst->src[0], line, cur_scope);
          cur_scope = scope;
          break;
       }
@@ -997,9 +1056,7 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
                                        cur_scope : cur_scope->parent();
 
          assert(num_inst_src_regs(inst) == 1);
-         const st_src_reg& src = inst->src[0];
-         if (src.file == PROGRAM_TEMPORARY)
-            acc[src.index].record_read(line, switch_scope, src.swizzle);
+         access.record_read(inst->src[0], line, switch_scope);
 
          /* Fall through to allocate the scope. */
       }
@@ -1035,23 +1092,16 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
           * Since this is not done, we have to bail out here and signal
           * that no register merge will take place.
           */
-         ok = false;
-         goto out;
+         return false;
       default: {
          for (unsigned j = 0; j < num_inst_src_regs(inst); j++) {
-            const st_src_reg& src = inst->src[j];
-            if (src.file == PROGRAM_TEMPORARY)
-               acc[src.index].record_read(line, cur_scope, src.swizzle);
+            access.record_read(inst->src[j], line, cur_scope);
          }
          for (unsigned j = 0; j < inst->tex_offset_num_offset; j++) {
-            const st_src_reg& src = inst->tex_offsets[j];
-            if (src.file == PROGRAM_TEMPORARY)
-               acc[src.index].record_read(line, cur_scope, src.swizzle);
+            access.record_read(inst->tex_offsets[j], line, cur_scope);
          }
          for (unsigned j = 0; j < num_inst_dst_regs(inst); j++) {
-            const st_dst_reg& dst = inst->dst[j];
-            if (dst.file == PROGRAM_TEMPORARY)
-               acc[dst.index].record_write(line, cur_scope, dst.writemask);
+            access.record_write(inst->dst[j], line, cur_scope);
          }
       }
       }
@@ -1066,18 +1116,8 @@ get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions,
    if (cur_scope->end() < 0)
       cur_scope->set_end(line - 1);
 
-   RENAME_DEBUG(debug_log << "========= lifetimes ==============\n");
-   for(int i = 0; i < ntemps; ++i) {
-      RENAME_DEBUG(debug_log << setw(4) << i);
-      lifetimes[i] = acc[i].get_required_lifetime();
-      RENAME_DEBUG(debug_log << ": [" << lifetimes[i].begin << ", "
-                        << lifetimes[i].end << "]\n");
-   }
-   RENAME_DEBUG(debug_log << "==================================\n\n");
-
-out:
-   delete[] acc;
-   return ok;
+   access.get_required_lifetimes(lifetimes);
+   return true;
 }
 
 /* Find the next register between [start, end) that has a life time starting
-- 
2.13.6



More information about the mesa-dev mailing list