glsl: fix lower jumps for returns when loop is inside an if

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>
This commit is contained in:
Timothy Arceri 2017-03-26 23:34:13 +11:00
parent b640dfcd05
commit c1096b7f1d
1 changed files with 12 additions and 5 deletions

View 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);
}