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