summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConnor Abbott <[email protected]>2015-07-21 19:54:26 -0700
committerKenneth Graunke <[email protected]>2015-08-24 13:31:42 -0700
commit633cbbc0682b1cec3107398a21a057697e8572aa (patch)
treeb63a5b1d23d59e843d082370b8acf877bfa78013
parent940873bf22c90db79d065f14ff44dab12415feb0 (diff)
nir/cf: handle jumps better in stitch_blocks()
In particular, handle the case where the earlier block ends in a jump and the later block is empty. In that case, we want to preserve the jump and remove any traces of the later block. Before, we would only hit this case when removing a control flow node after a jump, which wasn't a common occurance, but we'll need it to handle inserting a control flow list which ends in a jump, which should be more common/useful. Signed-off-by: Connor Abbott <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r--src/glsl/nir/nir_control_flow.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/glsl/nir/nir_control_flow.c b/src/glsl/nir/nir_control_flow.c
index 1f2a681f258..8a4a0bf5f9d 100644
--- a/src/glsl/nir/nir_control_flow.c
+++ b/src/glsl/nir/nir_control_flow.c
@@ -706,14 +706,24 @@ stitch_blocks(nir_block *before, nir_block *after)
* TODO: special case when before is empty and after isn't?
*/
- move_successors(after, before);
+ if (block_ends_in_jump(before)) {
+ assert(exec_list_is_empty(&after->instr_list));
+ if (after->successors[0])
+ remove_phi_src(after->successors[0], after);
+ if (after->successors[1])
+ remove_phi_src(after->successors[1], after);
+ unlink_block_successors(after);
+ exec_node_remove(&after->cf_node.node);
+ } else {
+ move_successors(after, before);
- foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
- instr->block = before;
- }
+ foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
+ instr->block = before;
+ }
- exec_list_append(&before->instr_list, &after->instr_list);
- exec_node_remove(&after->cf_node.node);
+ exec_list_append(&before->instr_list, &after->instr_list);
+ exec_node_remove(&after->cf_node.node);
+ }
}