nir/cf: Remove phi sources if needed in nir_handle_add_jump

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>
This commit is contained in:
Jason Ekstrand 2018-09-21 09:27:48 -05:00
parent 7b0752fb10
commit bfc89c668e

View 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.
*/