mesa/st/glsl_to_tgsi: Mark first write as unconditional when appropriate
authorGert Wollny <gw.fossdev@gmail.com>
Mon, 29 Jan 2018 12:24:00 +0000 (05:24 -0700)
committerBrian Paul <brianp@vmware.com>
Tue, 30 Jan 2018 04:04:49 +0000 (21:04 -0700)
In the register lifetime estimation if the first write is unconditional or
conditional but not within a loop then this is an unconditional dominant
write in the sense of register life time estimation.
Add a test case and record the write accordingly.

Fixes: 807e2539e512ca6c96f059da855473eb7be99ba1 ("mesa/st/glsl_to_tgsi: Add
tracking of ifelse writes in register merging")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104803
Signed-off-by: Gert Wollny <gw.fossdev@gmail.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp
src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp

index 3a00b33749659c5eeb3b37e597dac68ae46fc031..6921a643b744a04da4adf73c2ca43579bc142074 100644 (file)
@@ -197,6 +197,7 @@ private:
    static const int write_is_conditional = -1;
    static const int conditionality_unresolved = 0;
    static const int conditionality_untouched;
+   static const int write_is_unconditional;
 
    /* A bit field tracking the nexting levels of if-else clauses where the
     * temporary has (so far) been written to in the if branch, but not in the
@@ -220,6 +221,9 @@ private:
 const int
 temp_comp_access::conditionality_untouched = numeric_limits<int>::max();
 
+const int
+temp_comp_access::write_is_unconditional = numeric_limits<int>::max() - 1;
+
 /* Class to track the access to all components of a temporary register. */
 class temp_access {
 public:
@@ -566,6 +570,13 @@ void temp_comp_access::record_read(int line, prog_scope *scope)
       first_read_scope = scope;
    }
 
+   /* If the conditionality of the first write is already resolved then
+    * no further checks are required.
+    */
+   if (conditionality_in_loop_id == write_is_unconditional ||
+       conditionality_in_loop_id == write_is_conditional)
+      return;
+
    /* Check whether we are in a condition within a loop */
    const prog_scope *ifelse_scope = scope->in_ifelse_scope();
    const prog_scope *enclosing_loop;
@@ -612,9 +623,20 @@ void temp_comp_access::record_write(int line, prog_scope *scope)
    if (first_write < 0) {
       first_write = line;
       first_write_scope = scope;
+
+      /* If the first write we encounter is not in a conditional branch, or
+       * the conditional write is not within a loop, then this is to be
+       * considered an unconditional dominant write.
+       */
+      const prog_scope *conditional = scope->enclosing_conditional();
+      if (!conditional || !conditional->innermost_loop()) {
+         conditionality_in_loop_id = write_is_unconditional;
+      }
    }
 
-   if (conditionality_in_loop_id == write_is_conditional)
+   /* The conditionality of the first write is already resolved. */
+   if (conditionality_in_loop_id == write_is_unconditional ||
+       conditionality_in_loop_id == write_is_conditional)
       return;
 
    /* If the nesting depth is larger than the supported level,
index a3b0f0e02f98e0d068e4b856bbf5e3a8c3eb53ec..acebfb829354a67fdd3c90efcab24d90fc9dbec6 100644 (file)
@@ -794,6 +794,30 @@ TEST_F(LifetimeEvaluatorExactTest, WriteInIfElseBranchSecondIfInLoop)
    run (code, temp_lt_expect({{-1,-1}, {2,9}}));
 }
 
+/** Regression test for bug #104803,
+ *  Read and write in if/else path outside loop and later read in conditional
+ *  within a loop. The first write is to be considered the dominant write.
+ */
+TEST_F(LifetimeEvaluatorExactTest, IfElseWriteInBothOutsideLoopReadInElseInLoop)
+{
+   const vector<FakeCodeline> code = {
+      { TGSI_OPCODE_IF, {}, {in0}, {} },
+      {   TGSI_OPCODE_MOV, {1}, {in0}, {} },
+      { TGSI_OPCODE_ELSE, {}, {}, {} },
+      {   TGSI_OPCODE_MOV, {1}, {in1}, {} },
+      { TGSI_OPCODE_ENDIF, {}, {}, {} },
+      { TGSI_OPCODE_BGNLOOP },
+      {   TGSI_OPCODE_IF, {}, {in0}, {} },
+      {     TGSI_OPCODE_MOV, {2}, {in1}, {} },
+      {   TGSI_OPCODE_ELSE, {}, {}, {} },
+      {     TGSI_OPCODE_MOV, {2}, {1}, {} },
+      {   TGSI_OPCODE_ENDIF, {}, {}, {} },
+      { TGSI_OPCODE_ENDLOOP },
+      { TGSI_OPCODE_MOV, {out0}, {2}, {}},
+      { TGSI_OPCODE_END}
+   };
+   run (code, temp_lt_expect({{-1,-1}, {1,11}, {7, 12}}));
+}
 
 /* A continue in the loop is not relevant */
 TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterContinue)