nir/opt_if: Fix opt_if_simplification when else branch has jump
Consider the following case:
if ssa_1 {
block block_2:
/* succs: block_4 */
} else {
block block_3:
...
break
/* succs: block_5 */
}
block block_4:
vec1 32 ssa_100 = phi block_2: ssa_2
After block_3 extraction and reinsertion, phi->pred becomes invalid
and isn't updated by reinsertion since it is unreachable from block_3.
Call nir_opt_remove_phis_block before moving block to eliminate single
source phis after the if.
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3282
Fixes: e3e929f8c3
Signed-off-by: Danylo Piliaiev <danylo.piliaiev@globallogic.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5945>
This commit is contained in:

committed by
Marge Bot

parent
3f783a3c50
commit
6f94b3da11
@@ -931,6 +931,17 @@ opt_if_simplification(nir_builder *b, nir_if *nif)
|
||||
nir_block *then_block = nir_if_last_then_block(nif);
|
||||
nir_block *else_block = nir_if_last_else_block(nif);
|
||||
|
||||
if (nir_block_ends_in_jump(else_block)) {
|
||||
/* Even though this if statement has a jump on one side, we may still have
|
||||
* phis afterwards. Single-source phis can be produced by loop unrolling
|
||||
* or dead control-flow passes and are perfectly legal. Run a quick phi
|
||||
* removal on the block after the if to clean up any such phis.
|
||||
*/
|
||||
nir_block *const next_block =
|
||||
nir_cf_node_as_block(nir_cf_node_next(&nif->cf_node));
|
||||
nir_opt_remove_phis_block(next_block);
|
||||
}
|
||||
|
||||
rewrite_phi_predecessor_blocks(nif, then_block, else_block, else_block,
|
||||
then_block);
|
||||
|
||||
|
Reference in New Issue
Block a user