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"
34 /* Look for and eliminate dead control flow:
37 * - else in else/endif
38 * - then in if/else/endif
41 dead_control_flow_eliminate(backend_shader
*s
)
43 bool progress
= false;
45 foreach_block_safe (block
, s
->cfg
) {
46 bblock_t
*prev_block
= block
->prev();
51 backend_instruction
*const inst
= block
->start();
52 backend_instruction
*const prev_inst
= prev_block
->end();
54 /* ENDIF instructions, by definition, can only be found at the start of
57 if (inst
->opcode
== BRW_OPCODE_ENDIF
&&
58 prev_inst
->opcode
== BRW_OPCODE_ELSE
) {
59 bblock_t
*const else_block
= prev_block
;
60 backend_instruction
*const else_inst
= prev_inst
;
62 else_inst
->remove(else_block
);
64 } else if (inst
->opcode
== BRW_OPCODE_ENDIF
&&
65 prev_inst
->opcode
== BRW_OPCODE_IF
) {
66 bblock_t
*const endif_block
= block
;
67 bblock_t
*const if_block
= prev_block
;
68 backend_instruction
*const endif_inst
= inst
;
69 backend_instruction
*const if_inst
= prev_inst
;
71 bblock_t
*earlier_block
= NULL
, *later_block
= NULL
;
73 if (if_block
->start_ip
== if_block
->end_ip
) {
74 earlier_block
= if_block
->prev();
76 earlier_block
= if_block
;
78 if_inst
->remove(if_block
);
80 if (endif_block
->start_ip
== endif_block
->end_ip
) {
81 later_block
= endif_block
->next();
83 later_block
= endif_block
;
85 endif_inst
->remove(endif_block
);
87 assert((earlier_block
== NULL
) == (later_block
== NULL
));
88 if (earlier_block
&& earlier_block
->can_combine_with(later_block
)) {
89 earlier_block
->combine_with(later_block
);
91 /* If ENDIF was in its own block, then we've now deleted it and
92 * merged the two surrounding blocks, the latter of which the
93 * __next block pointer was pointing to.
95 if (endif_block
!= later_block
) {
96 __next
= earlier_block
->next();
101 } else if (inst
->opcode
== BRW_OPCODE_ELSE
&&
102 prev_inst
->opcode
== BRW_OPCODE_IF
) {
103 bblock_t
*const else_block
= block
;
104 backend_instruction
*const if_inst
= prev_inst
;
105 backend_instruction
*const else_inst
= inst
;
107 /* Since the else-branch is becoming the new then-branch, the
108 * condition has to be inverted.
110 if_inst
->predicate_inverse
= !if_inst
->predicate_inverse
;
111 else_inst
->remove(else_block
);
118 s
->invalidate_analysis(DEPENDENCY_BLOCKS
| DEPENDENCY_INSTRUCTIONS
);