pan/midgard: Print MIR by the bundle
[mesa.git] / src / panfrost / midgard / midgard_print.c
1 /*
2 * Copyright (C) 2018-2019 Alyssa Rosenzweig <alyssa@rosenzweig.io>
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 * 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:
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 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
21 * SOFTWARE.
22 */
23
24 #include "compiler.h"
25 #include "helpers.h"
26 #include "midgard_ops.h"
27
28 /* Pretty printer for Midgard IR, for use debugging compiler-internal
29 * passes like register allocation. The output superficially resembles
30 * Midgard assembly, with the exception that unit information and such is
31 * (normally) omitted, and generic indices are usually used instead of
32 * registers */
33
34 static void
35 mir_print_index(int source)
36 {
37 if (source == ~0) {
38 printf("_");
39 return;
40 }
41
42 if (source >= SSA_FIXED_MINIMUM) {
43 /* Specific register */
44 int reg = SSA_REG_FROM_FIXED(source);
45
46 /* TODO: Moving threshold */
47 if (reg > 16 && reg < 24)
48 printf("u%d", 23 - reg);
49 else
50 printf("r%d", reg);
51 } else {
52 printf("%d", source);
53 }
54 }
55
56 static const char components[16] = "xyzwefghijklmnop";
57
58 static void
59 mir_print_mask(unsigned mask)
60 {
61 printf(".");
62
63 for (unsigned i = 0; i < 16; ++i) {
64 if (mask & (1 << i))
65 putchar(components[i]);
66 }
67 }
68
69 static const char *
70 mir_get_unit(unsigned unit)
71 {
72 switch (unit) {
73 case ALU_ENAB_VEC_MUL:
74 return "vmul";
75 case ALU_ENAB_SCAL_ADD:
76 return "sadd";
77 case ALU_ENAB_VEC_ADD:
78 return "vadd";
79 case ALU_ENAB_SCAL_MUL:
80 return "smul";
81 case ALU_ENAB_VEC_LUT:
82 return "lut";
83 case ALU_ENAB_BR_COMPACT:
84 return "br";
85 case ALU_ENAB_BRANCH:
86 return "brx";
87 default:
88 return "???";
89 }
90 }
91
92 void
93 mir_print_instruction(midgard_instruction *ins)
94 {
95 printf("\t");
96
97 switch (ins->type) {
98 case TAG_ALU_4: {
99 midgard_alu_op op = ins->alu.op;
100 const char *name = alu_opcode_props[op].name;
101
102 const char *branch_target_names[] = {
103 "goto", "break", "continue", "discard"
104 };
105
106 if (ins->compact_branch && !ins->prepacked_branch)
107 name = branch_target_names[ins->branch.target_type];
108
109 if (ins->unit)
110 printf("%s.", mir_get_unit(ins->unit));
111
112 printf("%s", name ? name : "??");
113 break;
114 }
115
116 case TAG_LOAD_STORE_4: {
117 midgard_load_store_op op = ins->load_store.op;
118 const char *name = load_store_opcode_names[op];
119
120 assert(name);
121 printf("%s", name);
122 break;
123 }
124
125 case TAG_TEXTURE_4: {
126 printf("texture");
127 break;
128 }
129
130 default:
131 assert(0);
132 }
133
134 if (ins->invert || (ins->compact_branch && !ins->prepacked_branch && ins->branch.invert_conditional))
135 printf(".not");
136
137 printf(" ");
138 mir_print_index(ins->dest);
139
140 if (ins->mask != 0xF)
141 mir_print_mask(ins->mask);
142
143 printf(", ");
144
145 mir_print_index(ins->src[0]);
146 printf(", ");
147
148 if (ins->has_inline_constant)
149 printf("#%d", ins->inline_constant);
150 else
151 mir_print_index(ins->src[1]);
152
153 printf(", ");
154 mir_print_index(ins->src[2]);
155
156 if (ins->has_constants) {
157 uint32_t *uc = ins->constants;
158 float *fc = (float *) uc;
159
160 if (midgard_is_integer_op(ins->alu.op))
161 printf(" <0x%X, 0x%X, 0x%X, 0x%x>", uc[0], uc[1], uc[2], uc[3]);
162 else
163 printf(" <%f, %f, %f, %f>", fc[0], fc[1], fc[2], fc[3]);
164 }
165
166 if (ins->no_spill)
167 printf(" /* no spill */");
168
169 printf("\n");
170 }
171
172 /* Dumps MIR for a block or entire shader respective */
173
174 void
175 mir_print_block(midgard_block *block)
176 {
177 printf("block%d: {\n", block->source_id);
178
179 if (block->is_scheduled) {
180 mir_foreach_bundle_in_block(block, bundle) {
181 for (unsigned i = 0; i < bundle->instruction_count; ++i)
182 mir_print_instruction(bundle->instructions[i]);
183
184 printf("\n");
185 }
186 } else {
187 mir_foreach_instr_in_block(block, ins) {
188 mir_print_instruction(ins);
189 }
190 }
191
192 printf("}");
193
194 if (block->nr_successors) {
195 printf(" -> ");
196 for (unsigned i = 0; i < block->nr_successors; ++i) {
197 printf("block%d%s", block->successors[i]->source_id,
198 (i + 1) != block->nr_successors ? ", " : "");
199 }
200 }
201
202 printf(" from { ");
203 mir_foreach_predecessor(block, pred)
204 printf("block%d ", pred->source_id);
205 printf("}");
206
207 printf("\n\n");
208 }
209
210 void
211 mir_print_shader(compiler_context *ctx)
212 {
213 mir_foreach_block(ctx, block) {
214 mir_print_block(block);
215 }
216 }
217
218 void
219 mir_print_bundle(midgard_bundle *bundle)
220 {
221 printf("[\n");
222
223 for (unsigned i = 0; i < bundle->instruction_count; ++i) {
224 midgard_instruction *ins = bundle->instructions[i];
225 mir_print_instruction(ins);
226 }
227
228 printf("]\n");
229 }