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