2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #define PPH_DUMP(q) do { q } while (0)
35 #include "sb_shader.h"
47 void peephole::run_on(container_node
* c
) {
49 for (node_iterator I
= c
->begin(), E
= c
->end(); I
!= E
; ++I
) {
52 if (n
->is_container())
53 run_on(static_cast<container_node
*>(n
));
56 if (n
->is_alu_inst()) {
57 alu_node
*a
= static_cast<alu_node
*>(n
);
59 if (a
->bc
.op_ptr
->flags
&
60 (AF_PRED
| AF_SET
| AF_CMOV
| AF_KILL
)) {
62 } else if (a
->bc
.op
== ALU_OP1_FLT_TO_INT
) {
65 if (get_bool_flt_to_int_source(s
)) {
66 convert_float_setcc(a
, s
);
74 void peephole::optimize_cc_op(alu_node
* a
) {
75 unsigned aflags
= a
->bc
.op_ptr
->flags
;
77 if (aflags
& (AF_PRED
| AF_SET
| AF_KILL
)) {
79 } else if (aflags
& AF_CMOV
) {
84 void peephole::convert_float_setcc(alu_node
*f2i
, alu_node
*s
) {
85 alu_node
*ns
= sh
.clone(s
);
87 ns
->dst
[0] = f2i
->dst
[0];
89 ns
->bc
.set_op(ns
->bc
.op
+ (ALU_OP2_SETE_DX10
- ALU_OP2_SETE
));
90 f2i
->insert_after(ns
);
94 void peephole::optimize_cc_op2(alu_node
* a
) {
96 unsigned flags
= a
->bc
.op_ptr
->flags
;
97 unsigned cc
= flags
& AF_CC_MASK
;
99 if ((cc
!= AF_CC_E
&& cc
!= AF_CC_NE
) || a
->pred
)
102 unsigned cmp_type
= flags
& AF_CMP_TYPE_MASK
;
103 unsigned dst_type
= flags
& AF_DST_TYPE_MASK
;
105 int op_kind
= (flags
& AF_PRED
) ? 1 :
106 (flags
& AF_SET
) ? 2 :
107 (flags
& AF_KILL
) ? 3 : 0;
109 bool swapped
= false;
111 if (a
->src
[0]->is_const() && a
->src
[0]->literal_value
== literal(0)) {
112 std::swap(a
->src
[0],a
->src
[1]);
116 if (swapped
|| (a
->src
[1]->is_const() &&
117 a
->src
[1]->literal_value
== literal(0))) {
119 value
*s
= a
->src
[0];
121 bool_op_info bop
= {};
129 if (!get_bool_op_info(s
, bop
))
133 bop
.invert
= !bop
.invert
;
135 bool swap_args
= false;
137 cc
= bop
.n
->bc
.op_ptr
->flags
& AF_CC_MASK
;
140 cc
= invert_setcc_condition(cc
, swap_args
);
143 assert(cmp_type
!= AF_FLOAT_CMP
);
144 cmp_type
= AF_FLOAT_CMP
;
148 sblog
<< "boi node: ";
149 dump::dump_op(bop
.n
);
150 sblog
<< " invert: " << bop
.invert
<< " int_cvt: " << bop
.int_cvt
;
158 newop
= get_predsetcc_op(cc
, cmp_type
);
161 newop
= get_setcc_op(cc
, cmp_type
, dst_type
!= AF_FLOAT_DST
);
164 newop
= get_killcc_op(cc
, cmp_type
);
168 assert(!"invalid op kind");
175 a
->src
[0] = bop
.n
->src
[1];
176 a
->src
[1] = bop
.n
->src
[0];
177 a
->bc
.src
[0] = bop
.n
->bc
.src
[1];
178 a
->bc
.src
[1] = bop
.n
->bc
.src
[0];
181 a
->src
[0] = bop
.n
->src
[0];
182 a
->src
[1] = bop
.n
->src
[1];
183 a
->bc
.src
[0] = bop
.n
->bc
.src
[0];
184 a
->bc
.src
[1] = bop
.n
->bc
.src
[1];
189 void peephole::optimize_CNDcc_op(alu_node
* a
) {
194 bool peephole::get_bool_flt_to_int_source(alu_node
* &a
) {
196 if (a
->bc
.op
== ALU_OP1_FLT_TO_INT
) {
198 if (a
->bc
.src
[0].neg
|| a
->bc
.src
[0].abs
|| a
->bc
.src
[0].rel
)
201 value
*s
= a
->src
[0];
202 if (!s
|| !s
->def
|| !s
->def
->is_alu_inst())
205 alu_node
*dn
= static_cast<alu_node
*>(s
->def
);
207 if (dn
->is_alu_op(ALU_OP1_TRUNC
)) {
209 if (!s
|| !s
->def
|| !s
->def
->is_alu_inst())
212 if (dn
->bc
.src
[0].neg
!= 1 || dn
->bc
.src
[0].abs
!= 0 ||
213 dn
->bc
.src
[0].rel
!= 0) {
217 dn
= static_cast<alu_node
*>(s
->def
);
221 if (dn
->bc
.op_ptr
->flags
& AF_SET
) {
229 bool peephole::get_bool_op_info(value
* b
, bool_op_info
& bop
) {
233 if (!d
|| !d
->is_alu_inst())
236 alu_node
*dn
= static_cast<alu_node
*>(d
);
238 if (dn
->bc
.op_ptr
->flags
& AF_SET
) {
241 if (dn
->bc
.op_ptr
->flags
& AF_DX10
)
247 if (get_bool_flt_to_int_source(dn
)) {
256 } // namespace r600_sb