2 * Copyright © 2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 /** @file brw_dead_control_flow.cpp
26 * This file implements the dead control flow elimination optimization pass.
29 #include "brw_shader.h"
32 /* Look for and eliminate dead control flow:
35 * - else in else/endif
36 * - then in if/else/endif
39 dead_control_flow_eliminate(backend_shader
*s
)
41 bool progress
= false;
43 foreach_block_safe (block
, s
->cfg
) {
44 bblock_t
*prev_block
= block
->prev();
49 backend_instruction
*const inst
= block
->start();
50 backend_instruction
*const prev_inst
= prev_block
->end();
52 /* ENDIF instructions, by definition, can only be found at the start of
55 if (inst
->opcode
== BRW_OPCODE_ENDIF
&&
56 prev_inst
->opcode
== BRW_OPCODE_ELSE
) {
57 bblock_t
*const else_block
= prev_block
;
58 backend_instruction
*const else_inst
= prev_inst
;
60 else_inst
->remove(else_block
);
62 } else if (inst
->opcode
== BRW_OPCODE_ENDIF
&&
63 prev_inst
->opcode
== BRW_OPCODE_IF
) {
64 bblock_t
*const endif_block
= block
;
65 bblock_t
*const if_block
= prev_block
;
66 backend_instruction
*const endif_inst
= inst
;
67 backend_instruction
*const if_inst
= prev_inst
;
69 bblock_t
*earlier_block
= NULL
, *later_block
= NULL
;
71 if (if_block
->start_ip
== if_block
->end_ip
) {
72 earlier_block
= if_block
->prev();
74 earlier_block
= if_block
;
76 if_inst
->remove(if_block
);
78 if (endif_block
->start_ip
== endif_block
->end_ip
) {
79 later_block
= endif_block
->next();
81 later_block
= endif_block
;
83 endif_inst
->remove(endif_block
);
85 assert((earlier_block
== NULL
) == (later_block
== NULL
));
86 if (earlier_block
&& earlier_block
->can_combine_with(later_block
)) {
87 earlier_block
->combine_with(later_block
);
89 /* If ENDIF was in its own block, then we've now deleted it and
90 * merged the two surrounding blocks, the latter of which the
91 * __next block pointer was pointing to.
93 if (endif_block
!= later_block
) {
94 __next
= earlier_block
->next();
99 } else if (inst
->opcode
== BRW_OPCODE_ELSE
&&
100 prev_inst
->opcode
== BRW_OPCODE_IF
) {
101 bblock_t
*const else_block
= block
;
102 backend_instruction
*const if_inst
= prev_inst
;
103 backend_instruction
*const else_inst
= inst
;
105 /* Since the else-branch is becoming the new then-branch, the
106 * condition has to be inverted.
108 if_inst
->predicate_inverse
= !if_inst
->predicate_inverse
;
109 else_inst
->remove(else_block
);
116 s
->invalidate_live_intervals();