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