nir/cf: Don't break outer-block successors in split_block_beginning().
authorKenneth Graunke <kenneth@whitecape.org>
Thu, 3 Sep 2015 07:33:50 +0000 (00:33 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 23 Sep 2015 17:59:59 +0000 (10:59 -0700)
commit9674c76c0e473a3edbc45f935ea88afd64024325
treed96874854f2d4dcde305124827109ca1a7342c53
parente2637db618b868682e1c996b3c6394c2e82963f1
nir/cf: Don't break outer-block successors in split_block_beginning().

Consider the following NIR:

   block block_0;
   /* succs: block_1 block_2 */
   if (...) {
      block block_1;
      ...
   } else {
      block block_2;
   }

Calling split_block_beginning() on block_1 would break block_0's
successors:  link_block() sets both successors of a block, so calling
link_block(block_0, new_block, NULL) would throw away the second
successor, leaving only /* succ: new_block */.  This is invalid: the
block before an if statement must have two successors.

Changing the call to link_block(pred, new_block, pred->successors[0])
would correctly leave both successors in place, but because unlink_block
may shift successor[1] to successor[0], it may not preserve the original
order.  NIR maintains a convention that successor[0] must point to the
"then" block, while successor[1] points to the "else" block, so we need
to take care to preserve this ordering.

This patch creates a new function that swaps out one successor for
another, preserving the ordering.  It then uses this to fix the issue.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@intel.com>
src/glsl/nir/nir_control_flow.c