nir/opt_if: Clean up single-src phis in opt_if_loop_terminator
authorJason Ekstrand <jason@jlekstrand.net>
Wed, 10 Jul 2019 20:14:42 +0000 (15:14 -0500)
committerJason Ekstrand <jason@jlekstrand.net>
Mon, 15 Jul 2019 19:58:51 +0000 (19:58 +0000)
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111071
Fixes: 2a74296f24ba "nir: add opt_if_loop_terminator()"
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
src/compiler/nir/nir.h
src/compiler/nir/nir_opt_if.c
src/compiler/nir/nir_opt_remove_phis.c

index bc7ae1cc03e374a684a659633ff83e9c72b26c4b..2719087e9a45aa521d34070d9be28e7172ebf2f5 100644 (file)
@@ -3882,6 +3882,7 @@ bool nir_opt_peephole_select(nir_shader *shader, unsigned limit,
 bool nir_opt_rematerialize_compares(nir_shader *shader);
 
 bool nir_opt_remove_phis(nir_shader *shader);
+bool nir_opt_remove_phis_block(nir_block *block);
 
 bool nir_opt_shrink_load(nir_shader *shader);
 
index 6d488bd76a38ddbe05f66d0a7657eb568b09f2e4..e360c274bc92000d360bce5571a017f4daf9c968 100644 (file)
@@ -1039,6 +1039,13 @@ opt_if_loop_terminator(nir_if *nif)
    if (!nir_is_trivial_loop_if(nif, break_blk))
       return false;
 
+   /* 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_opt_remove_phis_block(nir_cf_node_as_block(nir_cf_node_next(&nif->cf_node)));
+
    /* Finally, move the continue from branch after the if-statement. */
    nir_cf_list tmp;
    nir_cf_extract(&tmp, nir_before_block(first_continue_from_blk),
index dd557396ec147d38db9e74eece39991d3030f0fc..a31861167986d6ba956f350803133761d0a052b4 100644 (file)
@@ -137,6 +137,14 @@ remove_phis_block(nir_block *block, nir_builder *b)
    return progress;
 }
 
+bool
+nir_opt_remove_phis_block(nir_block *block)
+{
+   nir_builder b;
+   nir_builder_init(&b, nir_cf_node_get_function(&block->cf_node));
+   return remove_phis_block(block, &b);
+}
+
 static bool
 nir_opt_remove_phis_impl(nir_function_impl *impl)
 {