5b4cab5390209d8a09a39a6e6d81e0c394bd6616
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
27 /** @file brw_fs_peephole_predicated_break.cpp
29 * Loops are often structured as
39 * This peephole pass removes the IF and ENDIF instructions and predicates the
40 * BREAK, dropping two instructions from the loop body.
44 fs_visitor::opt_peephole_predicated_break()
46 bool progress
= false;
48 foreach_block (block
, cfg
) {
49 if (block
->start_ip
!= block
->end_ip
)
52 /* BREAK and CONTINUE instructions, by definition, can only be found at
53 * the ends of basic blocks.
55 fs_inst
*jump_inst
= (fs_inst
*)block
->end
;
56 if (jump_inst
->opcode
!= BRW_OPCODE_BREAK
&&
57 jump_inst
->opcode
!= BRW_OPCODE_CONTINUE
)
60 fs_inst
*if_inst
= (fs_inst
*)((bblock_t
*)block
->link
.prev
)->end
;
61 if (if_inst
->opcode
!= BRW_OPCODE_IF
)
64 fs_inst
*endif_inst
= (fs_inst
*)((bblock_t
*)block
->link
.next
)->start
;
65 if (endif_inst
->opcode
!= BRW_OPCODE_ENDIF
)
68 bblock_t
*jump_block
= block
;
69 bblock_t
*if_block
= (bblock_t
*)jump_block
->link
.prev
;
70 bblock_t
*endif_block
= (bblock_t
*)jump_block
->link
.next
;
72 /* For Sandybridge with IF with embedded comparison we need to emit an
73 * instruction to set the flag register.
75 if (brw
->gen
== 6 && if_inst
->conditional_mod
) {
76 fs_inst
*cmp_inst
= CMP(reg_null_d
, if_inst
->src
[0], if_inst
->src
[1],
77 if_inst
->conditional_mod
);
78 if_inst
->insert_before(if_block
, cmp_inst
);
79 jump_inst
->predicate
= BRW_PREDICATE_NORMAL
;
81 jump_inst
->predicate
= if_inst
->predicate
;
82 jump_inst
->predicate_inverse
= if_inst
->predicate_inverse
;
85 bblock_t
*earlier_block
= if_block
;
86 if (if_block
->start_ip
== if_block
->end_ip
) {
87 earlier_block
= (bblock_t
*)if_block
->link
.prev
;
90 if_inst
->remove(if_block
);
92 bblock_t
*later_block
= endif_block
;
93 if (endif_block
->start_ip
== endif_block
->end_ip
) {
94 later_block
= (bblock_t
*)endif_block
->link
.next
;
96 endif_inst
->remove(endif_block
);
98 earlier_block
->children
.make_empty();
99 later_block
->parents
.make_empty();
101 earlier_block
->add_successor(cfg
->mem_ctx
, jump_block
);
102 jump_block
->add_successor(cfg
->mem_ctx
, later_block
);
104 if (earlier_block
->can_combine_with(jump_block
)) {
105 earlier_block
->combine_with(jump_block
);
107 block
= earlier_block
;
114 invalidate_live_intervals();