aco: fix fall-through test in try_remove_simple_block() with back-edges
authorRhys Perry <pendingchaos02@gmail.com>
Fri, 17 Jan 2020 20:08:34 +0000 (20:08 +0000)
committerMarge Bot <eric+marge@anholt.net>
Mon, 20 Jan 2020 11:51:45 +0000 (11:51 +0000)
3bca0af2 enhanced empty block determination which exposed this bug and
created an infinite loop in a Guild Wars 2 shader.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Fixes: 3bca0af25dbf6d6b162463138100abb20bc1a1cc
     ('aco: ignore parallelcopies to the same register on jump threading')

Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2364
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3452>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3452>

src/amd/compiler/aco_ssa_elimination.cpp

index 94f5a1ade8384ba0816eb9ef0464375b939c0b2c..23963d5b95caa09ff66e525222d6120c1bae6b22 100644 (file)
@@ -207,7 +207,7 @@ void try_remove_simple_block(ssa_elimination_ctx& ctx, Block* block)
       branch->opcode = aco_opcode::p_branch;
    } else if (branch->target[1] == block->index) {
       /* check if there is a fall-through path from block to succ */
-      bool falls_through = true;
+      bool falls_through = block->index < succ.index;
       for (unsigned j = block->index + 1; falls_through && j < succ.index; j++) {
          assert(ctx.program->blocks[j].index == j);
          if (!ctx.program->blocks[j].instructions.empty())
@@ -217,6 +217,8 @@ void try_remove_simple_block(ssa_elimination_ctx& ctx, Block* block)
          branch->target[1] = succ.index;
       } else {
          /* check if there is a fall-through path for the alternative target */
+         if (block->index >= branch->target[0])
+            return;
          for (unsigned j = block->index + 1; j < branch->target[0]; j++) {
             if (!ctx.program->blocks[j].instructions.empty())
                return;