1 /*
2 * Copyright © 2020 Google, Inc.
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 <stdlib.h>
25
26 #include "util/ralloc.h"
27
28 #include "ir3.h"
29
30 struct ir3_validate_ctx {
31 struct ir3 *ir;
32
33 /* Current block being validated: */
34 struct ir3_block *current_block;
35
36 /* Current instruction being validated: */
37 struct ir3_instruction *current_instr;
38
39 /* Set of instructions found so far, used to validate that we
40 * don't have SSA uses that occure before def's
41 */
42 struct set *defs;
43 };
44
45 static void
validate_error(struct ir3_validate_ctx * ctx,const char * condstr)46 validate_error(struct ir3_validate_ctx *ctx, const char *condstr)
47 {
48 fprintf(stderr, "validation fail: %s\n", condstr);
49 if (ctx->current_instr) {
50 fprintf(stderr, " -> for instruction: ");
51 ir3_print_instr(ctx->current_instr);
52 } else {
53 fprintf(stderr, " -> for block%u\n", block_id(ctx->current_block));
54 }
55 abort();
56 }
57
58 #define validate_assert(ctx, cond) \
59 do { \
60 if (!(cond)) { \
61 validate_error(ctx, #cond); \
62 } \
63 } while (0)
64
65 static unsigned
reg_class_flags(struct ir3_register * reg)66 reg_class_flags(struct ir3_register *reg)
67 {
68 return reg->flags & (IR3_REG_HALF | IR3_REG_SHARED);
69 }
70
71 static void
validate_src(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)72 validate_src(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
73 struct ir3_register *reg)
74 {
75 if (reg->flags & IR3_REG_IMMED)
76 validate_assert(ctx, ir3_valid_immediate(instr, reg->iim_val));
77
78 if (!(reg->flags & IR3_REG_SSA) || !reg->def)
79 return;
80
81 struct ir3_register *src = reg->def;
82
83 validate_assert(ctx, _mesa_set_search(ctx->defs, src->instr));
84 validate_assert(ctx, src->wrmask == reg->wrmask);
85 validate_assert(ctx, reg_class_flags(src) == reg_class_flags(reg));
86
87 if (src->flags & IR3_REG_CONST)
88 validate_assert(ctx, !(src->flags & IR3_REG_SHARED));
89
90 if (reg->tied) {
91 validate_assert(ctx, reg->tied->tied == reg);
92 bool found = false;
93 foreach_dst (dst, instr) {
94 if (dst == reg->tied) {
95 found = true;
96 break;
97 }
98 }
99 validate_assert(ctx,
100 found && "tied register not in the same instruction");
101 }
102 }
103
104 /* phi sources are logically read at the end of the predecessor basic block,
105 * and we have to validate them then in order to correctly validate that the
106 * use comes after the definition for loop phis.
107 */
108 static void
validate_phi_src(struct ir3_validate_ctx * ctx,struct ir3_block * block,struct ir3_block * pred)109 validate_phi_src(struct ir3_validate_ctx *ctx, struct ir3_block *block,
110 struct ir3_block *pred)
111 {
112 unsigned pred_idx = ir3_block_get_pred_index(block, pred);
113
114 foreach_instr (phi, &block->instr_list) {
115 if (phi->opc != OPC_META_PHI)
116 break;
117
118 ctx->current_instr = phi;
119 validate_assert(ctx, phi->srcs_count == block->predecessors_count);
120 validate_src(ctx, phi, phi->srcs[pred_idx]);
121 }
122 }
123
124 static void
validate_phi(struct ir3_validate_ctx * ctx,struct ir3_instruction * phi)125 validate_phi(struct ir3_validate_ctx *ctx, struct ir3_instruction *phi)
126 {
127 _mesa_set_add(ctx->defs, phi);
128 validate_assert(ctx, phi->dsts_count == 1);
129 validate_assert(ctx, is_dest_gpr(phi->dsts[0]));
130 }
131
132 static void
validate_dst(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * reg)133 validate_dst(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
134 struct ir3_register *reg)
135 {
136 if (reg->tied) {
137 validate_assert(ctx, reg->tied->tied == reg);
138 validate_assert(ctx, reg_class_flags(reg->tied) == reg_class_flags(reg));
139 validate_assert(ctx, reg->tied->wrmask == reg->wrmask);
140 if (reg->flags & IR3_REG_ARRAY) {
141 validate_assert(ctx, reg->tied->array.base == reg->array.base);
142 validate_assert(ctx, reg->tied->size == reg->size);
143 }
144 bool found = false;
145 foreach_src (src, instr) {
146 if (src == reg->tied) {
147 found = true;
148 break;
149 }
150 }
151 validate_assert(ctx,
152 found && "tied register not in the same instruction");
153 }
154
155 if (reg->flags & IR3_REG_SSA)
156 validate_assert(ctx, reg->instr == instr);
157
158 if (reg->flags & IR3_REG_RELATIV)
159 validate_assert(ctx, instr->address);
160 }
161
162 #define validate_reg_size(ctx, reg, type) \
163 validate_assert( \
164 ctx, (type_size(type) <= 16) == !!((reg)->flags & IR3_REG_HALF))
165
166 static void
validate_instr(struct ir3_validate_ctx * ctx,struct ir3_instruction * instr)167 validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
168 {
169 struct ir3_register *last_reg = NULL;
170
171 foreach_src_n (reg, n, instr) {
172 if (reg->flags & IR3_REG_RELATIV)
173 validate_assert(ctx, instr->address);
174
175 validate_src(ctx, instr, reg);
176
177 /* Validate that all src's are either half of full.
178 *
179 * Note: tex instructions w/ .s2en are a bit special in that the
180 * tex/samp src reg is half-reg for non-bindless and full for
181 * bindless, irrespective of the precision of other srcs. The
182 * tex/samp src is the first src reg when .s2en is set
183 */
184 if (reg->tied) {
185 /* must have the same size as the destination, handled in
186 * validate_reg().
187 */
188 } else if (reg == instr->address) {
189 validate_assert(ctx, reg->flags & IR3_REG_HALF);
190 } else if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) {
191 if (n == 0) {
192 if (instr->flags & IR3_INSTR_B)
193 validate_assert(ctx, !(reg->flags & IR3_REG_HALF));
194 else
195 validate_assert(ctx, reg->flags & IR3_REG_HALF);
196 }
197 } else if (opc_cat(instr->opc) == 1 || opc_cat(instr->opc) == 6) {
198 /* handled below */
199 } else if (opc_cat(instr->opc) == 0) {
200 /* end/chmask/etc are allowed to have different size sources */
201 } else if (instr->opc == OPC_META_PARALLEL_COPY) {
202 /* pcopy sources have to match with their destination but can have
203 * different sizes from each other.
204 */
205 } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
206 instr->opc == OPC_READ_FIRST_MACRO ||
207 instr->opc == OPC_READ_COND_MACRO) {
208 /* nothing yet */
209 } else if (n > 0) {
210 validate_assert(ctx, (last_reg->flags & IR3_REG_HALF) ==
211 (reg->flags & IR3_REG_HALF));
212 }
213
214 last_reg = reg;
215 }
216
217 for (unsigned i = 0; i < instr->dsts_count; i++) {
218 struct ir3_register *reg = instr->dsts[i];
219
220 validate_dst(ctx, instr, reg);
221 }
222
223 _mesa_set_add(ctx->defs, instr);
224
225 /* Check that src/dst types match the register types, and for
226 * instructions that have different opcodes depending on type,
227 * that the opcodes are correct.
228 */
229 switch (opc_cat(instr->opc)) {
230 case 1: /* move instructions */
231 if (instr->opc == OPC_MOVMSK || instr->opc == OPC_BALLOT_MACRO) {
232 validate_assert(ctx, instr->dsts_count == 1);
233 validate_assert(ctx, instr->dsts[0]->flags & IR3_REG_SHARED);
234 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
235 validate_assert(
236 ctx, util_is_power_of_two_or_zero(instr->dsts[0]->wrmask + 1));
237 } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
238 instr->opc == OPC_READ_FIRST_MACRO ||
239 instr->opc == OPC_READ_COND_MACRO) {
240 /* nothing yet */
241 } else if (instr->opc == OPC_ELECT_MACRO || instr->opc == OPC_SHPS_MACRO) {
242 validate_assert(ctx, instr->dsts_count == 1);
243 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_SHARED));
244 } else if (instr->opc == OPC_SCAN_MACRO) {
245 validate_assert(ctx, instr->dsts_count == 3);
246 validate_assert(ctx, instr->srcs_count == 2);
247 validate_assert(ctx, reg_class_flags(instr->dsts[0]) ==
248 reg_class_flags(instr->srcs[0]));
249 validate_assert(ctx, reg_class_flags(instr->dsts[1]) ==
250 reg_class_flags(instr->srcs[0]));
251 validate_assert(ctx, reg_class_flags(instr->dsts[2]) == IR3_REG_SHARED);
252 } else if (instr->opc == OPC_SCAN_CLUSTERS_MACRO) {
253 validate_assert(ctx, instr->dsts_count >= 2 && instr->dsts_count < 5);
254 validate_assert(ctx, instr->srcs_count >= 2 && instr->srcs_count < 4);
255 validate_assert(ctx,
256 reg_class_flags(instr->dsts[0]) == IR3_REG_SHARED);
257 validate_assert(ctx, reg_class_flags(instr->dsts[1]) ==
258 reg_class_flags(instr->srcs[1]));
259
260 /* exclusive scan */
261 if (instr->srcs_count == 3) {
262 validate_assert(ctx, instr->dsts_count >= 3);
263 validate_assert(ctx, reg_class_flags(instr->srcs[2]) ==
264 reg_class_flags(instr->srcs[1]));
265 validate_assert(ctx, reg_class_flags(instr->dsts[2]) ==
266 reg_class_flags(instr->srcs[1]));
267 }
268
269 /* scratch register */
270 validate_assert(ctx,
271 reg_class_flags(instr->dsts[instr->dsts_count - 1]) ==
272 reg_class_flags(instr->srcs[1]));
273 } else {
274 foreach_dst (dst, instr)
275 validate_reg_size(ctx, dst, instr->cat1.dst_type);
276 foreach_src (src, instr) {
277 if (!src->tied && src != instr->address)
278 validate_reg_size(ctx, src, instr->cat1.src_type);
279 }
280
281 switch (instr->opc) {
282 case OPC_SWZ:
283 validate_assert(ctx, instr->srcs_count == 2);
284 validate_assert(ctx, instr->dsts_count == 2);
285 break;
286 case OPC_GAT:
287 validate_assert(ctx, instr->srcs_count == 4);
288 validate_assert(ctx, instr->dsts_count == 1);
289 break;
290 case OPC_SCT:
291 validate_assert(ctx, instr->srcs_count == 1);
292 validate_assert(ctx, instr->dsts_count == 4);
293 break;
294 default:
295 break;
296 }
297 }
298
299 if (instr->opc != OPC_MOV)
300 validate_assert(ctx, !instr->address);
301
302 break;
303 case 3:
304 /* Validate that cat3 opc matches the src type. We've already checked
305 * that all the src regs are same type
306 */
307 if (instr->srcs[0]->flags & IR3_REG_HALF) {
308 validate_assert(ctx, instr->opc == cat3_half_opc(instr->opc));
309 } else {
310 validate_assert(ctx, instr->opc == cat3_full_opc(instr->opc));
311 }
312 break;
313 case 4:
314 /* Validate that cat4 opc matches the dst type: */
315 if (instr->dsts[0]->flags & IR3_REG_HALF) {
316 validate_assert(ctx, instr->opc == cat4_half_opc(instr->opc));
317 } else {
318 validate_assert(ctx, instr->opc == cat4_full_opc(instr->opc));
319 }
320 break;
321 case 5:
322 validate_reg_size(ctx, instr->dsts[0], instr->cat5.type);
323 break;
324 case 6:
325 switch (instr->opc) {
326 case OPC_RESINFO:
327 case OPC_RESFMT:
328 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
329 validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
330 break;
331 case OPC_L2G:
332 case OPC_G2L:
333 validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
334 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
335 break;
336 case OPC_STG:
337 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
338 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
339 validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
340 validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
341 break;
342 case OPC_STG_A:
343 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
344 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
345 validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
346 validate_reg_size(ctx, instr->srcs[4], instr->cat6.type);
347 validate_assert(ctx, !(instr->srcs[5]->flags & IR3_REG_HALF));
348 break;
349 case OPC_STL:
350 case OPC_STP:
351 case OPC_STLW:
352 case OPC_SPILL_MACRO:
353 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
354 validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
355 validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
356 break;
357 case OPC_STIB:
358 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
359 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
360 validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
361 break;
362 case OPC_GETFIBERID:
363 case OPC_GETSPID:
364 case OPC_GETWID:
365 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
366 break;
367 case OPC_STC:
368 case OPC_STSC:
369 validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
370 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
371 break;
372 case OPC_LDC_K:
373 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
374 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
375 break;
376 default:
377 validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
378 validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
379 if (instr->srcs_count > 1)
380 validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
381 break;
382 }
383 }
384
385 if (instr->opc == OPC_META_PARALLEL_COPY) {
386 foreach_src_n (src, n, instr) {
387 validate_assert(ctx, reg_class_flags(src) ==
388 reg_class_flags(instr->dsts[n]));
389 }
390 }
391 }
392
393 static bool
is_physical_successor(struct ir3_block * block,struct ir3_block * succ)394 is_physical_successor(struct ir3_block *block, struct ir3_block *succ)
395 {
396 for (unsigned i = 0; i < block->physical_successors_count; i++)
397 if (block->physical_successors[i] == succ)
398 return true;
399 return false;
400 }
401
402 void
ir3_validate(struct ir3 * ir)403 ir3_validate(struct ir3 *ir)
404 {
405 #ifdef NDEBUG
406 #define VALIDATE 0
407 #else
408 #define VALIDATE 1
409 #endif
410
411 if (!VALIDATE)
412 return;
413
414 struct ir3_validate_ctx *ctx = ralloc_size(NULL, sizeof(*ctx));
415
416 ctx->ir = ir;
417 ctx->defs = _mesa_pointer_set_create(ctx);
418
419 foreach_block (block, &ir->block_list) {
420 ctx->current_block = block;
421 ctx->current_instr = NULL;
422
423 /* We require that the first block does not have any predecessors,
424 * which allows us to assume that phi nodes and meta:input's do not
425 * appear in the same basic block.
426 */
427 validate_assert(
428 ctx, block != ir3_start_block(ir) || block->predecessors_count == 0);
429
430 struct ir3_instruction *prev = NULL;
431 foreach_instr (instr, &block->instr_list) {
432 ctx->current_instr = instr;
433 if (instr->opc == OPC_META_PHI) {
434 /* phis must be the first in the block */
435 validate_assert(ctx, prev == NULL || prev->opc == OPC_META_PHI);
436 validate_phi(ctx, instr);
437 } else {
438 validate_instr(ctx, instr);
439 }
440 prev = instr;
441 }
442
443 for (unsigned i = 0; i < 2; i++) {
444 if (block->successors[i]) {
445 validate_phi_src(ctx, block->successors[i], block);
446
447 ctx->current_instr = NULL;
448
449 /* Each logical successor should also be a physical successor: */
450 if (block->physical_successors_count > 0)
451 validate_assert(ctx, is_physical_successor(block, block->successors[i]));
452 }
453 }
454
455 validate_assert(ctx, block->successors[0] || !block->successors[1]);
456 }
457
458 ralloc_free(ctx);
459 }
460