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
39 dead_control_flow_eliminate(backend_shader
*s
)
41 bool progress
= false;
43 foreach_block_safe (block
, s
->cfg
) {
44 bblock_t
*if_block
= NULL
, *else_block
= NULL
, *endif_block
= block
;
47 /* ENDIF instructions, by definition, can only be found at the start of
50 backend_instruction
*endif_inst
= endif_block
->start();
51 if (endif_inst
->opcode
!= BRW_OPCODE_ENDIF
)
54 backend_instruction
*if_inst
= NULL
, *else_inst
= NULL
;
55 backend_instruction
*prev_inst
= endif_block
->prev()->end();
56 if (prev_inst
->opcode
== BRW_OPCODE_ELSE
) {
57 else_inst
= prev_inst
;
58 else_block
= endif_block
->prev();
61 if (else_block
->start_ip
== else_block
->end_ip
)
62 prev_inst
= else_block
->prev()->end();
65 if (prev_inst
->opcode
== BRW_OPCODE_IF
) {
67 if_block
= else_block
!= NULL
? else_block
->prev()
68 : endif_block
->prev();
71 /* Don't remove the ENDIF if we didn't find a dead IF. */
76 bblock_t
*earlier_block
= NULL
, *later_block
= NULL
;
79 if (if_block
->start_ip
== if_block
->end_ip
) {
80 earlier_block
= if_block
->prev();
82 earlier_block
= if_block
;
84 if_inst
->remove(if_block
);
88 else_inst
->remove(else_block
);
92 if (endif_block
->start_ip
== endif_block
->end_ip
) {
93 later_block
= endif_block
->next();
95 later_block
= endif_block
;
97 endif_inst
->remove(endif_block
);
100 assert((earlier_block
== NULL
) == (later_block
== NULL
));
101 if (earlier_block
&& earlier_block
->can_combine_with(later_block
)) {
102 earlier_block
->combine_with(later_block
);
104 /* If ENDIF was in its own block, then we've now deleted it and
105 * merged the two surrounding blocks, the latter of which the
106 * __next block pointer was pointing to.
108 if (endif_block
!= later_block
) {
109 __next
= earlier_block
->next();
118 s
->invalidate_live_intervals();