[Mesa-dev] [PATCH 2/3] st/glsl_to_tgsi: fix DFRACEXP with only one destination

Nicolai Hähnle nhaehnle at gmail.com
Tue Oct 10 12:11:14 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

Replace the undefined destination by a new temporary register.

Cleanup merge_two_dsts while we're at it.
---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 38 ++++++++++++++++++------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 168719b33c9..235690510b9 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -5199,54 +5199,62 @@ glsl_to_tgsi_visitor::eliminate_dead_code(void)
    return removed;
 }
 
 /* merge DFRACEXP instructions into one. */
 void
 glsl_to_tgsi_visitor::merge_two_dsts(void)
 {
    /* We never delete inst, but we may delete its successor. */
    foreach_in_list(glsl_to_tgsi_instruction, inst, &this->instructions) {
       glsl_to_tgsi_instruction *inst2;
-      bool merged;
+      unsigned defined;
+
       if (num_inst_dst_regs(inst) != 2)
          continue;
 
       if (inst->dst[0].file != PROGRAM_UNDEFINED &&
           inst->dst[1].file != PROGRAM_UNDEFINED)
          continue;
 
+      assert(inst->dst[0].file != PROGRAM_UNDEFINED ||
+             inst->dst[1].file != PROGRAM_UNDEFINED);
+
+      if (inst->dst[0].file == PROGRAM_UNDEFINED)
+         defined = 1;
+      else
+         defined = 0;
+
       inst2 = (glsl_to_tgsi_instruction *) inst->next;
       do {
-
-         if (inst->src[0].file == inst2->src[0].file &&
+         if (inst->op == inst2->op &&
+             inst2->dst[defined].file == PROGRAM_UNDEFINED &&
+             inst->src[0].file == inst2->src[0].file &&
              inst->src[0].index == inst2->src[0].index &&
              inst->src[0].type == inst2->src[0].type &&
              inst->src[0].swizzle == inst2->src[0].swizzle)
             break;
          inst2 = (glsl_to_tgsi_instruction *) inst2->next;
       } while (inst2);
 
-      if (!inst2)
+      if (!inst2) {
+         /* Undefined destinations are not allowed, substitute with an unused
+          * temporary register.
+          */
+         st_src_reg tmp = get_temp(glsl_type::vec4_type);
+         inst->dst[defined ^ 1] = st_dst_reg(tmp);
+         inst->dst[defined ^ 1].writemask = 0;
          continue;
-      merged = false;
-      if (inst->dst[0].file == PROGRAM_UNDEFINED) {
-         merged = true;
-         inst->dst[0] = inst2->dst[0];
-      } else if (inst->dst[1].file == PROGRAM_UNDEFINED) {
-         inst->dst[1] = inst2->dst[1];
-         merged = true;
       }
 
-      if (merged) {
-         inst2->remove();
-         delete inst2;
-      }
+      inst->dst[defined ^ 1] = inst2->dst[defined ^ 1];
+      inst2->remove();
+      delete inst2;
    }
 }
 
 /* Merges temporary registers together where possible to reduce the number of
  * registers needed to run a program.
  *
  * Produces optimal code only after copy propagation and dead code elimination
  * have been run. */
 void
 glsl_to_tgsi_visitor::merge_registers(void)
-- 
2.11.0



More information about the mesa-dev mailing list