Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright 2013 Vadim Girlin |
||
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 | #include "sb_shader.h" |
||
28 | #include "sb_pass.h" |
||
29 | |||
30 | namespace r600_sb { |
||
31 | |||
32 | int ra_checker::run() { |
||
33 | |||
34 | rm_stack.clear(); |
||
35 | rm_stack.resize(1); |
||
36 | rm_stk_level = 0; |
||
37 | |||
38 | process_op_dst(sh.root); |
||
39 | |||
40 | run_on(sh.root); |
||
41 | |||
42 | assert(rm_stk_level == 0); |
||
43 | |||
44 | dump_all_errors(); |
||
45 | |||
46 | assert(sh.errors.empty()); |
||
47 | |||
48 | return 0; |
||
49 | } |
||
50 | |||
51 | void ra_checker::dump_error(const error_info &e) { |
||
52 | |||
53 | sblog << "error at : "; |
||
54 | dump::dump_op(e.n); |
||
55 | |||
56 | sblog << "\n"; |
||
57 | sblog << " : " << e.message << "\n"; |
||
58 | } |
||
59 | |||
60 | void ra_checker::dump_all_errors() { |
||
61 | for (error_map::iterator I = sh.errors.begin(), E = sh.errors.end(); |
||
62 | I != E; ++I) { |
||
63 | dump_error(I->second); |
||
64 | } |
||
65 | } |
||
66 | |||
67 | |||
68 | void ra_checker::error(node *n, unsigned id, std::string msg) { |
||
69 | error_info e; |
||
70 | e.n = n; |
||
71 | e.arg_index = id; |
||
72 | e.message = msg; |
||
73 | sh.errors.insert(std::make_pair(n, e)); |
||
74 | } |
||
75 | |||
76 | void ra_checker::push_stack() { |
||
77 | ++rm_stk_level; |
||
78 | if (rm_stack.size() == rm_stk_level) |
||
79 | rm_stack.push_back(rm_stack.back()); |
||
80 | else |
||
81 | rm_stack[rm_stk_level] = rm_stack[rm_stk_level - 1]; |
||
82 | } |
||
83 | |||
84 | void ra_checker::pop_stack() { |
||
85 | --rm_stk_level; |
||
86 | } |
||
87 | |||
88 | void ra_checker::kill_alu_only_regs() { |
||
89 | // TODO |
||
90 | } |
||
91 | |||
92 | void ra_checker::check_value_gpr(node *n, unsigned id, value *v) { |
||
93 | sel_chan gpr = v->gpr; |
||
94 | if (!gpr) { |
||
95 | sb_ostringstream o; |
||
96 | o << "operand value " << *v << " is not allocated"; |
||
97 | error(n, id, o.str()); |
||
98 | return; |
||
99 | } |
||
100 | reg_value_map::iterator F = rmap().find(v->gpr); |
||
101 | if (F == rmap().end()) { |
||
102 | sb_ostringstream o; |
||
103 | o << "operand value " << *v << " was not previously written to its gpr"; |
||
104 | error(n, id, o.str()); |
||
105 | return; |
||
106 | } |
||
107 | if (!F->second->v_equal(v)) { |
||
108 | sb_ostringstream o; |
||
109 | o << "expected operand value " << *v |
||
110 | << ", gpr contains " << *(F->second); |
||
111 | error(n, id, o.str()); |
||
112 | return; |
||
113 | } |
||
114 | |||
115 | |||
116 | } |
||
117 | |||
118 | void ra_checker::check_src_vec(node *n, unsigned id, vvec &vv, bool src) { |
||
119 | |||
120 | for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) { |
||
121 | value *v = *I; |
||
122 | if (!v || !v->is_sgpr()) |
||
123 | continue; |
||
124 | |||
125 | if (v->is_rel()) { |
||
126 | if (!v->rel) { |
||
127 | sb_ostringstream o; |
||
128 | o << "expected relative offset in " << *v; |
||
129 | error(n, id, o.str()); |
||
130 | return; |
||
131 | } |
||
132 | } else if (src) { |
||
133 | check_value_gpr(n, id, v); |
||
134 | } |
||
135 | } |
||
136 | } |
||
137 | |||
138 | void ra_checker::check_op_src(node *n) { |
||
139 | check_src_vec(n, 0, n->dst, false); |
||
140 | check_src_vec(n, 100, n->src, true); |
||
141 | } |
||
142 | |||
143 | void ra_checker::process_op_dst(node *n) { |
||
144 | |||
145 | unsigned id = 0; |
||
146 | |||
147 | for (vvec::iterator I = n->dst.begin(), E = n->dst.end(); I != E; ++I) { |
||
148 | value *v = *I; |
||
149 | |||
150 | ++id; |
||
151 | |||
152 | if (!v) |
||
153 | continue; |
||
154 | |||
155 | if (v->is_sgpr()) { |
||
156 | |||
157 | if (!v->gpr) { |
||
158 | sb_ostringstream o; |
||
159 | o << "destination operand " << *v << " is not allocated"; |
||
160 | error(n, id, o.str()); |
||
161 | return; |
||
162 | } |
||
163 | |||
164 | rmap()[v->gpr] = v; |
||
165 | } else if (v->is_rel()) { |
||
166 | if (v->rel->is_const()) { |
||
167 | rmap()[v->get_final_gpr()] = v; |
||
168 | } else { |
||
169 | unsigned sz = v->array->array_size; |
||
170 | unsigned start = v->array->gpr; |
||
171 | for (unsigned i = 0; i < sz; ++i) { |
||
172 | rmap()[start + (i << 2)] = v; |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | } |
||
177 | } |
||
178 | |||
179 | void ra_checker::check_phi_src(container_node *p, unsigned id) { |
||
180 | for (node_iterator I = p->begin(), E = p->end(); I != E; ++I) { |
||
181 | node *n = *I; |
||
182 | value *s = n->src[id]; |
||
183 | if (s->is_sgpr()) |
||
184 | check_value_gpr(n, id, s); |
||
185 | } |
||
186 | } |
||
187 | |||
188 | void ra_checker::process_phi_dst(container_node *p) { |
||
189 | for (node_iterator I = p->begin(), E = p->end(); I != E; ++I) { |
||
190 | node *n = *I; |
||
191 | process_op_dst(n); |
||
192 | } |
||
193 | } |
||
194 | |||
195 | void ra_checker::check_alu_group(alu_group_node *g) { |
||
196 | |||
197 | for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) { |
||
198 | node *a = *I; |
||
199 | if (!a->is_alu_inst()) { |
||
200 | sb_ostringstream o; |
||
201 | o << "non-alu node inside alu group"; |
||
202 | error(a, 0, o.str()); |
||
203 | return; |
||
204 | } |
||
205 | |||
206 | check_op_src(a); |
||
207 | } |
||
208 | |||
209 | std::fill(prev_dst, prev_dst + 5, (value*)NULL); |
||
210 | |||
211 | for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) { |
||
212 | alu_node *a = static_cast |
||
213 | |||
214 | process_op_dst(a); |
||
215 | |||
216 | unsigned slot = a->bc.slot; |
||
217 | prev_dst[slot] = a->dst[0]; |
||
218 | } |
||
219 | } |
||
220 | |||
221 | void ra_checker::run_on(container_node* c) { |
||
222 | |||
223 | if (c->is_region()) { |
||
224 | region_node *r = static_cast |
||
225 | if (r->loop_phi) { |
||
226 | check_phi_src(r->loop_phi, 0); |
||
227 | process_phi_dst(r->loop_phi); |
||
228 | } |
||
229 | } else if (c->is_depart()) { |
||
230 | |||
231 | push_stack(); |
||
232 | |||
233 | } else if (c->is_repeat()) { |
||
234 | |||
235 | push_stack(); |
||
236 | |||
237 | } |
||
238 | |||
239 | for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) { |
||
240 | node *n = *I; |
||
241 | |||
242 | if(n->is_cf_inst() || n->is_fetch_inst()) { |
||
243 | check_op_src(n); |
||
244 | process_op_dst(n); |
||
245 | } |
||
246 | |||
247 | if (n->is_container()) { |
||
248 | if (n->is_alu_group()) { |
||
249 | check_alu_group(static_cast |
||
250 | } else { |
||
251 | container_node *nc = static_cast |
||
252 | run_on(nc); |
||
253 | } |
||
254 | } |
||
255 | } |
||
256 | |||
257 | if (c->is_depart()) { |
||
258 | depart_node *r = static_cast |
||
259 | check_phi_src(r->target->phi, r->dep_id); |
||
260 | pop_stack(); |
||
261 | } else if (c->is_repeat()) { |
||
262 | repeat_node *r = static_cast |
||
263 | assert (r->target->loop_phi); |
||
264 | |||
265 | pop_stack(); |
||
266 | } else if (c->is_region()) { |
||
267 | region_node *r = static_cast |
||
268 | if (r->phi) |
||
269 | process_phi_dst(r->phi); |
||
270 | } |
||
271 | } |
||
272 | |||
273 | } // namespace r600_sb><>><>>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><>><> |