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 sz
= nir_alu_type_get_type_size(T
);
77 unsigned comps
= 128 / sz
;
81 for (unsigned i
= 0; i
< comps
; ++i
) {
82 unsigned C
= swizzle
[i
];
84 putchar(components
[C
]);
89 mir_get_unit(unsigned unit
)
92 case ALU_ENAB_VEC_MUL
:
94 case ALU_ENAB_SCAL_ADD
:
96 case ALU_ENAB_VEC_ADD
:
98 case ALU_ENAB_SCAL_MUL
:
100 case ALU_ENAB_VEC_LUT
:
102 case ALU_ENAB_BR_COMPACT
:
104 case ALU_ENAB_BRANCH
:
112 mir_print_constant_component(FILE *fp
, const midgard_constants
*consts
, unsigned c
,
113 midgard_reg_mode reg_mode
, bool half
,
114 unsigned mod
, midgard_alu_op op
)
116 bool is_sint
= false, is_uint
= false, is_hex
= false;
117 const char *opname
= alu_opcode_props
[op
].name
;
119 /* Add a sentinel name to prevent crashing */
123 if (opname
[0] == 'u') {
124 /* If the opcode starts with a 'u' we are sure we deal with an
125 * unsigned int operation
128 } else if (opname
[0] == 'i') {
129 /* Bit ops are easier to follow when the constant is printed in
130 * hexadecimal. Other operations starting with a 'i' are
131 * considered to operate on signed integers. That might not
132 * be true for all of them, but it's good enough for traces.
134 if (op
>= midgard_alu_op_iand
&&
135 op
<= midgard_alu_op_ibitcount8
)
145 case midgard_reg_mode_64
:
147 fprintf(fp
, "%"PRIi64
, consts
->i64
[c
]);
148 } else if (is_uint
) {
149 fprintf(fp
, "%"PRIu64
, consts
->u64
[c
]);
151 fprintf(fp
, "0x%"PRIX64
, consts
->u64
[c
]);
153 double v
= consts
->f64
[c
];
155 if (mod
& MIDGARD_FLOAT_MOD_ABS
) v
= fabs(v
);
156 if (mod
& MIDGARD_FLOAT_MOD_NEG
) v
= -v
;
162 case midgard_reg_mode_32
:
166 if (half
&& mod
== midgard_int_zero_extend
)
168 else if (half
&& mod
== midgard_int_shift
)
169 v
= (uint64_t)consts
->u32
[c
] << 32;
173 fprintf(fp
, "%"PRIi64
, v
);
174 } else if (is_uint
|| is_hex
) {
177 if (half
&& mod
== midgard_int_shift
)
178 v
= (uint64_t)consts
->u32
[c
] << 32;
182 fprintf(fp
, is_uint
? "%"PRIu64
: "0x%"PRIX64
, v
);
184 float v
= consts
->f32
[c
];
186 if (mod
& MIDGARD_FLOAT_MOD_ABS
) v
= fabsf(v
);
187 if (mod
& MIDGARD_FLOAT_MOD_NEG
) v
= -v
;
189 fprintf(fp
, "%g", v
);
193 case midgard_reg_mode_16
:
197 if (half
&& mod
== midgard_int_zero_extend
)
199 else if (half
&& mod
== midgard_int_shift
)
200 v
= (uint32_t)consts
->u16
[c
] << 16;
204 fprintf(fp
, "%d", v
);
205 } else if (is_uint
|| is_hex
) {
208 if (half
&& mod
== midgard_int_shift
)
209 v
= (uint32_t)consts
->u16
[c
] << 16;
213 fprintf(fp
, is_uint
? "%u" : "0x%X", v
);
215 float v
= _mesa_half_to_float(consts
->f16
[c
]);
217 if (mod
& MIDGARD_FLOAT_MOD_ABS
) v
= fabsf(v
);
218 if (mod
& MIDGARD_FLOAT_MOD_NEG
) v
= -v
;
220 fprintf(fp
, "%g", v
);
224 case midgard_reg_mode_8
:
225 unreachable("XXX TODO: sort out how 8-bit constant encoding works");
231 mir_print_embedded_constant(midgard_instruction
*ins
, unsigned src_idx
)
233 unsigned type_size
= nir_alu_type_get_type_size(ins
->dest_type
);
234 midgard_vector_alu_src src
;
236 assert(src_idx
<= 1);
238 src
= vector_alu_from_unsigned(ins
->alu
.src1
);
240 src
= vector_alu_from_unsigned(ins
->alu
.src2
);
242 unsigned *swizzle
= ins
->swizzle
[src_idx
];
243 unsigned comp_mask
= effective_writemask(&ins
->alu
, ins
->mask
);
244 unsigned num_comp
= util_bitcount(comp_mask
);
245 unsigned max_comp
= 64 / type_size
;
251 printf("vec%d(", num_comp
);
253 for (unsigned comp
= 0; comp
< max_comp
; comp
++) {
254 if (!(comp_mask
& (1 << comp
)))
262 mir_print_constant_component(stdout
, &ins
->constants
,
263 swizzle
[comp
], ins
->alu
.reg_mode
,
264 src
.half
, src
.mod
, ins
->alu
.op
);
272 mir_print_instruction(midgard_instruction
*ins
)
276 if (midgard_is_branch_unit(ins
->unit
)) {
277 const char *branch_target_names
[] = {
278 "goto", "break", "continue", "discard"
281 printf("%s.", mir_get_unit(ins
->unit
));
282 if (ins
->branch
.target_type
== TARGET_DISCARD
)
284 else if (ins
->writeout
)
286 else if (ins
->unit
== ALU_ENAB_BR_COMPACT
&&
287 !ins
->branch
.conditional
)
292 if (!ins
->branch
.conditional
)
294 else if (ins
->branch
.invert_conditional
)
299 if (ins
->branch
.target_type
!= TARGET_DISCARD
)
300 printf(" %s -> block(%d)\n",
301 ins
->branch
.target_type
< 4 ?
302 branch_target_names
[ins
->branch
.target_type
] : "??",
303 ins
->branch
.target_block
);
310 midgard_alu_op op
= ins
->alu
.op
;
311 const char *name
= alu_opcode_props
[op
].name
;
314 printf("%s.", mir_get_unit(ins
->unit
));
316 printf("%s", name
? name
: "??");
320 case TAG_LOAD_STORE_4
: {
321 midgard_load_store_op op
= ins
->load_store
.op
;
322 const char *name
= load_store_opcode_props
[op
].name
;
329 case TAG_TEXTURE_4
: {
332 if (ins
->helper_terminate
)
333 printf(".terminate");
335 if (ins
->helper_execute
)
345 if (ins
->compact_branch
&& ins
->branch
.invert_conditional
)
349 mir_print_index(ins
->dest
);
352 pan_print_alu_type(ins
->dest_type
, stdout
);
353 mir_print_mask(ins
->mask
);
358 unsigned r_constant
= SSA_FIXED_REGISTER(REGISTER_CONSTANT
);
360 if (ins
->src
[0] == r_constant
)
361 mir_print_embedded_constant(ins
, 0);
363 mir_print_index(ins
->src
[0]);
365 if (ins
->src
[0] != ~0) {
366 pan_print_alu_type(ins
->src_types
[0], stdout
);
367 mir_print_swizzle(ins
->swizzle
[0], ins
->src_types
[0]);
372 if (ins
->has_inline_constant
)
373 printf("#%d", ins
->inline_constant
);
374 else if (ins
->src
[1] == r_constant
)
375 mir_print_embedded_constant(ins
, 1);
377 mir_print_index(ins
->src
[1]);
379 if (ins
->src
[1] != ~0) {
380 pan_print_alu_type(ins
->src_types
[1], stdout
);
381 mir_print_swizzle(ins
->swizzle
[1], ins
->src_types
[1]);
385 for (unsigned c
= 2; c
<= 3; ++c
) {
387 mir_print_index(ins
->src
[c
]);
389 if (ins
->src
[c
] != ~0) {
390 pan_print_alu_type(ins
->src_types
[c
], stdout
);
391 mir_print_swizzle(ins
->swizzle
[c
], ins
->src_types
[c
]);
396 printf(" /* no spill */");
401 /* Dumps MIR for a block or entire shader respective */
404 mir_print_block(midgard_block
*block
)
406 printf("block%u: {\n", block
->base
.name
);
408 if (block
->scheduled
) {
409 mir_foreach_bundle_in_block(block
, bundle
) {
410 for (unsigned i
= 0; i
< bundle
->instruction_count
; ++i
)
411 mir_print_instruction(bundle
->instructions
[i
]);
416 mir_foreach_instr_in_block(block
, ins
) {
417 mir_print_instruction(ins
);
423 if (block
->base
.successors
[0]) {
425 pan_foreach_successor((&block
->base
), succ
)
426 printf(" block%u ", succ
->name
);
430 mir_foreach_predecessor(block
, pred
)
431 printf("block%u ", pred
->base
.name
);
438 mir_print_shader(compiler_context
*ctx
)
440 mir_foreach_block(ctx
, block
) {
441 mir_print_block((midgard_block
*) block
);