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 GVN_DUMP(q) do { q } while (0)
35 #include "sb_shader.h"
41 bool gvn::visit(node
& n
, bool enter
) {
47 if (n
.dst
[0]->is_agpr()) {
52 process_op(n
, rewrite
);
56 if (n
.parent
->subtype
== NST_LOOP_PHI_CONTAINER
) {
57 // There is a problem - sometimes with nested loops
58 // loop counter initialization for inner loop is incorrectly hoisted
59 // out of the outer loop
61 // FIXME not sure if this is enough to fix a problem completely,
62 // possibly more complete fix is needed (anyway, the
63 // problem was seen only in relatively complex
64 // case involving nested loops and
65 // indirect access to loop counters (without proper array info
66 // loop counters may be considered as array elements too),
67 // was not seen in any tests
68 // or real apps when proper array information is available in TGSI).
70 // For now just mark the instructions that initialize loop counters
71 // with DONT_HOIST flag to prevent the insts like MOV r, 0
72 // (initialization of inner loop's counter with const)
73 // from being hoisted out of the outer loop
75 assert(!n
.src
.empty());
78 if (v
->is_any_gpr() && v
->def
)
79 v
->def
->flags
|= NF_DONT_HOIST
;
87 bool gvn::visit(cf_node
& n
, bool enter
) {
95 bool gvn::visit(alu_node
& n
, bool enter
) {
103 bool gvn::visit(alu_packed_node
& n
, bool enter
) {
111 bool gvn::visit(fetch_node
& n
, bool enter
) {
119 bool gvn::visit(region_node
& n
, bool enter
) {
121 // FIXME: loop_phi sources are undefined yet (except theone from the preceding
122 // code), can we handle that somehow?
124 // run_on(*n.loop_phi);
135 bool gvn::process_src(value
* &v
, bool rewrite
) {
139 if (rewrite
&& !v
->gvn_source
->is_rel()) {
146 // FIXME: maybe handle it in the scheduler?
147 void gvn::process_alu_src_constants(node
&n
, value
* &v
) {
148 if (n
.src
.size() < 3) {
149 process_src(v
, true);
156 rp_kcache_tracker
kc(sh
);
158 if (v
->gvn_source
->is_kcache())
159 kc
.try_reserve(v
->gvn_source
->select
);
161 // don't propagate 3rd constant to the trans-only instruction
162 if (!n
.is_alu_packed()) {
163 alu_node
*a
= static_cast<alu_node
*>(&n
);
164 if (a
->bc
.op_ptr
->src_count
== 3 && !(a
->bc
.slot_flags
& AF_V
)) {
165 unsigned const_count
= 0;
166 for (vvec::iterator I
= n
.src
.begin(), E
= n
.src
.end(); I
!= E
;
169 if (c
&& c
->is_readonly() && ++const_count
== 2) {
170 process_src(v
, false);
177 for (vvec::iterator I
= n
.src
.begin(), E
= n
.src
.end(); I
!= E
; ++I
) {
180 if (c
->is_kcache() && !kc
.try_reserve(c
->select
)) {
181 process_src(v
, false);
185 process_src(v
, true);
188 void gvn::process_op(node
& n
, bool rewrite
) {
190 for(vvec::iterator I
= n
.src
.begin(), E
= n
.src
.end(); I
!= E
; ++I
) {
194 process_src(v
->rel
, rewrite
);
197 if (rewrite
&& v
->gvn_source
&& v
->gvn_source
->is_readonly() &&
199 process_alu_src_constants(n
, v
);
200 } else if (rewrite
&& v
->gvn_source
&& v
->gvn_source
->is_const() &&
201 (n
.is_fetch_op(FETCH_OP_VFETCH
) ||
202 n
.is_fetch_op(FETCH_OP_SEMFETCH
)))
203 process_src(v
, false);
205 process_src(v
, rewrite
);
209 process_src(n
.pred
, false);
211 if (n
.type
== NT_IF
) {
212 if_node
&i
= (if_node
&)n
;
214 process_src(i
.cond
, false);
217 for(vvec::iterator I
= n
.dst
.begin(), E
= n
.dst
.end(); I
!= E
; ++I
) {
221 process_src(v
->rel
, rewrite
);
227 } // namespace r600_sb