2 #include "aco_builder.h"
5 #include "ac_shader_util.h"
9 static const char *reduce_ops
[] = {
60 static void print_reg_class(const RegClass rc
, FILE *output
)
63 case RegClass::s1
: fprintf(output
, " s1: "); return;
64 case RegClass::s2
: fprintf(output
, " s2: "); return;
65 case RegClass::s3
: fprintf(output
, " s3: "); return;
66 case RegClass::s4
: fprintf(output
, " s4: "); return;
67 case RegClass::s6
: fprintf(output
, " s6: "); return;
68 case RegClass::s8
: fprintf(output
, " s8: "); return;
69 case RegClass::s16
: fprintf(output
, "s16: "); return;
70 case RegClass::v1
: fprintf(output
, " v1: "); return;
71 case RegClass::v2
: fprintf(output
, " v2: "); return;
72 case RegClass::v3
: fprintf(output
, " v3: "); return;
73 case RegClass::v4
: fprintf(output
, " v4: "); return;
74 case RegClass::v5
: fprintf(output
, " v5: "); return;
75 case RegClass::v6
: fprintf(output
, " v6: "); return;
76 case RegClass::v7
: fprintf(output
, " v7: "); return;
77 case RegClass::v8
: fprintf(output
, " v8: "); return;
78 case RegClass::v1b
: fprintf(output
, " v1b: "); return;
79 case RegClass::v2b
: fprintf(output
, " v2b: "); return;
80 case RegClass::v3b
: fprintf(output
, " v3b: "); return;
81 case RegClass::v4b
: fprintf(output
, " v4b: "); return;
82 case RegClass::v6b
: fprintf(output
, " v6b: "); return;
83 case RegClass::v8b
: fprintf(output
, " v8b: "); return;
84 case RegClass::v1_linear
: fprintf(output
, " v1: "); return;
85 case RegClass::v2_linear
: fprintf(output
, " v2: "); return;
89 void print_physReg(PhysReg reg
, unsigned bytes
, FILE *output
)
92 fprintf(output
, ":m0");
93 } else if (reg
== 106) {
94 fprintf(output
, ":vcc");
95 } else if (reg
== 253) {
96 fprintf(output
, ":scc");
97 } else if (reg
== 126) {
98 fprintf(output
, ":exec");
100 bool is_vgpr
= reg
/ 256;
101 unsigned r
= reg
% 256;
102 unsigned size
= DIV_ROUND_UP(bytes
, 4);
103 fprintf(output
, ":%c[%d", is_vgpr
? 'v' : 's', r
);
105 fprintf(output
, "-%d]", r
+ size
-1);
107 fprintf(output
, "]");
108 if (reg
.byte() || bytes
% 4)
109 fprintf(output
, "[%d:%d]", reg
.byte()*8, (reg
.byte()+bytes
) * 8);
113 static void print_constant(uint8_t reg
, FILE *output
)
115 if (reg
>= 128 && reg
<= 192) {
116 fprintf(output
, "%d", reg
- 128);
118 } else if (reg
>= 192 && reg
<= 208) {
119 fprintf(output
, "%d", 192 - reg
);
125 fprintf(output
, "0.5");
128 fprintf(output
, "-0.5");
131 fprintf(output
, "1.0");
134 fprintf(output
, "-1.0");
137 fprintf(output
, "2.0");
140 fprintf(output
, "-2.0");
143 fprintf(output
, "4.0");
146 fprintf(output
, "-4.0");
149 fprintf(output
, "1/(2*PI)");
154 static void print_operand(const Operand
*operand
, FILE *output
)
156 if (operand
->isLiteral() || (operand
->isConstant() && operand
->bytes() == 1)) {
157 if (operand
->bytes() == 1)
158 fprintf(output
, "0x%.2x", operand
->constantValue());
159 else if (operand
->bytes() == 2)
160 fprintf(output
, "0x%.4x", operand
->constantValue());
162 fprintf(output
, "0x%x", operand
->constantValue());
163 } else if (operand
->isConstant()) {
164 print_constant(operand
->physReg().reg(), output
);
165 } else if (operand
->isUndefined()) {
166 print_reg_class(operand
->regClass(), output
);
167 fprintf(output
, "undef");
169 if (operand
->isLateKill())
170 fprintf(output
, "(latekill)");
172 fprintf(output
, "%%%d", operand
->tempId());
174 if (operand
->isFixed())
175 print_physReg(operand
->physReg(), operand
->bytes(), output
);
179 static void print_definition(const Definition
*definition
, FILE *output
)
181 print_reg_class(definition
->regClass(), output
);
182 if (definition
->isPrecise())
183 fprintf(output
, "(precise)");
184 if (definition
->isNUW())
185 fprintf(output
, "(nuw)");
186 fprintf(output
, "%%%d", definition
->tempId());
188 if (definition
->isFixed())
189 print_physReg(definition
->physReg(), definition
->bytes(), output
);
192 static void print_storage(storage_class storage
, FILE *output
)
194 fprintf(output
, " storage:");
196 if (storage
& storage_buffer
)
197 printed
+= fprintf(output
, "%sbuffer", printed
? "," : "");
198 if (storage
& storage_atomic_counter
)
199 printed
+= fprintf(output
, "%satomic_counter", printed
? "," : "");
200 if (storage
& storage_image
)
201 printed
+= fprintf(output
, "%simage", printed
? "," : "");
202 if (storage
& storage_shared
)
203 printed
+= fprintf(output
, "%sshared", printed
? "," : "");
204 if (storage
& storage_vmem_output
)
205 printed
+= fprintf(output
, "%svmem_output", printed
? "," : "");
206 if (storage
& storage_scratch
)
207 printed
+= fprintf(output
, "%sscratch", printed
? "," : "");
208 if (storage
& storage_vgpr_spill
)
209 printed
+= fprintf(output
, "%svgpr_spill", printed
? "," : "");
212 static void print_semantics(memory_semantics sem
, FILE *output
)
214 fprintf(output
, " semantics:");
216 if (sem
& semantic_acquire
)
217 printed
+= fprintf(output
, "%sacquire", printed
? "," : "");
218 if (sem
& semantic_release
)
219 printed
+= fprintf(output
, "%srelease", printed
? "," : "");
220 if (sem
& semantic_volatile
)
221 printed
+= fprintf(output
, "%svolatile", printed
? "," : "");
222 if (sem
& semantic_private
)
223 printed
+= fprintf(output
, "%sprivate", printed
? "," : "");
224 if (sem
& semantic_can_reorder
)
225 printed
+= fprintf(output
, "%sreorder", printed
? "," : "");
226 if (sem
& semantic_atomic
)
227 printed
+= fprintf(output
, "%satomic", printed
? "," : "");
228 if (sem
& semantic_rmw
)
229 printed
+= fprintf(output
, "%srmw", printed
? "," : "");
232 static void print_scope(sync_scope scope
, FILE *output
, const char *prefix
="scope")
234 fprintf(output
, " %s:", prefix
);
236 case scope_invocation
:
237 fprintf(output
, "invocation");
240 fprintf(output
, "subgroup");
242 case scope_workgroup
:
243 fprintf(output
, "workgroup");
245 case scope_queuefamily
:
246 fprintf(output
, "queuefamily");
249 fprintf(output
, "device");
254 static void print_sync(memory_sync_info sync
, FILE *output
)
256 print_storage(sync
.storage
, output
);
257 print_semantics(sync
.semantics
, output
);
258 print_scope(sync
.scope
, output
);
261 static void print_instr_format_specific(const Instruction
*instr
, FILE *output
)
263 switch (instr
->format
) {
265 const SOPK_instruction
* sopk
= static_cast<const SOPK_instruction
*>(instr
);
266 fprintf(output
, " imm:%d", sopk
->imm
& 0x8000 ? (sopk
->imm
- 65536) : sopk
->imm
);
270 const SOPP_instruction
* sopp
= static_cast<const SOPP_instruction
*>(instr
);
271 uint16_t imm
= sopp
->imm
;
272 switch (instr
->opcode
) {
273 case aco_opcode::s_waitcnt
: {
274 /* we usually should check the chip class for vmcnt/lgkm, but
275 * insert_waitcnt() should fill it in regardless. */
276 unsigned vmcnt
= (imm
& 0xF) | ((imm
& (0x3 << 14)) >> 10);
277 if (vmcnt
!= 63) fprintf(output
, " vmcnt(%d)", vmcnt
);
278 if (((imm
>> 4) & 0x7) < 0x7) fprintf(output
, " expcnt(%d)", (imm
>> 4) & 0x7);
279 if (((imm
>> 8) & 0x3F) < 0x3F) fprintf(output
, " lgkmcnt(%d)", (imm
>> 8) & 0x3F);
282 case aco_opcode::s_endpgm
:
283 case aco_opcode::s_endpgm_saved
:
284 case aco_opcode::s_endpgm_ordered_ps_done
:
285 case aco_opcode::s_wakeup
:
286 case aco_opcode::s_barrier
:
287 case aco_opcode::s_icache_inv
:
288 case aco_opcode::s_ttracedata
:
289 case aco_opcode::s_set_gpr_idx_off
: {
292 case aco_opcode::s_sendmsg
: {
293 unsigned id
= imm
& sendmsg_id_mask
;
296 fprintf(output
, " sendmsg(MSG_NONE)");
299 fprintf(output
, " sendmsg(gs%s%s, %u)",
300 imm
& 0x10 ? ", cut" : "", imm
& 0x20 ? ", emit" : "", imm
>> 8);
302 case _sendmsg_gs_done
:
303 fprintf(output
, " sendmsg(gs_done%s%s, %u)",
304 imm
& 0x10 ? ", cut" : "", imm
& 0x20 ? ", emit" : "", imm
>> 8);
306 case sendmsg_save_wave
:
307 fprintf(output
, " sendmsg(save_wave)");
309 case sendmsg_stall_wave_gen
:
310 fprintf(output
, " sendmsg(stall_wave_gen)");
312 case sendmsg_halt_waves
:
313 fprintf(output
, " sendmsg(halt_waves)");
315 case sendmsg_ordered_ps_done
:
316 fprintf(output
, " sendmsg(ordered_ps_done)");
318 case sendmsg_early_prim_dealloc
:
319 fprintf(output
, " sendmsg(early_prim_dealloc)");
321 case sendmsg_gs_alloc_req
:
322 fprintf(output
, " sendmsg(gs_alloc_req)");
329 fprintf(output
, " imm:%u", imm
);
333 if (sopp
->block
!= -1)
334 fprintf(output
, " block:BB%d", sopp
->block
);
338 const SMEM_instruction
* smem
= static_cast<const SMEM_instruction
*>(instr
);
340 fprintf(output
, " glc");
342 fprintf(output
, " dlc");
344 fprintf(output
, " nv");
345 print_sync(smem
->sync
, output
);
348 case Format::VINTRP
: {
349 const Interp_instruction
* vintrp
= static_cast<const Interp_instruction
*>(instr
);
350 fprintf(output
, " attr%d.%c", vintrp
->attribute
, "xyzw"[vintrp
->component
]);
354 const DS_instruction
* ds
= static_cast<const DS_instruction
*>(instr
);
356 fprintf(output
, " offset0:%u", ds
->offset0
);
358 fprintf(output
, " offset1:%u", ds
->offset1
);
360 fprintf(output
, " gds");
361 print_sync(ds
->sync
, output
);
364 case Format::MUBUF
: {
365 const MUBUF_instruction
* mubuf
= static_cast<const MUBUF_instruction
*>(instr
);
367 fprintf(output
, " offset:%u", mubuf
->offset
);
369 fprintf(output
, " offen");
371 fprintf(output
, " idxen");
373 fprintf(output
, " addr64");
375 fprintf(output
, " glc");
377 fprintf(output
, " dlc");
379 fprintf(output
, " slc");
381 fprintf(output
, " tfe");
383 fprintf(output
, " lds");
384 if (mubuf
->disable_wqm
)
385 fprintf(output
, " disable_wqm");
386 print_sync(mubuf
->sync
, output
);
390 const MIMG_instruction
* mimg
= static_cast<const MIMG_instruction
*>(instr
);
391 unsigned identity_dmask
= !instr
->definitions
.empty() ?
392 (1 << instr
->definitions
[0].size()) - 1 :
394 if ((mimg
->dmask
& identity_dmask
) != identity_dmask
)
395 fprintf(output
, " dmask:%s%s%s%s",
396 mimg
->dmask
& 0x1 ? "x" : "",
397 mimg
->dmask
& 0x2 ? "y" : "",
398 mimg
->dmask
& 0x4 ? "z" : "",
399 mimg
->dmask
& 0x8 ? "w" : "");
402 fprintf(output
, " 1d");
405 fprintf(output
, " 2d");
408 fprintf(output
, " 3d");
411 fprintf(output
, " cube");
413 case ac_image_1darray
:
414 fprintf(output
, " 1darray");
416 case ac_image_2darray
:
417 fprintf(output
, " 2darray");
419 case ac_image_2dmsaa
:
420 fprintf(output
, " 2dmsaa");
422 case ac_image_2darraymsaa
:
423 fprintf(output
, " 2darraymsaa");
427 fprintf(output
, " unrm");
429 fprintf(output
, " glc");
431 fprintf(output
, " dlc");
433 fprintf(output
, " slc");
435 fprintf(output
, " tfe");
437 fprintf(output
, " da");
439 fprintf(output
, " lwe");
440 if (mimg
->r128
|| mimg
->a16
)
441 fprintf(output
, " r128/a16");
443 fprintf(output
, " d16");
444 if (mimg
->disable_wqm
)
445 fprintf(output
, " disable_wqm");
446 print_sync(mimg
->sync
, output
);
450 const Export_instruction
* exp
= static_cast<const Export_instruction
*>(instr
);
451 unsigned identity_mask
= exp
->compressed
? 0x5 : 0xf;
452 if ((exp
->enabled_mask
& identity_mask
) != identity_mask
)
453 fprintf(output
, " en:%c%c%c%c",
454 exp
->enabled_mask
& 0x1 ? 'r' : '*',
455 exp
->enabled_mask
& 0x2 ? 'g' : '*',
456 exp
->enabled_mask
& 0x4 ? 'b' : '*',
457 exp
->enabled_mask
& 0x8 ? 'a' : '*');
459 fprintf(output
, " compr");
461 fprintf(output
, " done");
463 fprintf(output
, " vm");
465 if (exp
->dest
<= V_008DFC_SQ_EXP_MRT
+ 7)
466 fprintf(output
, " mrt%d", exp
->dest
- V_008DFC_SQ_EXP_MRT
);
467 else if (exp
->dest
== V_008DFC_SQ_EXP_MRTZ
)
468 fprintf(output
, " mrtz");
469 else if (exp
->dest
== V_008DFC_SQ_EXP_NULL
)
470 fprintf(output
, " null");
471 else if (exp
->dest
>= V_008DFC_SQ_EXP_POS
&& exp
->dest
<= V_008DFC_SQ_EXP_POS
+ 3)
472 fprintf(output
, " pos%d", exp
->dest
- V_008DFC_SQ_EXP_POS
);
473 else if (exp
->dest
>= V_008DFC_SQ_EXP_PARAM
&& exp
->dest
<= V_008DFC_SQ_EXP_PARAM
+ 31)
474 fprintf(output
, " param%d", exp
->dest
- V_008DFC_SQ_EXP_PARAM
);
477 case Format::PSEUDO_BRANCH
: {
478 const Pseudo_branch_instruction
* branch
= static_cast<const Pseudo_branch_instruction
*>(instr
);
479 /* Note: BB0 cannot be a branch target */
480 if (branch
->target
[0] != 0)
481 fprintf(output
, " BB%d", branch
->target
[0]);
482 if (branch
->target
[1] != 0)
483 fprintf(output
, ", BB%d", branch
->target
[1]);
486 case Format::PSEUDO_REDUCTION
: {
487 const Pseudo_reduction_instruction
* reduce
= static_cast<const Pseudo_reduction_instruction
*>(instr
);
488 fprintf(output
, " op:%s", reduce_ops
[reduce
->reduce_op
]);
489 if (reduce
->cluster_size
)
490 fprintf(output
, " cluster_size:%u", reduce
->cluster_size
);
493 case Format::PSEUDO_BARRIER
: {
494 const Pseudo_barrier_instruction
* barrier
= static_cast<const Pseudo_barrier_instruction
*>(instr
);
495 print_sync(barrier
->sync
, output
);
496 print_scope(barrier
->exec_scope
, output
, "exec_scope");
501 case Format::SCRATCH
: {
502 const FLAT_instruction
* flat
= static_cast<const FLAT_instruction
*>(instr
);
504 fprintf(output
, " offset:%u", flat
->offset
);
506 fprintf(output
, " glc");
508 fprintf(output
, " dlc");
510 fprintf(output
, " slc");
512 fprintf(output
, " lds");
514 fprintf(output
, " nv");
515 if (flat
->disable_wqm
)
516 fprintf(output
, " disable_wqm");
517 print_sync(flat
->sync
, output
);
520 case Format::MTBUF
: {
521 const MTBUF_instruction
* mtbuf
= static_cast<const MTBUF_instruction
*>(instr
);
522 fprintf(output
, " dfmt:");
523 switch (mtbuf
->dfmt
) {
524 case V_008F0C_BUF_DATA_FORMAT_8
: fprintf(output
, "8"); break;
525 case V_008F0C_BUF_DATA_FORMAT_16
: fprintf(output
, "16"); break;
526 case V_008F0C_BUF_DATA_FORMAT_8_8
: fprintf(output
, "8_8"); break;
527 case V_008F0C_BUF_DATA_FORMAT_32
: fprintf(output
, "32"); break;
528 case V_008F0C_BUF_DATA_FORMAT_16_16
: fprintf(output
, "16_16"); break;
529 case V_008F0C_BUF_DATA_FORMAT_10_11_11
: fprintf(output
, "10_11_11"); break;
530 case V_008F0C_BUF_DATA_FORMAT_11_11_10
: fprintf(output
, "11_11_10"); break;
531 case V_008F0C_BUF_DATA_FORMAT_10_10_10_2
: fprintf(output
, "10_10_10_2"); break;
532 case V_008F0C_BUF_DATA_FORMAT_2_10_10_10
: fprintf(output
, "2_10_10_10"); break;
533 case V_008F0C_BUF_DATA_FORMAT_8_8_8_8
: fprintf(output
, "8_8_8_8"); break;
534 case V_008F0C_BUF_DATA_FORMAT_32_32
: fprintf(output
, "32_32"); break;
535 case V_008F0C_BUF_DATA_FORMAT_16_16_16_16
: fprintf(output
, "16_16_16_16"); break;
536 case V_008F0C_BUF_DATA_FORMAT_32_32_32
: fprintf(output
, "32_32_32"); break;
537 case V_008F0C_BUF_DATA_FORMAT_32_32_32_32
: fprintf(output
, "32_32_32_32"); break;
538 case V_008F0C_BUF_DATA_FORMAT_RESERVED_15
: fprintf(output
, "reserved15"); break;
540 fprintf(output
, " nfmt:");
541 switch (mtbuf
->nfmt
) {
542 case V_008F0C_BUF_NUM_FORMAT_UNORM
: fprintf(output
, "unorm"); break;
543 case V_008F0C_BUF_NUM_FORMAT_SNORM
: fprintf(output
, "snorm"); break;
544 case V_008F0C_BUF_NUM_FORMAT_USCALED
: fprintf(output
, "uscaled"); break;
545 case V_008F0C_BUF_NUM_FORMAT_SSCALED
: fprintf(output
, "sscaled"); break;
546 case V_008F0C_BUF_NUM_FORMAT_UINT
: fprintf(output
, "uint"); break;
547 case V_008F0C_BUF_NUM_FORMAT_SINT
: fprintf(output
, "sint"); break;
548 case V_008F0C_BUF_NUM_FORMAT_SNORM_OGL
: fprintf(output
, "snorm"); break;
549 case V_008F0C_BUF_NUM_FORMAT_FLOAT
: fprintf(output
, "float"); break;
552 fprintf(output
, " offset:%u", mtbuf
->offset
);
554 fprintf(output
, " offen");
556 fprintf(output
, " idxen");
558 fprintf(output
, " glc");
560 fprintf(output
, " dlc");
562 fprintf(output
, " slc");
564 fprintf(output
, " tfe");
565 if (mtbuf
->disable_wqm
)
566 fprintf(output
, " disable_wqm");
567 print_sync(mtbuf
->sync
, output
);
570 case Format::VOP3P
: {
571 if (static_cast<const VOP3P_instruction
*>(instr
)->clamp
)
572 fprintf(output
, " clamp");
579 if (instr
->isVOP3()) {
580 const VOP3A_instruction
* vop3
= static_cast<const VOP3A_instruction
*>(instr
);
581 switch (vop3
->omod
) {
583 fprintf(output
, " *2");
586 fprintf(output
, " *4");
589 fprintf(output
, " *0.5");
593 fprintf(output
, " clamp");
594 if (vop3
->opsel
& (1 << 3))
595 fprintf(output
, " opsel_hi");
596 } else if (instr
->isDPP()) {
597 const DPP_instruction
* dpp
= static_cast<const DPP_instruction
*>(instr
);
598 if (dpp
->dpp_ctrl
<= 0xff) {
599 fprintf(output
, " quad_perm:[%d,%d,%d,%d]",
600 dpp
->dpp_ctrl
& 0x3, (dpp
->dpp_ctrl
>> 2) & 0x3,
601 (dpp
->dpp_ctrl
>> 4) & 0x3, (dpp
->dpp_ctrl
>> 6) & 0x3);
602 } else if (dpp
->dpp_ctrl
>= 0x101 && dpp
->dpp_ctrl
<= 0x10f) {
603 fprintf(output
, " row_shl:%d", dpp
->dpp_ctrl
& 0xf);
604 } else if (dpp
->dpp_ctrl
>= 0x111 && dpp
->dpp_ctrl
<= 0x11f) {
605 fprintf(output
, " row_shr:%d", dpp
->dpp_ctrl
& 0xf);
606 } else if (dpp
->dpp_ctrl
>= 0x121 && dpp
->dpp_ctrl
<= 0x12f) {
607 fprintf(output
, " row_ror:%d", dpp
->dpp_ctrl
& 0xf);
608 } else if (dpp
->dpp_ctrl
== dpp_wf_sl1
) {
609 fprintf(output
, " wave_shl:1");
610 } else if (dpp
->dpp_ctrl
== dpp_wf_rl1
) {
611 fprintf(output
, " wave_rol:1");
612 } else if (dpp
->dpp_ctrl
== dpp_wf_sr1
) {
613 fprintf(output
, " wave_shr:1");
614 } else if (dpp
->dpp_ctrl
== dpp_wf_rr1
) {
615 fprintf(output
, " wave_ror:1");
616 } else if (dpp
->dpp_ctrl
== dpp_row_mirror
) {
617 fprintf(output
, " row_mirror");
618 } else if (dpp
->dpp_ctrl
== dpp_row_half_mirror
) {
619 fprintf(output
, " row_half_mirror");
620 } else if (dpp
->dpp_ctrl
== dpp_row_bcast15
) {
621 fprintf(output
, " row_bcast:15");
622 } else if (dpp
->dpp_ctrl
== dpp_row_bcast31
) {
623 fprintf(output
, " row_bcast:31");
625 fprintf(output
, " dpp_ctrl:0x%.3x", dpp
->dpp_ctrl
);
627 if (dpp
->row_mask
!= 0xf)
628 fprintf(output
, " row_mask:0x%.1x", dpp
->row_mask
);
629 if (dpp
->bank_mask
!= 0xf)
630 fprintf(output
, " bank_mask:0x%.1x", dpp
->bank_mask
);
632 fprintf(output
, " bound_ctrl:1");
633 } else if ((int)instr
->format
& (int)Format::SDWA
) {
634 const SDWA_instruction
* sdwa
= static_cast<const SDWA_instruction
*>(instr
);
635 switch (sdwa
->omod
) {
637 fprintf(output
, " *2");
640 fprintf(output
, " *4");
643 fprintf(output
, " *0.5");
647 fprintf(output
, " clamp");
648 switch (sdwa
->dst_sel
& sdwa_asuint
) {
655 fprintf(output
, " dst_sel:%sbyte%u", sdwa
->dst_sel
& sdwa_sext
? "s" : "u",
656 sdwa
->dst_sel
& sdwa_bytenum
);
660 fprintf(output
, " dst_sel:%sword%u", sdwa
->dst_sel
& sdwa_sext
? "s" : "u",
661 sdwa
->dst_sel
& sdwa_wordnum
);
664 if (sdwa
->dst_preserve
)
665 fprintf(output
, " dst_preserve");
669 void aco_print_instr(const Instruction
*instr
, FILE *output
)
671 if (!instr
->definitions
.empty()) {
672 for (unsigned i
= 0; i
< instr
->definitions
.size(); ++i
) {
673 print_definition(&instr
->definitions
[i
], output
);
674 if (i
+ 1 != instr
->definitions
.size())
675 fprintf(output
, ", ");
677 fprintf(output
, " = ");
679 fprintf(output
, "%s", instr_info
.name
[(int)instr
->opcode
]);
680 if (instr
->operands
.size()) {
681 bool abs
[instr
->operands
.size()];
682 bool neg
[instr
->operands
.size()];
683 bool opsel
[instr
->operands
.size()];
684 uint8_t sel
[instr
->operands
.size()];
685 if ((int)instr
->format
& (int)Format::VOP3A
) {
686 const VOP3A_instruction
* vop3
= static_cast<const VOP3A_instruction
*>(instr
);
687 for (unsigned i
= 0; i
< instr
->operands
.size(); ++i
) {
688 abs
[i
] = vop3
->abs
[i
];
689 neg
[i
] = vop3
->neg
[i
];
690 opsel
[i
] = vop3
->opsel
& (1 << i
);
691 sel
[i
] = sdwa_udword
;
693 } else if (instr
->isDPP()) {
694 const DPP_instruction
* dpp
= static_cast<const DPP_instruction
*>(instr
);
695 for (unsigned i
= 0; i
< instr
->operands
.size(); ++i
) {
696 abs
[i
] = i
< 2 ? dpp
->abs
[i
] : false;
697 neg
[i
] = i
< 2 ? dpp
->neg
[i
] : false;
699 sel
[i
] = sdwa_udword
;
701 } else if (instr
->isSDWA()) {
702 const SDWA_instruction
* sdwa
= static_cast<const SDWA_instruction
*>(instr
);
703 for (unsigned i
= 0; i
< instr
->operands
.size(); ++i
) {
704 abs
[i
] = i
< 2 ? sdwa
->abs
[i
] : false;
705 neg
[i
] = i
< 2 ? sdwa
->neg
[i
] : false;
707 sel
[i
] = i
< 2 ? sdwa
->sel
[i
] : sdwa_udword
;
710 for (unsigned i
= 0; i
< instr
->operands
.size(); ++i
) {
714 sel
[i
] = sdwa_udword
;
717 for (unsigned i
= 0; i
< instr
->operands
.size(); ++i
) {
719 fprintf(output
, ", ");
721 fprintf(output
, " ");
724 fprintf(output
, "-");
726 fprintf(output
, "|");
728 fprintf(output
, "hi(");
729 else if (sel
[i
] & sdwa_sext
)
730 fprintf(output
, "sext(");
731 print_operand(&instr
->operands
[i
], output
);
732 if (opsel
[i
] || (sel
[i
] & sdwa_sext
))
733 fprintf(output
, ")");
734 if (!(sel
[i
] & sdwa_isra
)) {
735 if (sel
[i
] & sdwa_udword
) {
737 } else if (sel
[i
] & sdwa_isword
) {
738 unsigned index
= sel
[i
] & sdwa_wordnum
;
739 fprintf(output
, "[%u:%u]", index
* 16, index
* 16 + 15);
741 unsigned index
= sel
[i
] & sdwa_bytenum
;
742 fprintf(output
, "[%u:%u]", index
* 8, index
* 8 + 7);
746 fprintf(output
, "|");
748 if (instr
->format
== Format::VOP3P
) {
749 const VOP3P_instruction
* vop3
= static_cast<const VOP3P_instruction
*>(instr
);
750 if ((vop3
->opsel_lo
& (1 << i
)) || !(vop3
->opsel_hi
& (1 << i
))) {
751 fprintf(output
, ".%c%c",
752 vop3
->opsel_lo
& (1 << i
) ? 'y' : 'x',
753 vop3
->opsel_hi
& (1 << i
) ? 'y' : 'x');
755 if (vop3
->neg_lo
[i
] && vop3
->neg_hi
[i
])
756 fprintf(output
, "*[-1,-1]");
757 else if (vop3
->neg_lo
[i
])
758 fprintf(output
, "*[-1,1]");
759 else if (vop3
->neg_hi
[i
])
760 fprintf(output
, "*[1,-1]");
764 print_instr_format_specific(instr
, output
);
767 static void print_block_kind(uint16_t kind
, FILE *output
)
769 if (kind
& block_kind_uniform
)
770 fprintf(output
, "uniform, ");
771 if (kind
& block_kind_top_level
)
772 fprintf(output
, "top-level, ");
773 if (kind
& block_kind_loop_preheader
)
774 fprintf(output
, "loop-preheader, ");
775 if (kind
& block_kind_loop_header
)
776 fprintf(output
, "loop-header, ");
777 if (kind
& block_kind_loop_exit
)
778 fprintf(output
, "loop-exit, ");
779 if (kind
& block_kind_continue
)
780 fprintf(output
, "continue, ");
781 if (kind
& block_kind_break
)
782 fprintf(output
, "break, ");
783 if (kind
& block_kind_continue_or_break
)
784 fprintf(output
, "continue_or_break, ");
785 if (kind
& block_kind_discard
)
786 fprintf(output
, "discard, ");
787 if (kind
& block_kind_branch
)
788 fprintf(output
, "branch, ");
789 if (kind
& block_kind_merge
)
790 fprintf(output
, "merge, ");
791 if (kind
& block_kind_invert
)
792 fprintf(output
, "invert, ");
793 if (kind
& block_kind_uses_discard_if
)
794 fprintf(output
, "discard_if, ");
795 if (kind
& block_kind_needs_lowering
)
796 fprintf(output
, "needs_lowering, ");
797 if (kind
& block_kind_uses_demote
)
798 fprintf(output
, "uses_demote, ");
799 if (kind
& block_kind_export_end
)
800 fprintf(output
, "export_end, ");
803 static void print_stage(Stage stage
, FILE *output
)
805 fprintf(output
, "ACO shader stage: ");
807 if (stage
== compute_cs
)
808 fprintf(output
, "compute_cs");
809 else if (stage
== fragment_fs
)
810 fprintf(output
, "fragment_fs");
811 else if (stage
== gs_copy_vs
)
812 fprintf(output
, "gs_copy_vs");
813 else if (stage
== vertex_ls
)
814 fprintf(output
, "vertex_ls");
815 else if (stage
== vertex_es
)
816 fprintf(output
, "vertex_es");
817 else if (stage
== vertex_vs
)
818 fprintf(output
, "vertex_vs");
819 else if (stage
== tess_control_hs
)
820 fprintf(output
, "tess_control_hs");
821 else if (stage
== vertex_tess_control_hs
)
822 fprintf(output
, "vertex_tess_control_hs");
823 else if (stage
== tess_eval_es
)
824 fprintf(output
, "tess_eval_es");
825 else if (stage
== tess_eval_vs
)
826 fprintf(output
, "tess_eval_vs");
827 else if (stage
== geometry_gs
)
828 fprintf(output
, "geometry_gs");
829 else if (stage
== vertex_geometry_gs
)
830 fprintf(output
, "vertex_geometry_gs");
831 else if (stage
== tess_eval_geometry_gs
)
832 fprintf(output
, "tess_eval_geometry_gs");
833 else if (stage
== ngg_vertex_gs
)
834 fprintf(output
, "ngg_vertex_gs");
835 else if (stage
== ngg_tess_eval_gs
)
836 fprintf(output
, "ngg_tess_eval_gs");
837 else if (stage
== ngg_vertex_geometry_gs
)
838 fprintf(output
, "ngg_vertex_geometry_gs");
839 else if (stage
== ngg_tess_eval_geometry_gs
)
840 fprintf(output
, "ngg_tess_eval_geometry_gs");
842 fprintf(output
, "unknown");
844 fprintf(output
, "\n");
847 void aco_print_block(const Block
* block
, FILE *output
)
849 fprintf(output
, "BB%d\n", block
->index
);
850 fprintf(output
, "/* logical preds: ");
851 for (unsigned pred
: block
->logical_preds
)
852 fprintf(output
, "BB%d, ", pred
);
853 fprintf(output
, "/ linear preds: ");
854 for (unsigned pred
: block
->linear_preds
)
855 fprintf(output
, "BB%d, ", pred
);
856 fprintf(output
, "/ kind: ");
857 print_block_kind(block
->kind
, output
);
858 fprintf(output
, "*/\n");
859 for (auto const& instr
: block
->instructions
) {
860 fprintf(output
, "\t");
861 aco_print_instr(instr
.get(), output
);
862 fprintf(output
, "\n");
866 void aco_print_program(const Program
*program
, FILE *output
)
868 print_stage(program
->stage
, output
);
870 for (Block
const& block
: program
->blocks
)
871 aco_print_block(&block
, output
);
873 if (program
->constant_data
.size()) {
874 fprintf(output
, "\n/* constant data */\n");
875 for (unsigned i
= 0; i
< program
->constant_data
.size(); i
+= 32) {
876 fprintf(output
, "[%06d] ", i
);
877 unsigned line_size
= std::min
<size_t>(program
->constant_data
.size() - i
, 32);
878 for (unsigned j
= 0; j
< line_size
; j
+= 4) {
879 unsigned size
= std::min
<size_t>(program
->constant_data
.size() - (i
+ j
), 4);
881 memcpy(&v
, &program
->constant_data
[i
+ j
], size
);
882 fprintf(output
, " %08x", v
);
884 fprintf(output
, "\n");
888 fprintf(output
, "\n");