2 * Copyright (C) 2018-2019 Alyssa Rosenzweig <alyssa@rosenzweig.io>
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
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
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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "util/bitscan.h"
27 #include "util/half_float.h"
30 #include "midgard_ops.h"
32 /* Pretty printer for Midgard IR, for use debugging compiler-internal
33 * passes like register allocation. The output superficially resembles
34 * Midgard assembly, with the exception that unit information and such is
35 * (normally) omitted, and generic indices are usually used instead of
39 mir_print_index(int source
)
46 if (source
>= SSA_FIXED_MINIMUM
) {
47 /* Specific register */
48 int reg
= SSA_REG_FROM_FIXED(source
);
50 /* TODO: Moving threshold */
51 if (reg
> 16 && reg
< 24)
52 printf("u%d", 23 - reg
);
60 static const char components
[16] = "xyzwefghijklmnop";
63 mir_print_mask(unsigned mask
)
67 for (unsigned i
= 0; i
< 16; ++i
) {
69 putchar(components
[i
]);
74 mir_print_swizzle(unsigned *swizzle
, nir_alu_type T
)
76 unsigned comps
= mir_components_for_type(T
);
80 for (unsigned i
= 0; i
< comps
; ++i
) {
81 unsigned C
= swizzle
[i
];
83 putchar(components
[C
]);
88 mir_get_unit(unsigned unit
)
91 case ALU_ENAB_VEC_MUL
:
93 case ALU_ENAB_SCAL_ADD
:
95 case ALU_ENAB_VEC_ADD
:
97 case ALU_ENAB_SCAL_MUL
:
99 case ALU_ENAB_VEC_LUT
:
101 case ALU_ENAB_BR_COMPACT
:
103 case ALU_ENAB_BRANCH
:
111 mir_print_embedded_constant(midgard_instruction
*ins
, unsigned src_idx
)
113 assert(src_idx
<= 1);
115 unsigned base_size
= max_bitsize_for_alu(ins
);
116 unsigned sz
= nir_alu_type_get_type_size(ins
->src_types
[src_idx
]);
117 bool half
= (sz
== (base_size
>> 1));
118 unsigned mod
= mir_pack_mod(ins
, src_idx
, false);
119 unsigned *swizzle
= ins
->swizzle
[src_idx
];
120 midgard_reg_mode reg_mode
= reg_mode_for_bitsize(max_bitsize_for_alu(ins
));
121 unsigned comp_mask
= effective_writemask(ins
->op
, ins
->mask
);
122 unsigned num_comp
= util_bitcount(comp_mask
);
123 unsigned max_comp
= mir_components_for_type(ins
->dest_type
);
129 printf("vec%d(", num_comp
);
131 for (unsigned comp
= 0; comp
< max_comp
; comp
++) {
132 if (!(comp_mask
& (1 << comp
)))
140 mir_print_constant_component(stdout
, &ins
->constants
,
141 swizzle
[comp
], reg_mode
,
149 #define PRINT_SRC(ins, c) \
150 do { mir_print_index(ins->src[c]); \
151 if (ins->src[c] != ~0 && ins->src_types[c] != nir_type_invalid) { \
152 pan_print_alu_type(ins->src_types[c], stdout); \
153 mir_print_swizzle(ins->swizzle[c], ins->src_types[c]); \
157 mir_print_instruction(midgard_instruction
*ins
)
161 if (midgard_is_branch_unit(ins
->unit
)) {
162 const char *branch_target_names
[] = {
163 "goto", "break", "continue", "discard"
166 printf("%s.", mir_get_unit(ins
->unit
));
167 if (ins
->branch
.target_type
== TARGET_DISCARD
)
169 else if (ins
->writeout
)
171 else if (ins
->unit
== ALU_ENAB_BR_COMPACT
&&
172 !ins
->branch
.conditional
)
177 if (!ins
->branch
.conditional
)
179 else if (ins
->branch
.invert_conditional
)
194 if (ins
->branch
.target_type
!= TARGET_DISCARD
)
195 printf(" %s -> block(%d)\n",
196 ins
->branch
.target_type
< 4 ?
197 branch_target_names
[ins
->branch
.target_type
] : "??",
198 ins
->branch
.target_block
);
205 midgard_alu_op op
= ins
->op
;
206 const char *name
= alu_opcode_props
[op
].name
;
209 printf("%s.", mir_get_unit(ins
->unit
));
211 printf("%s", name
? name
: "??");
215 case TAG_LOAD_STORE_4
: {
216 midgard_load_store_op op
= ins
->op
;
217 const char *name
= load_store_opcode_props
[op
].name
;
224 case TAG_TEXTURE_4
: {
227 if (ins
->helper_terminate
)
228 printf(".terminate");
230 if (ins
->helper_execute
)
240 if (ins
->compact_branch
&& ins
->branch
.invert_conditional
)
244 mir_print_index(ins
->dest
);
246 if (ins
->dest
!= ~0) {
247 pan_print_alu_type(ins
->dest_type
, stdout
);
248 mir_print_mask(ins
->mask
);
253 /* Only ALU can have an embedded constant, r26 as read on load/store is
254 * something else entirely */
255 bool is_alu
= ins
->type
== TAG_ALU_4
;
256 unsigned r_constant
= SSA_FIXED_REGISTER(REGISTER_CONSTANT
);
258 if (ins
->src
[0] == r_constant
&& is_alu
)
259 mir_print_embedded_constant(ins
, 0);
265 if (ins
->has_inline_constant
)
266 printf("#%d", ins
->inline_constant
);
267 else if (ins
->src
[1] == r_constant
&& is_alu
)
268 mir_print_embedded_constant(ins
, 1);
272 for (unsigned c
= 2; c
<= 3; ++c
) {
278 printf(" /* no spill */");
283 /* Dumps MIR for a block or entire shader respective */
286 mir_print_block(midgard_block
*block
)
288 printf("block%u: {\n", block
->base
.name
);
290 if (block
->scheduled
) {
291 mir_foreach_bundle_in_block(block
, bundle
) {
292 for (unsigned i
= 0; i
< bundle
->instruction_count
; ++i
)
293 mir_print_instruction(bundle
->instructions
[i
]);
298 mir_foreach_instr_in_block(block
, ins
) {
299 mir_print_instruction(ins
);
305 if (block
->base
.successors
[0]) {
307 pan_foreach_successor((&block
->base
), succ
)
308 printf(" block%u ", succ
->name
);
312 mir_foreach_predecessor(block
, pred
)
313 printf("block%u ", pred
->base
.name
);
320 mir_print_shader(compiler_context
*ctx
)
322 mir_foreach_block(ctx
, block
) {
323 mir_print_block((midgard_block
*) block
);