• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
3  *
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:
10  *
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
13  * Software.
14  *
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.
22  *
23  * Authors:
24  *      Vadim Girlin
25  */
26 
27 #define GVN_DEBUG 0
28 
29 #if GVN_DEBUG
30 #define GVN_DUMP(q) do { q } while (0)
31 #else
32 #define GVN_DUMP(q)
33 #endif
34 
35 #include "sb_shader.h"
36 #include "sb_pass.h"
37 #include "sb_sched.h"
38 
39 namespace r600_sb {
40 
visit(node & n,bool enter)41 bool gvn::visit(node& n, bool enter) {
42 	if (enter) {
43 
44 
45 		bool rewrite = true;
46 
47 		if (n.dst[0]->is_agpr()) {
48 			rewrite = false;
49 		}
50 
51 
52 		process_op(n, rewrite);
53 
54 		assert(n.parent);
55 
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
60 
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).
69 
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
74 
75 			assert(!n.src.empty());
76 			value *v = n.src[0];
77 
78 			if (v->is_any_gpr() && v->def)
79 				v->def->flags |= NF_DONT_HOIST;
80 		}
81 
82 	} else {
83 	}
84 	return true;
85 }
86 
visit(cf_node & n,bool enter)87 bool gvn::visit(cf_node& n, bool enter) {
88 	if (enter) {
89 		process_op(n);
90 	} else {
91 	}
92 	return true;
93 }
94 
visit(alu_node & n,bool enter)95 bool gvn::visit(alu_node& n, bool enter) {
96 	if (enter) {
97 		process_op(n);
98 	} else {
99 	}
100 	return true;
101 }
102 
visit(alu_packed_node & n,bool enter)103 bool gvn::visit(alu_packed_node& n, bool enter) {
104 	if (enter) {
105 		process_op(n);
106 	} else {
107 	}
108 	return false;
109 }
110 
visit(fetch_node & n,bool enter)111 bool gvn::visit(fetch_node& n, bool enter) {
112 	if (enter) {
113 		process_op(n);
114 	} else {
115 	}
116 	return true;
117 }
118 
visit(region_node & n,bool enter)119 bool gvn::visit(region_node& n, bool enter) {
120 	if (enter) {
121 // FIXME: loop_phi sources are undefined yet (except theone from the preceding
122 // code), can we handle that somehow?
123 //		if (n.loop_phi)
124 //			run_on(*n.loop_phi);
125 	} else {
126 		if (n.loop_phi)
127 			run_on(*n.loop_phi);
128 
129 		if (n.phi)
130 			run_on(*n.phi);
131 	}
132 	return true;
133 }
134 
process_src(value * & v,bool rewrite)135 bool gvn::process_src(value* &v, bool rewrite) {
136 	if (!v->gvn_source)
137 		sh.vt.add_value(v);
138 
139 	if (rewrite && !v->gvn_source->is_rel()) {
140 		v = v->gvn_source;
141 		return true;
142 	}
143 	return false;
144 }
145 
146 // FIXME: maybe handle it in the scheduler?
process_alu_src_constants(node & n,value * & v)147 void gvn::process_alu_src_constants(node &n, value* &v) {
148 	if (n.src.size() < 3) {
149 		process_src(v, true);
150 		return;
151 	}
152 
153 	if (!v->gvn_source)
154 		sh.vt.add_value(v);
155 
156 	rp_kcache_tracker kc(sh);
157 
158 	if (v->gvn_source->is_kcache())
159 		kc.try_reserve(v->gvn_source->select);
160 
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;
167 					++I) {
168 				value *c = (*I);
169 				if (c && c->is_readonly() && ++const_count == 2) {
170 					process_src(v, false);
171 					return;
172 				}
173 			}
174 		}
175 	}
176 
177 	unsigned kcache_count = 0;
178 	for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
179 		value *c = (*I);
180 
181 		if (c->is_kcache() && (!kc.try_reserve(c->select) || ++kcache_count == 2)) {
182 			process_src(v, false);
183 			return;
184 		}
185 	}
186 	process_src(v, true);
187 }
188 
process_op(node & n,bool rewrite)189 void gvn::process_op(node& n, bool rewrite) {
190 
191 	for(vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
192 		value* &v = *I;
193 		if (v) {
194 			if (v->rel) {
195 				process_src(v->rel, rewrite);
196 			}
197 
198 			if (rewrite && v->gvn_source && v->gvn_source->is_readonly() &&
199 					n.is_any_alu()) {
200 				process_alu_src_constants(n, v);
201 			} else if (rewrite && v->gvn_source && v->gvn_source->is_const() &&
202 					(n.is_fetch_op(FETCH_OP_VFETCH) ||
203 							n.is_fetch_op(FETCH_OP_SEMFETCH)))
204 				process_src(v, false);
205 			else
206 				process_src(v, rewrite);
207 		}
208 	}
209 	if (n.pred)
210 		process_src(n.pred, false);
211 
212 	if (n.type == NT_IF) {
213 		if_node &i = (if_node&)n;
214 		if (i.cond)
215 			process_src(i.cond, false);
216 	}
217 
218 	for(vvec::iterator I = n.dst.begin(), E = n.dst.end(); I != E; ++I) {
219 		value *v = *I;
220 		if (v) {
221 			if (v->rel)
222 				process_src(v->rel, rewrite);
223 			sh.vt.add_value(v);
224 		}
225 	}
226 }
227 
228 } // namespace r600_sb
229