glsl: fix lower jumps for returns when loop is inside an if
authorTimothy Arceri <tarceri@itsqueeze.com>
Sun, 26 Mar 2017 12:34:13 +0000 (23:34 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Mon, 27 Mar 2017 22:54:31 +0000 (09:54 +1100)
Previously we would just escape the loop and move everything
following the loop inside the if to the else branch of a new if
with a return flag conditional. However everything outside the
if the loop was nested in would still get executed.

Adding a new return to the then branch of the new if fixes this
and we just let a follow pass clean it up if needed.

Fixes:
tests/spec/glsl-1.10/execution/vs-nested-return-sibling-loop.shader_test
tests/spec/glsl-1.10/execution/vs-nested-return-sibling-loop2.shader_test

Cc: "13.0 17.0" <mesa-stable@lists.freedesktop.org>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/compiler/glsl/lower_jumps.cpp

index ed1b6d1..1b893e5 100644 (file)
@@ -932,14 +932,21 @@ lower_continue:
              * break statement if necessary.
              */
             return_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break));
-         else
-            /* Otherwise, all we need to do is ensure that the
-             * instructions that follow are only executed if the
-             * return flag is clear.  We can do that by moving those
-             * instructions into the else clause of the generated if
+         else {
+            /* Otherwise, ensure that the instructions that follow are only
+             * executed if the return flag is clear.  We can do that by moving
+             * those instructions into the else clause of the generated if
              * statement.
              */
             move_outer_block_inside(ir, &return_if->else_instructions);
+
+            /* In case the loop is embeded inside an if add a new return to
+             * the return flag then branch and let a future pass tidy it up.
+             */
+            if (this->function.signature->return_type->is_void())
+               return_if->then_instructions.push_tail(new(ir) ir_return(NULL));
+         }
+
          ir->insert_after(return_if);
       }