7e317abe7a7f5d73da0813b756d2eb18fa7944ea
[mesa.git] / src / gallium / drivers / r600 / sb / sb_dump.cpp
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 #include "sb_shader.h"
28 #include "sb_pass.h"
29
30 namespace r600_sb {
31
32 bool dump::visit(node& n, bool enter) {
33 if (enter) {
34 indent();
35 dump_flags(n);
36
37 switch (n.subtype) {
38 case NST_PHI:
39 dump_op(n, "* phi");
40 break;
41 case NST_PSI:
42 dump_op(n, "* psi");
43 break;
44 case NST_COPY:
45 dump_op(n, "* copy");
46 break;
47 default:
48 assert(!"invalid node subtype");
49 break;
50 }
51 sblog << "\n";
52 }
53 return false;
54 }
55
56 bool dump::visit(container_node& n, bool enter) {
57 if (enter) {
58 if (!n.empty()) {
59 indent();
60 dump_flags(n);
61 sblog << "{ ";
62 if (!n.dst.empty()) {
63 sblog << " preloaded inputs [";
64 dump_vec(n.dst);
65 sblog << "] ";
66 }
67 dump_live_values(n, true);
68 }
69 ++level;
70 } else {
71 --level;
72 if (!n.empty()) {
73 indent();
74 sblog << "} ";
75 if (!n.src.empty()) {
76 sblog << " results [";
77 dump_vec(n.src);
78 sblog << "] ";
79 }
80 dump_live_values(n, false);
81 }
82 }
83 return true;
84 }
85
86 bool dump::visit(bb_node& n, bool enter) {
87 if (enter) {
88 indent();
89 dump_flags(n);
90 sblog << "{ BB_" << n.id << " loop_level = " << n.loop_level << " ";
91 dump_live_values(n, true);
92 ++level;
93 } else {
94 --level;
95 indent();
96 sblog << "} end BB_" << n.id << " ";
97 dump_live_values(n, false);
98 }
99 return true;
100 }
101
102 bool dump::visit(alu_group_node& n, bool enter) {
103 if (enter) {
104 indent();
105 dump_flags(n);
106 sblog << "[ ";
107 dump_live_values(n, true);
108
109 ++level;
110 } else {
111 --level;
112
113 indent();
114 sblog << "] ";
115 dump_live_values(n, false);
116 }
117 return true;
118 }
119
120 bool dump::visit(cf_node& n, bool enter) {
121 if (enter) {
122 indent();
123 dump_flags(n);
124 dump_op(n, n.bc.op_ptr->name);
125
126 if (n.bc.op_ptr->flags & CF_BRANCH) {
127 sblog << " @" << (n.bc.addr << 1);
128 }
129
130 dump_common(n);
131 sblog << "\n";
132
133 if (!n.empty()) {
134 indent();
135 sblog << "< ";
136 dump_live_values(n, true);
137 }
138
139 ++level;
140 } else {
141 --level;
142 if (!n.empty()) {
143 indent();
144 sblog << "> ";
145 dump_live_values(n, false);
146 }
147 }
148 return true;
149 }
150
151 bool dump::visit(alu_node& n, bool enter) {
152 if (enter) {
153 indent();
154 dump_flags(n);
155 dump_alu(&n);
156 dump_common(n);
157 sblog << "\n";
158
159 ++level;
160 } else {
161 --level;
162
163 }
164 return true;
165 }
166
167 bool dump::visit(alu_packed_node& n, bool enter) {
168 if (enter) {
169 indent();
170 dump_flags(n);
171 dump_op(n, n.op_ptr()->name);
172 sblog << " ";
173 dump_live_values(n, true);
174
175 ++level;
176 } else {
177 --level;
178 if (!n.live_after.empty()) {
179 indent();
180 dump_live_values(n, false);
181 }
182
183 }
184 // proccess children only if their src/dst aren't moved to this node yet
185 return n.src.empty();
186 }
187
188 bool dump::visit(fetch_node& n, bool enter) {
189 if (enter) {
190 indent();
191 dump_flags(n);
192 dump_op(n, n.bc.op_ptr->name);
193 sblog << "\n";
194
195 ++level;
196 } else {
197 --level;
198 }
199 return true;
200 }
201
202 bool dump::visit(region_node& n, bool enter) {
203 if (enter) {
204 indent();
205 dump_flags(n);
206 sblog << "region #" << n.region_id << " ";
207 dump_common(n);
208
209 if (!n.vars_defined.empty()) {
210 sblog << "vars_defined: ";
211 dump_set(sh, n.vars_defined);
212 }
213
214 dump_live_values(n, true);
215
216 ++level;
217
218 if (n.loop_phi)
219 run_on(*n.loop_phi);
220 } else {
221 --level;
222
223 if (n.phi)
224 run_on(*n.phi);
225
226 indent();
227 dump_live_values(n, false);
228 }
229 return true;
230 }
231
232 bool dump::visit(repeat_node& n, bool enter) {
233 if (enter) {
234 indent();
235 dump_flags(n);
236 sblog << "repeat region #" << n.target->region_id;
237 sblog << (n.empty() ? " " : " after { ");
238 dump_common(n);
239 sblog << " ";
240 dump_live_values(n, true);
241
242 ++level;
243 } else {
244 --level;
245
246 if (!n.empty()) {
247 indent();
248 sblog << "} end_repeat ";
249 dump_live_values(n, false);
250 }
251 }
252 return true;
253 }
254
255 bool dump::visit(depart_node& n, bool enter) {
256 if (enter) {
257 indent();
258 dump_flags(n);
259 sblog << "depart region #" << n.target->region_id;
260 sblog << (n.empty() ? " " : " after { ");
261 dump_common(n);
262 sblog << " ";
263 dump_live_values(n, true);
264
265 ++level;
266 } else {
267 --level;
268 if (!n.empty()) {
269 indent();
270 sblog << "} end_depart ";
271 dump_live_values(n, false);
272 }
273 }
274 return true;
275 }
276
277 bool dump::visit(if_node& n, bool enter) {
278 if (enter) {
279 indent();
280 dump_flags(n);
281 sblog << "if " << *n.cond << " ";
282 dump_common(n);
283 sblog << " ";
284 dump_live_values(n, true);
285
286 indent();
287 sblog <<"{\n";
288
289 ++level;
290 } else {
291 --level;
292 indent();
293 sblog << "} endif ";
294 dump_live_values(n, false);
295 }
296 return true;
297 }
298
299 void dump::indent() {
300 sblog.print_wl("", level * 4);
301 }
302
303 void dump::dump_vec(const vvec & vv) {
304 bool first = true;
305 for(vvec::const_iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
306 value *v = *I;
307 if (!first)
308 sblog << ", ";
309 else
310 first = false;
311
312 if (v) {
313 sblog << *v;
314 } else {
315 sblog << "__";
316 }
317 }
318 }
319
320 void dump::dump_rels(vvec & vv) {
321 for(vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
322 value *v = *I;
323
324 if (!v || !v->is_rel())
325 continue;
326
327 sblog << "\n\t\t\t\t\t";
328 sblog << " rels: " << *v << " : ";
329 dump_vec(v->mdef);
330 sblog << " <= ";
331 dump_vec(v->muse);
332 }
333 }
334
335 void dump::dump_op(node &n, const char *name) {
336
337 if (n.pred) {
338 alu_node &a = static_cast<alu_node&>(n);
339 sblog << (a.bc.pred_sel-2) << " [" << *a.pred << "] ";
340 }
341
342 sblog << name;
343
344 bool has_dst = !n.dst.empty();
345
346 if (n.subtype == NST_CF_INST) {
347 cf_node *c = static_cast<cf_node*>(&n);
348 if (c->bc.op_ptr->flags & CF_EXP) {
349 static const char *exp_type[] = {"PIXEL", "POS ", "PARAM"};
350 sblog << " " << exp_type[c->bc.type] << " " << c->bc.array_base;
351 has_dst = false;
352 } else if (c->bc.op_ptr->flags & CF_STRM) {
353 static const char *exp_type[] = {"WRITE", "WRITE_IND", "WRITE_ACK",
354 "WRITE_IND_ACK"};
355 sblog << " " << exp_type[c->bc.type] << " " << c->bc.array_base
356 << " ES:" << c->bc.elem_size;
357 has_dst = false;
358 }
359 }
360
361 sblog << " ";
362
363 if (has_dst) {
364 dump_vec(n.dst);
365 sblog << ", ";
366 }
367
368 dump_vec(n.src);
369 }
370
371 void dump::dump_set(shader &sh, val_set& v) {
372 sblog << "[";
373 for(val_set::iterator I = v.begin(sh), E = v.end(sh); I != E; ++I) {
374 value *val = *I;
375 sblog << *val << " ";
376 }
377 sblog << "]";
378 }
379
380 void dump::dump_common(node& n) {
381 }
382
383 void dump::dump_flags(node &n) {
384 if (n.flags & NF_DEAD)
385 sblog << "### DEAD ";
386 if (n.flags & NF_REG_CONSTRAINT)
387 sblog << "R_CONS ";
388 if (n.flags & NF_CHAN_CONSTRAINT)
389 sblog << "CH_CONS ";
390 if (n.flags & NF_ALU_4SLOT)
391 sblog << "4S ";
392 }
393
394 void dump::dump_val(value* v) {
395 sblog << *v;
396 }
397
398 void dump::dump_alu(alu_node *n) {
399
400 if (n->is_copy_mov())
401 sblog << "(copy) ";
402
403 if (n->pred) {
404 sblog << (n->bc.pred_sel-2) << " [" << *n->pred << "] ";
405 }
406
407 sblog << n->bc.op_ptr->name;
408
409 if (n->bc.omod) {
410 static const char *omod_str[] = {"", "*2", "*4", "/2"};
411 sblog << omod_str[n->bc.omod];
412 }
413
414 if (n->bc.clamp) {
415 sblog << "_sat";
416 }
417
418 bool has_dst = !n->dst.empty();
419
420 sblog << " ";
421
422 if (has_dst) {
423 dump_vec(n->dst);
424 sblog << ", ";
425 }
426
427 unsigned s = 0;
428 for (vvec::iterator I = n->src.begin(), E = n->src.end(); I != E;
429 ++I, ++s) {
430
431 bc_alu_src &src = n->bc.src[s];
432
433 if (src.neg)
434 sblog << "-";
435
436 if (src.abs)
437 sblog << "|";
438
439 dump_val(*I);
440
441 if (src.abs)
442 sblog << "|";
443
444 if (I + 1 != E)
445 sblog << ", ";
446 }
447
448 dump_rels(n->dst);
449 dump_rels(n->src);
450
451 }
452
453 void dump::dump_op(node* n) {
454 if (n->type == NT_IF) {
455 dump_op(*n, "IF ");
456 return;
457 }
458
459 switch(n->subtype) {
460 case NST_ALU_INST:
461 dump_alu(static_cast<alu_node*>(n));
462 break;
463 case NST_FETCH_INST:
464 dump_op(*n, static_cast<fetch_node*>(n)->bc.op_ptr->name);
465 break;
466 case NST_CF_INST:
467 case NST_ALU_CLAUSE:
468 case NST_TEX_CLAUSE:
469 case NST_VTX_CLAUSE:
470 dump_op(*n, static_cast<cf_node*>(n)->bc.op_ptr->name);
471 break;
472 case NST_ALU_PACKED_INST:
473 dump_op(*n, static_cast<alu_packed_node*>(n)->op_ptr()->name);
474 break;
475 case NST_PHI:
476 dump_op(*n, "PHI");
477 break;
478 case NST_PSI:
479 dump_op(*n, "PSI");
480 break;
481 case NST_COPY:
482 dump_op(*n, "COPY");
483 break;
484 default:
485 dump_op(*n, "??unknown_op");
486 }
487 }
488
489 void dump::dump_op_list(container_node* c) {
490 for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) {
491 dump_op(*I);
492 sblog << "\n";
493 }
494 }
495
496 void dump::dump_queue(sched_queue& q) {
497 for (sched_queue::iterator I = q.begin(), E = q.end(); I != E; ++I) {
498 dump_op(*I);
499 sblog << "\n";
500 }
501 }
502
503 void dump::dump_live_values(container_node &n, bool before) {
504 if (before) {
505 if (!n.live_before.empty()) {
506 sblog << "live_before: ";
507 dump_set(sh, n.live_before);
508 }
509 } else {
510 if (!n.live_after.empty()) {
511 sblog << "live_after: ";
512 dump_set(sh, n.live_after);
513 }
514 }
515 sblog << "\n";
516 }
517
518 } // namespace r600_sb