nir/cf: Remove phi sources if needed in nir_handle_add_jump
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 21 Sep 2018 14:27:48 +0000 (09:27 -0500)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 2 Oct 2018 15:24:56 +0000 (10:24 -0500)
If the block in which the jump is inserted is the predecessor of a phi
then we need to remove phi sources otherwise the phi may end up with
things improperly connected.  This fixes the following CTS test when
dEQP is run with SPIR-V optimization recipe 1:

dEQP-VK.glsl.functions.control_flow.return_in_nested_loop_vertex

Cc: mesa-stable@lists.freedesktop.org
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
src/compiler/nir/nir_control_flow.c

index 3b0a0f1a5b092ef3671daa584eb8c6d5b69fb661..92e92c5dea161276a4ba60e210a81bbbb670557c 100644 (file)
@@ -437,6 +437,23 @@ nearest_loop(nir_cf_node *node)
    return nir_cf_node_as_loop(node);
 }
 
+static void
+remove_phi_src(nir_block *block, nir_block *pred)
+{
+   nir_foreach_instr(instr, block) {
+      if (instr->type != nir_instr_type_phi)
+         break;
+
+      nir_phi_instr *phi = nir_instr_as_phi(instr);
+      nir_foreach_phi_src_safe(src, phi) {
+         if (src->pred == pred) {
+            list_del(&src->src.use_link);
+            exec_node_remove(&src->node);
+         }
+      }
+   }
+}
+
 /*
  * update the CFG after a jump instruction has been added to the end of a block
  */
@@ -447,6 +464,10 @@ nir_handle_add_jump(nir_block *block)
    nir_instr *instr = nir_block_last_instr(block);
    nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
 
+   if (block->successors[0])
+      remove_phi_src(block->successors[0], block);
+   if (block->successors[1])
+      remove_phi_src(block->successors[1], block);
    unlink_block_successors(block);
 
    nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
@@ -470,23 +491,6 @@ nir_handle_add_jump(nir_block *block)
    }
 }
 
-static void
-remove_phi_src(nir_block *block, nir_block *pred)
-{
-   nir_foreach_instr(instr, block) {
-      if (instr->type != nir_instr_type_phi)
-         break;
-
-      nir_phi_instr *phi = nir_instr_as_phi(instr);
-      nir_foreach_phi_src_safe(src, phi) {
-         if (src->pred == pred) {
-            list_del(&src->src.use_link);
-            exec_node_remove(&src->node);
-         }
-      }
-   }
-}
-
 /* Removes the successor of a block with a jump. Note that the jump to be
  * eliminated may be free-floating.
  */