1 /*
2 * Copyright © 2014 Rob Clark <robclark@freedesktop.org>
3 * SPDX-License-Identifier: MIT
4 *
5 * Authors:
6 * Rob Clark <robclark@freedesktop.org>
7 */
8
9 #include <stdarg.h>
10 #include <stdio.h>
11
12 #include "util/log.h"
13 #include "ir3.h"
14
15 #define PTRID(x) ((unsigned long)(x))
16
17 /* ansi escape sequences: */
18 #define RESET "\x1b[0m"
19 #define RED "\x1b[0;31m"
20 #define GREEN "\x1b[0;32m"
21 #define YELLOW "\x1b[0;33m"
22 #define BLUE "\x1b[0;34m"
23 #define MAGENTA "\x1b[0;35m"
24
25 /* syntax coloring, mostly to make it easier to see different sorts of
26 * srcs (immediate, constant, ssa, array, ...)
27 */
28 #define SYN_REG(x) RED x RESET
29 #define SYN_IMMED(x) GREEN x RESET
30 #define SYN_CONST(x) GREEN x RESET
31 #define SYN_RT(x) YELLOW x RESET
32 #define SYN_SSA(x) BLUE x RESET
33 #define SYN_ARRAY(x) MAGENTA x RESET
34
35 static const char *
type_name(type_t type)36 type_name(type_t type)
37 {
38 static const char *type_names[] = {
39 /* clang-format off */
40 [TYPE_F16] = "f16",
41 [TYPE_F32] = "f32",
42 [TYPE_U16] = "u16",
43 [TYPE_U32] = "u32",
44 [TYPE_S16] = "s16",
45 [TYPE_S32] = "s32",
46 [TYPE_U8] = "u8",
47 [TYPE_U8_32] = "u8_32",
48 /* clang-format on */
49 };
50 return type_names[type];
51 }
52
53 static void
print_instr_name(struct log_stream * stream,struct ir3_instruction * instr,bool flags)54 print_instr_name(struct log_stream *stream, struct ir3_instruction *instr,
55 bool flags)
56 {
57 if (!instr)
58 return;
59 #if MESA_DEBUG
60 mesa_log_stream_printf(stream, "%04u:", instr->serialno);
61 #endif
62 mesa_log_stream_printf(stream, "%04u:", instr->ip);
63 if (instr->flags & IR3_INSTR_UNUSED) {
64 mesa_log_stream_printf(stream, "XXX: ");
65 } else {
66 mesa_log_stream_printf(stream, "%03u: ", instr->use_count);
67 }
68
69 if (flags) {
70 mesa_log_stream_printf(stream, "\t");
71 if (instr->flags & IR3_INSTR_SY)
72 mesa_log_stream_printf(stream, "(sy)");
73 if (instr->flags & IR3_INSTR_SS)
74 mesa_log_stream_printf(stream, "(ss)");
75 if (instr->flags & IR3_INSTR_JP)
76 mesa_log_stream_printf(stream, "(jp)");
77 if (instr->repeat)
78 mesa_log_stream_printf(stream, "(rpt%d)", instr->repeat);
79 if (instr->nop)
80 mesa_log_stream_printf(stream, "(nop%d)", instr->nop);
81 if (instr->flags & IR3_INSTR_UL)
82 mesa_log_stream_printf(stream, "(ul)");
83 if (instr->flags & IR3_INSTR_SAT)
84 mesa_log_stream_printf(stream, "(sat)");
85 } else {
86 mesa_log_stream_printf(stream, " ");
87 }
88
89 if (is_meta(instr)) {
90 switch (instr->opc) {
91 case OPC_META_INPUT:
92 mesa_log_stream_printf(stream, "_meta:in");
93 break;
94 case OPC_META_SPLIT:
95 mesa_log_stream_printf(stream, "_meta:split");
96 break;
97 case OPC_META_COLLECT:
98 mesa_log_stream_printf(stream, "_meta:collect");
99 break;
100 case OPC_META_TEX_PREFETCH:
101 mesa_log_stream_printf(stream, "_meta:tex_prefetch");
102 break;
103 case OPC_META_PARALLEL_COPY:
104 mesa_log_stream_printf(stream, "_meta:parallel_copy");
105 break;
106 case OPC_META_PHI:
107 mesa_log_stream_printf(stream, "_meta:phi");
108 break;
109
110 /* shouldn't hit here.. just for debugging: */
111 default:
112 mesa_log_stream_printf(stream, "_meta:%d", instr->opc);
113 break;
114 }
115 } else if (opc_cat(instr->opc) == 1) {
116 if (instr->opc == OPC_MOV) {
117 if (instr->cat1.src_type == instr->cat1.dst_type)
118 mesa_log_stream_printf(stream, "mov");
119 else
120 mesa_log_stream_printf(stream, "cov");
121 } else {
122 mesa_log_stream_printf(stream, "%s",
123 disasm_a3xx_instr_name(instr->opc));
124 }
125
126 if (instr->opc == OPC_SCAN_MACRO ||
127 instr->opc == OPC_SCAN_CLUSTERS_MACRO) {
128 switch (instr->cat1.reduce_op) {
129 case REDUCE_OP_ADD_U:
130 mesa_log_stream_printf(stream, ".add.u");
131 break;
132 case REDUCE_OP_ADD_F:
133 mesa_log_stream_printf(stream, ".add.f");
134 break;
135 case REDUCE_OP_MUL_U:
136 mesa_log_stream_printf(stream, ".mul.u");
137 break;
138 case REDUCE_OP_MUL_F:
139 mesa_log_stream_printf(stream, ".mul.f");
140 break;
141 case REDUCE_OP_MIN_U:
142 mesa_log_stream_printf(stream, ".min.u");
143 break;
144 case REDUCE_OP_MIN_S:
145 mesa_log_stream_printf(stream, ".min.s");
146 break;
147 case REDUCE_OP_MIN_F:
148 mesa_log_stream_printf(stream, ".min.f");
149 break;
150 case REDUCE_OP_MAX_U:
151 mesa_log_stream_printf(stream, ".max.u");
152 break;
153 case REDUCE_OP_MAX_S:
154 mesa_log_stream_printf(stream, ".max.s");
155 break;
156 case REDUCE_OP_MAX_F:
157 mesa_log_stream_printf(stream, ".max.f");
158 break;
159 case REDUCE_OP_AND_B:
160 mesa_log_stream_printf(stream, ".and.b");
161 break;
162 case REDUCE_OP_OR_B:
163 mesa_log_stream_printf(stream, ".or.b");
164 break;
165 case REDUCE_OP_XOR_B:
166 mesa_log_stream_printf(stream, ".xor.b");
167 break;
168 }
169 }
170
171 if (instr->opc != OPC_MOVMSK && instr->opc != OPC_SCAN_MACRO &&
172 instr->opc != OPC_PUSH_CONSTS_LOAD_MACRO) {
173 mesa_log_stream_printf(stream, ".%s%s",
174 type_name(instr->cat1.src_type),
175 type_name(instr->cat1.dst_type));
176 }
177 } else {
178 mesa_log_stream_printf(stream, "%s", disasm_a3xx_instr_name(instr->opc));
179 if (instr->flags & IR3_INSTR_3D)
180 mesa_log_stream_printf(stream, ".3d");
181 if (instr->flags & IR3_INSTR_A)
182 mesa_log_stream_printf(stream, ".a");
183 if (instr->flags & IR3_INSTR_O)
184 mesa_log_stream_printf(stream, ".o");
185 if (instr->flags & IR3_INSTR_P)
186 mesa_log_stream_printf(stream, ".p");
187 if (instr->flags & IR3_INSTR_S)
188 mesa_log_stream_printf(stream, ".s");
189 if (instr->flags & IR3_INSTR_V)
190 mesa_log_stream_printf(stream, ".v");
191 if (instr->flags & IR3_INSTR_A1EN)
192 mesa_log_stream_printf(stream, ".a1en");
193 if (instr->flags & IR3_INSTR_U)
194 mesa_log_stream_printf(stream, ".u");
195 if (instr->opc == OPC_LDC)
196 mesa_log_stream_printf(stream, ".offset%d", instr->cat6.d);
197 if (instr->opc == OPC_LDC_K)
198 mesa_log_stream_printf(stream, ".%d", instr->cat6.iim_val);
199 if (instr->flags & IR3_INSTR_B) {
200 mesa_log_stream_printf(
201 stream, ".base%d",
202 is_tex(instr) ? instr->cat5.tex_base : instr->cat6.base);
203 }
204 if (instr->flags & IR3_INSTR_S2EN)
205 mesa_log_stream_printf(stream, ".s2en");
206
207 static const char *cond[0x7] = {
208 "lt", "le", "gt", "ge", "eq", "ne",
209 };
210
211 switch (instr->opc) {
212 case OPC_CMPS_F:
213 case OPC_CMPS_U:
214 case OPC_CMPS_S:
215 case OPC_CMPV_F:
216 case OPC_CMPV_U:
217 case OPC_CMPV_S:
218 mesa_log_stream_printf(stream, ".%s",
219 cond[instr->cat2.condition & 0x7]);
220 break;
221 case OPC_BRAC:
222 mesa_log_stream_printf(stream, ".%u", instr->cat0.idx);
223 break;
224 case OPC_SHFL:
225 switch (instr->cat6.shfl_mode) {
226 case SHFL_XOR:
227 mesa_log_stream_printf(stream, ".xor");
228 break;
229 case SHFL_UP:
230 mesa_log_stream_printf(stream, ".up");
231 break;
232 case SHFL_DOWN:
233 mesa_log_stream_printf(stream, ".down");
234 break;
235 case SHFL_RUP:
236 mesa_log_stream_printf(stream, ".rup");
237 break;
238 case SHFL_RDOWN:
239 mesa_log_stream_printf(stream, ".rdown");
240 break;
241 default:
242 mesa_log_stream_printf(stream, ".%u", instr->cat6.shfl_mode);
243 break;
244 }
245
246 mesa_log_stream_printf(stream, ".%s", type_name(instr->cat6.type));
247 break;
248 case OPC_ALIAS:
249 switch (instr->cat7.alias_scope) {
250 case ALIAS_TEX:
251 mesa_log_stream_printf(stream, ".tex");
252 break;
253 case ALIAS_RT:
254 mesa_log_stream_printf(stream, ".rt");
255 break;
256 case ALIAS_MEM:
257 mesa_log_stream_printf(stream, ".mem");
258 break;
259 }
260
261 if (instr->cat7.alias_type_float) {
262 mesa_log_stream_printf(stream, ".f");
263 } else {
264 mesa_log_stream_printf(stream, ".b");
265 }
266
267 if (instr->srcs[0]->flags & IR3_REG_HALF) {
268 mesa_log_stream_printf(stream, "16");
269 } else {
270 mesa_log_stream_printf(stream, "32");
271 }
272
273 mesa_log_stream_printf(stream, ".%u",
274 instr->cat7.alias_table_size_minus_one);
275 break;
276 default:
277 break;
278 }
279 }
280 }
281
282 static void
print_ssa_def_name(struct log_stream * stream,struct ir3_register * reg)283 print_ssa_def_name(struct log_stream *stream, struct ir3_register *reg)
284 {
285 mesa_log_stream_printf(stream, SYN_SSA("ssa_%u"), reg->instr->serialno);
286 if (reg->name != 0)
287 mesa_log_stream_printf(stream, ":%u", reg->name);
288 }
289
290 static void
print_ssa_name(struct log_stream * stream,struct ir3_register * reg,bool dst)291 print_ssa_name(struct log_stream *stream, struct ir3_register *reg, bool dst)
292 {
293 if (!dst) {
294 if (!reg->def)
295 mesa_log_stream_printf(stream, SYN_SSA("undef"));
296 else
297 print_ssa_def_name(stream, reg->def);
298 } else {
299 print_ssa_def_name(stream, reg);
300 }
301
302 if (reg->num != INVALID_REG && !(reg->flags & IR3_REG_ARRAY)) {
303 const char *prefix = "r";
304 unsigned num = reg_num(reg);
305
306 if (reg->flags & IR3_REG_PREDICATE) {
307 prefix = "p";
308 num = 0;
309 }
310
311 mesa_log_stream_printf(stream, "(" SYN_REG("%s%u.%c") ")", prefix, num,
312 "xyzw"[reg_comp(reg)]);
313 }
314 }
315
316 static void
print_reg_name(struct log_stream * stream,struct ir3_instruction * instr,struct ir3_register * reg,bool dest)317 print_reg_name(struct log_stream *stream, struct ir3_instruction *instr,
318 struct ir3_register *reg, bool dest)
319 {
320 if ((reg->flags & (IR3_REG_FABS | IR3_REG_SABS)) &&
321 (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT)))
322 mesa_log_stream_printf(stream, "(absneg)");
323 else if (reg->flags & (IR3_REG_FNEG | IR3_REG_SNEG | IR3_REG_BNOT))
324 mesa_log_stream_printf(stream, "(neg)");
325 else if (reg->flags & (IR3_REG_FABS | IR3_REG_SABS))
326 mesa_log_stream_printf(stream, "(abs)");
327
328 if (reg->flags & IR3_REG_FIRST_KILL)
329 mesa_log_stream_printf(stream, "(kill)");
330 if (reg->flags & IR3_REG_UNUSED)
331 mesa_log_stream_printf(stream, "(unused)");
332
333 if (reg->flags & IR3_REG_R)
334 mesa_log_stream_printf(stream, "(r)");
335
336 if (reg->flags & IR3_REG_EARLY_CLOBBER)
337 mesa_log_stream_printf(stream, "(early_clobber)");
338
339 /* Right now all instructions that use tied registers only have one
340 * destination register, so we can just print (tied) as if it's a flag,
341 * although it's more convenient for RA if it's a pointer.
342 */
343 if (reg->tied)
344 mesa_log_stream_printf(stream, "(tied)");
345
346 if (instr->opc == OPC_BR || instr->opc == OPC_BRAA ||
347 instr->opc == OPC_BRAO) {
348 bool inv = reg == instr->srcs[0] ? instr->cat0.inv1 : instr->cat0.inv2;
349 if (inv)
350 mesa_log_stream_printf(stream, "!");
351 }
352
353 if (reg->flags & IR3_REG_SHARED)
354 mesa_log_stream_printf(stream, "s");
355 if (reg->flags & IR3_REG_HALF)
356 mesa_log_stream_printf(stream, "h");
357 if (reg->flags & IR3_REG_PREDICATE)
358 mesa_log_stream_printf(stream, "p");
359
360 if (reg->flags & IR3_REG_IMMED) {
361 mesa_log_stream_printf(stream, SYN_IMMED("imm[%f,%d,0x%x]"), reg->fim_val,
362 reg->iim_val, reg->iim_val);
363 } else if (reg->flags & IR3_REG_ARRAY) {
364 if (reg->flags & IR3_REG_SSA) {
365 print_ssa_name(stream, reg, dest);
366 mesa_log_stream_printf(stream, ":");
367 }
368 mesa_log_stream_printf(stream,
369 SYN_ARRAY("arr[id=%u, offset=%d, size=%u]"),
370 reg->array.id, reg->array.offset, reg->size);
371 if (reg->array.base != INVALID_REG)
372 mesa_log_stream_printf(stream, "(" SYN_REG("r%u.%c") ")",
373 reg->array.base >> 2,
374 "xyzw"[reg->array.base & 0x3]);
375 } else if (reg->flags & IR3_REG_SSA) {
376 print_ssa_name(stream, reg, dest);
377 } else if (reg->flags & IR3_REG_RELATIV) {
378 if (reg->flags & IR3_REG_CONST)
379 mesa_log_stream_printf(stream, SYN_CONST("c<a0.x + %d>"),
380 reg->array.offset);
381 else
382 mesa_log_stream_printf(stream, SYN_REG("r<a0.x + %d>") " (%u)",
383 reg->array.offset, reg->size);
384 } else {
385 if (reg->flags & IR3_REG_CONST)
386 mesa_log_stream_printf(stream, SYN_CONST("c%u.%c"), reg_num(reg),
387 "xyzw"[reg_comp(reg)]);
388 else if (reg->flags & IR3_REG_PREDICATE)
389 mesa_log_stream_printf(stream, SYN_REG("p0.%c"),
390 "xyzw"[reg_comp(reg)]);
391 else if (reg->flags & IR3_REG_RT)
392 mesa_log_stream_printf(stream, SYN_RT("rt%u.%c"), reg_num(reg),
393 "xyzw"[reg_comp(reg)]);
394 else
395 mesa_log_stream_printf(stream, SYN_REG("r%u.%c"), reg_num(reg),
396 "xyzw"[reg_comp(reg)]);
397 }
398
399 if (reg->wrmask != 0x1)
400 mesa_log_stream_printf(stream, " (wrmask=0x%x)", reg->wrmask);
401 }
402
403 static void
tab(struct log_stream * stream,int lvl)404 tab(struct log_stream *stream, int lvl)
405 {
406 for (int i = 0; i < lvl; i++)
407 mesa_log_stream_printf(stream, "\t");
408 }
409
410 static void
print_instr(struct log_stream * stream,struct ir3_instruction * instr,int lvl)411 print_instr(struct log_stream *stream, struct ir3_instruction *instr, int lvl)
412 {
413 tab(stream, lvl);
414
415 print_instr_name(stream, instr, true);
416
417 if (is_tex(instr)) {
418 if (instr->opc == OPC_BRCST_ACTIVE)
419 mesa_log_stream_printf(stream, ".w%d", instr->cat5.cluster_size);
420 mesa_log_stream_printf(stream, " (%s)(", type_name(instr->cat5.type));
421 for (unsigned i = 0; i < 4; i++)
422 if (instr->dsts[0]->wrmask & (1 << i))
423 mesa_log_stream_printf(stream, "%c", "xyzw"[i]);
424 mesa_log_stream_printf(stream, ")");
425 } else if ((instr->srcs_count > 0 || instr->dsts_count > 0)) {
426 /* NOTE the b(ranch) instruction has a suffix, which is
427 * handled below
428 */
429 mesa_log_stream_printf(stream, " ");
430 }
431
432 if (opc_cat(instr->opc) == 1) {
433 switch (instr->cat1.round) {
434 case ROUND_ZERO:
435 break;
436 case ROUND_EVEN:
437 mesa_log_stream_printf(stream, "(even)");
438 break;
439 case ROUND_POS_INF:
440 mesa_log_stream_printf(stream, "(pos_infinity)");
441 break;
442 case ROUND_NEG_INF:
443 mesa_log_stream_printf(stream, "(neg_infinity)");
444 break;
445 }
446 }
447
448 bool first = true;
449 foreach_dst (reg, instr) {
450 if (reg->wrmask == 0)
451 continue;
452 if (!first)
453 mesa_log_stream_printf(stream, ", ");
454 if (reg->flags & IR3_REG_ALIAS)
455 mesa_log_stream_printf(stream, "@");
456 print_reg_name(stream, instr, reg, true);
457 first = false;
458 }
459 foreach_src_n (reg, n, instr) {
460 if (!first)
461 mesa_log_stream_printf(stream, ", ");
462 if (reg->flags & IR3_REG_FIRST_ALIAS)
463 mesa_log_stream_printf(stream, "@{");
464 print_reg_name(stream, instr, reg, false);
465 if ((reg->flags & IR3_REG_ALIAS) &&
466 (n == instr->srcs_count - 1 ||
467 ir3_src_is_first_in_group(instr->srcs[n + 1]))) {
468 mesa_log_stream_printf(stream, "}");
469 }
470 if (instr->opc == OPC_END || instr->opc == OPC_CHMASK)
471 mesa_log_stream_printf(stream, " (%u)", instr->end.outidxs[n]);
472 first = false;
473 }
474
475 if (is_tex(instr) && !(instr->flags & IR3_INSTR_S2EN) &&
476 !is_tex_shuffle(instr)) {
477 if (!!(instr->flags & IR3_INSTR_B) && !!(instr->flags & IR3_INSTR_A1EN)) {
478 mesa_log_stream_printf(stream, ", s#%d", instr->cat5.samp);
479 } else {
480 mesa_log_stream_printf(stream, ", s#%d, t#%d", instr->cat5.samp,
481 instr->cat5.tex);
482 }
483 }
484
485 if (instr->opc == OPC_META_SPLIT) {
486 mesa_log_stream_printf(stream, ", off=%d", instr->split.off);
487 } else if (instr->opc == OPC_META_TEX_PREFETCH) {
488 mesa_log_stream_printf(stream, ", tex=%d, samp=%d, input_offset=%d",
489 instr->prefetch.tex, instr->prefetch.samp,
490 instr->prefetch.input_offset);
491 } else if (instr->opc == OPC_PUSH_CONSTS_LOAD_MACRO) {
492 mesa_log_stream_printf(
493 stream, " dst_offset=%d, src_offset = %d, src_size = %d",
494 instr->push_consts.dst_base, instr->push_consts.src_base,
495 instr->push_consts.src_size);
496 } else if (instr->opc == OPC_SPILL_MACRO) {
497 mesa_log_stream_printf(stream, " dst_offset=%d", instr->cat6.dst_offset);
498 }
499
500 if (is_flow(instr) && instr->cat0.target) {
501 mesa_log_stream_printf(stream, " target=block%u",
502 block_id(instr->cat0.target));
503 }
504
505 if (instr->deps_count) {
506 mesa_log_stream_printf(stream, ", false-deps:");
507 unsigned n = 0;
508 for (unsigned i = 0; i < instr->deps_count; i++) {
509 if (!instr->deps[i])
510 continue;
511 if (n++ > 0)
512 mesa_log_stream_printf(stream, ", ");
513 mesa_log_stream_printf(stream, SYN_SSA("ssa_%u"),
514 instr->deps[i]->serialno);
515 }
516 }
517
518 if (ir3_instr_is_rpt(instr)) {
519 mesa_log_stream_printf(stream, ", rpt: ");
520
521 if (ir3_instr_is_first_rpt(instr)) {
522 mesa_log_stream_printf(stream, "first");
523 } else {
524 mesa_log_stream_printf(stream, "%u",
525 ir3_instr_prev_rpt(instr)->serialno);
526 }
527 }
528
529 mesa_log_stream_printf(stream, "\n");
530 }
531
532 void
ir3_print_instr_stream(struct log_stream * stream,struct ir3_instruction * instr)533 ir3_print_instr_stream(struct log_stream *stream, struct ir3_instruction *instr)
534 {
535 print_instr(stream, instr, 0);
536 }
537
538 void
ir3_print_instr(struct ir3_instruction * instr)539 ir3_print_instr(struct ir3_instruction *instr)
540 {
541 struct log_stream *stream = mesa_log_streami();
542 print_instr(stream, instr, 0);
543 mesa_log_stream_destroy(stream);
544 }
545
546 static void
print_block(struct ir3_block * block,int lvl)547 print_block(struct ir3_block *block, int lvl)
548 {
549 struct log_stream *stream = mesa_log_streami();
550
551 tab(stream, lvl);
552 mesa_log_stream_printf(stream, "%sblock%u {\n",
553 block->reconvergence_point ? "(jp)" : "",
554 block_id(block));
555
556 if (block->predecessors_count > 0) {
557 tab(stream, lvl + 1);
558 mesa_log_stream_printf(stream, "pred: ");
559 for (unsigned i = 0; i < block->predecessors_count; i++) {
560 struct ir3_block *pred = block->predecessors[i];
561 if (i != 0)
562 mesa_log_stream_printf(stream, ", ");
563 mesa_log_stream_printf(stream, "block%u", block_id(pred));
564 }
565 mesa_log_stream_printf(stream, "\n");
566 }
567
568 if (block->physical_predecessors_count > 0) {
569 tab(stream, lvl + 1);
570 mesa_log_stream_printf(stream, "physical pred: ");
571 for (unsigned i = 0; i < block->physical_predecessors_count; i++) {
572 struct ir3_block *pred = block->physical_predecessors[i];
573 if (i != 0)
574 mesa_log_stream_printf(stream, ", ");
575 mesa_log_stream_printf(stream, "block%u", block_id(pred));
576 }
577 mesa_log_stream_printf(stream, "\n");
578 }
579
580 foreach_instr (instr, &block->instr_list) {
581 print_instr(stream, instr, lvl + 1);
582 }
583
584 tab(stream, lvl + 1);
585 mesa_log_stream_printf(stream, "/* keeps:\n");
586 for (unsigned i = 0; i < block->keeps_count; i++) {
587 print_instr(stream, block->keeps[i], lvl + 2);
588 }
589 tab(stream, lvl + 1);
590 mesa_log_stream_printf(stream, " */\n");
591
592 if (block->successors[0]) {
593 tab(stream, lvl + 1);
594 mesa_log_stream_printf(stream, "/* succs: block%u",
595 block_id(block->successors[0]));
596 if (block->successors[1]) {
597 mesa_log_stream_printf(stream, ", block%u",
598 block_id(block->successors[1]));
599
600 mesa_log_stream_printf(stream, " (%s)",
601 block->divergent_condition ? "div" : "con");
602 }
603 mesa_log_stream_printf(stream, " */\n");
604 }
605 if (block->physical_successors_count > 0) {
606 tab(stream, lvl + 1);
607 mesa_log_stream_printf(stream, "/* physical succs: ");
608 for (unsigned i = 0; i < block->physical_successors_count; i++) {
609 mesa_log_stream_printf(stream, "block%u",
610 block_id(block->physical_successors[i]));
611 if (i < block->physical_successors_count - 1)
612 mesa_log_stream_printf(stream, ", ");
613 }
614 mesa_log_stream_printf(stream, " */\n");
615 }
616 tab(stream, lvl);
617 mesa_log_stream_printf(stream, "}\n");
618 }
619
620 void
ir3_print(struct ir3 * ir)621 ir3_print(struct ir3 *ir)
622 {
623 foreach_block (block, &ir->block_list)
624 print_block(block, 0);
625 }
626