17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2020 Google, Inc.
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217ec681f3Smrg * SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include <stdlib.h>
257ec681f3Smrg
267ec681f3Smrg#include "util/ralloc.h"
277ec681f3Smrg
287ec681f3Smrg#include "ir3.h"
297ec681f3Smrg
307ec681f3Smrgstruct ir3_validate_ctx {
317ec681f3Smrg   struct ir3 *ir;
327ec681f3Smrg
337ec681f3Smrg   /* Current block being validated: */
347ec681f3Smrg   struct ir3_block *current_block;
357ec681f3Smrg
367ec681f3Smrg   /* Current instruction being validated: */
377ec681f3Smrg   struct ir3_instruction *current_instr;
387ec681f3Smrg
397ec681f3Smrg   /* Set of instructions found so far, used to validate that we
407ec681f3Smrg    * don't have SSA uses that occure before def's
417ec681f3Smrg    */
427ec681f3Smrg   struct set *defs;
437ec681f3Smrg};
447ec681f3Smrg
457ec681f3Smrgstatic void
467ec681f3Smrgvalidate_error(struct ir3_validate_ctx *ctx, const char *condstr)
477ec681f3Smrg{
487ec681f3Smrg   fprintf(stderr, "validation fail: %s\n", condstr);
497ec681f3Smrg   if (ctx->current_instr) {
507ec681f3Smrg      fprintf(stderr, "  -> for instruction: ");
517ec681f3Smrg      ir3_print_instr(ctx->current_instr);
527ec681f3Smrg   } else {
537ec681f3Smrg      fprintf(stderr, "  -> for block%u\n", block_id(ctx->current_block));
547ec681f3Smrg   }
557ec681f3Smrg   abort();
567ec681f3Smrg}
577ec681f3Smrg
587ec681f3Smrg#define validate_assert(ctx, cond)                                             \
597ec681f3Smrg   do {                                                                        \
607ec681f3Smrg      if (!(cond)) {                                                           \
617ec681f3Smrg         validate_error(ctx, #cond);                                           \
627ec681f3Smrg      }                                                                        \
637ec681f3Smrg   } while (0)
647ec681f3Smrg
657ec681f3Smrgstatic unsigned
667ec681f3Smrgreg_class_flags(struct ir3_register *reg)
677ec681f3Smrg{
687ec681f3Smrg   return reg->flags & (IR3_REG_HALF | IR3_REG_SHARED);
697ec681f3Smrg}
707ec681f3Smrg
717ec681f3Smrgstatic void
727ec681f3Smrgvalidate_src(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
737ec681f3Smrg             struct ir3_register *reg)
747ec681f3Smrg{
757ec681f3Smrg   if (reg->flags & IR3_REG_IMMED)
767ec681f3Smrg      validate_assert(ctx, ir3_valid_immediate(instr, reg->iim_val));
777ec681f3Smrg
787ec681f3Smrg   if (!(reg->flags & IR3_REG_SSA) || !reg->def)
797ec681f3Smrg      return;
807ec681f3Smrg
817ec681f3Smrg   struct ir3_register *src = reg->def;
827ec681f3Smrg
837ec681f3Smrg   validate_assert(ctx, _mesa_set_search(ctx->defs, src->instr));
847ec681f3Smrg   validate_assert(ctx, src->wrmask == reg->wrmask);
857ec681f3Smrg   validate_assert(ctx, reg_class_flags(src) == reg_class_flags(reg));
867ec681f3Smrg
877ec681f3Smrg   if (reg->tied) {
887ec681f3Smrg      validate_assert(ctx, reg->tied->tied == reg);
897ec681f3Smrg      bool found = false;
907ec681f3Smrg      foreach_dst (dst, instr) {
917ec681f3Smrg         if (dst == reg->tied) {
927ec681f3Smrg            found = true;
937ec681f3Smrg            break;
947ec681f3Smrg         }
957ec681f3Smrg      }
967ec681f3Smrg      validate_assert(ctx,
977ec681f3Smrg                      found && "tied register not in the same instruction");
987ec681f3Smrg   }
997ec681f3Smrg}
1007ec681f3Smrg
1017ec681f3Smrg/* phi sources are logically read at the end of the predecessor basic block,
1027ec681f3Smrg * and we have to validate them then in order to correctly validate that the
1037ec681f3Smrg * use comes after the definition for loop phis.
1047ec681f3Smrg */
1057ec681f3Smrgstatic void
1067ec681f3Smrgvalidate_phi_src(struct ir3_validate_ctx *ctx, struct ir3_block *block,
1077ec681f3Smrg                 struct ir3_block *pred)
1087ec681f3Smrg{
1097ec681f3Smrg   unsigned pred_idx = ir3_block_get_pred_index(block, pred);
1107ec681f3Smrg
1117ec681f3Smrg   foreach_instr (phi, &block->instr_list) {
1127ec681f3Smrg      if (phi->opc != OPC_META_PHI)
1137ec681f3Smrg         break;
1147ec681f3Smrg
1157ec681f3Smrg      ctx->current_instr = phi;
1167ec681f3Smrg      validate_assert(ctx, phi->srcs_count == block->predecessors_count);
1177ec681f3Smrg      validate_src(ctx, phi, phi->srcs[pred_idx]);
1187ec681f3Smrg   }
1197ec681f3Smrg}
1207ec681f3Smrg
1217ec681f3Smrgstatic void
1227ec681f3Smrgvalidate_phi(struct ir3_validate_ctx *ctx, struct ir3_instruction *phi)
1237ec681f3Smrg{
1247ec681f3Smrg   _mesa_set_add(ctx->defs, phi);
1257ec681f3Smrg   validate_assert(ctx, phi->dsts_count == 1);
1267ec681f3Smrg   validate_assert(ctx, is_dest_gpr(phi->dsts[0]));
1277ec681f3Smrg}
1287ec681f3Smrg
1297ec681f3Smrgstatic void
1307ec681f3Smrgvalidate_dst(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
1317ec681f3Smrg             struct ir3_register *reg)
1327ec681f3Smrg{
1337ec681f3Smrg   if (reg->tied) {
1347ec681f3Smrg      validate_assert(ctx, reg->tied->tied == reg);
1357ec681f3Smrg      validate_assert(ctx, reg_class_flags(reg->tied) == reg_class_flags(reg));
1367ec681f3Smrg      validate_assert(ctx, reg->tied->wrmask == reg->wrmask);
1377ec681f3Smrg      if (reg->flags & IR3_REG_ARRAY) {
1387ec681f3Smrg         validate_assert(ctx, reg->tied->array.base == reg->array.base);
1397ec681f3Smrg         validate_assert(ctx, reg->tied->size == reg->size);
1407ec681f3Smrg      }
1417ec681f3Smrg      bool found = false;
1427ec681f3Smrg      foreach_src (src, instr) {
1437ec681f3Smrg         if (src == reg->tied) {
1447ec681f3Smrg            found = true;
1457ec681f3Smrg            break;
1467ec681f3Smrg         }
1477ec681f3Smrg      }
1487ec681f3Smrg      validate_assert(ctx,
1497ec681f3Smrg                      found && "tied register not in the same instruction");
1507ec681f3Smrg   }
1517ec681f3Smrg
1527ec681f3Smrg   if (reg->flags & IR3_REG_SSA)
1537ec681f3Smrg      validate_assert(ctx, reg->instr == instr);
1547ec681f3Smrg
1557ec681f3Smrg   if (reg->flags & IR3_REG_RELATIV)
1567ec681f3Smrg      validate_assert(ctx, instr->address);
1577ec681f3Smrg}
1587ec681f3Smrg
1597ec681f3Smrg#define validate_reg_size(ctx, reg, type)                                      \
1607ec681f3Smrg   validate_assert(                                                            \
1617ec681f3Smrg      ctx, type_size(type) == (((reg)->flags & IR3_REG_HALF) ? 16 : 32))
1627ec681f3Smrg
1637ec681f3Smrgstatic void
1647ec681f3Smrgvalidate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr)
1657ec681f3Smrg{
1667ec681f3Smrg   struct ir3_register *last_reg = NULL;
1677ec681f3Smrg
1687ec681f3Smrg   foreach_src_n (reg, n, instr) {
1697ec681f3Smrg      if (reg->flags & IR3_REG_RELATIV)
1707ec681f3Smrg         validate_assert(ctx, instr->address);
1717ec681f3Smrg
1727ec681f3Smrg      validate_src(ctx, instr, reg);
1737ec681f3Smrg
1747ec681f3Smrg      /* Validate that all src's are either half of full.
1757ec681f3Smrg       *
1767ec681f3Smrg       * Note: tex instructions w/ .s2en are a bit special in that the
1777ec681f3Smrg       * tex/samp src reg is half-reg for non-bindless and full for
1787ec681f3Smrg       * bindless, irrespective of the precision of other srcs. The
1797ec681f3Smrg       * tex/samp src is the first src reg when .s2en is set
1807ec681f3Smrg       */
1817ec681f3Smrg      if (reg->tied) {
1827ec681f3Smrg         /* must have the same size as the destination, handled in
1837ec681f3Smrg          * validate_reg().
1847ec681f3Smrg          */
1857ec681f3Smrg      } else if (reg == instr->address) {
1867ec681f3Smrg         validate_assert(ctx, reg->flags & IR3_REG_HALF);
1877ec681f3Smrg      } else if ((instr->flags & IR3_INSTR_S2EN) && (n < 2)) {
1887ec681f3Smrg         if (n == 0) {
1897ec681f3Smrg            if (instr->flags & IR3_INSTR_B)
1907ec681f3Smrg               validate_assert(ctx, !(reg->flags & IR3_REG_HALF));
1917ec681f3Smrg            else
1927ec681f3Smrg               validate_assert(ctx, reg->flags & IR3_REG_HALF);
1937ec681f3Smrg         }
1947ec681f3Smrg      } else if (opc_cat(instr->opc) == 1 || opc_cat(instr->opc) == 6) {
1957ec681f3Smrg         /* handled below */
1967ec681f3Smrg      } else if (opc_cat(instr->opc) == 0) {
1977ec681f3Smrg         /* end/chmask/etc are allowed to have different size sources */
1987ec681f3Smrg      } else if (instr->opc == OPC_META_PARALLEL_COPY) {
1997ec681f3Smrg         /* pcopy sources have to match with their destination but can have
2007ec681f3Smrg          * different sizes from each other.
2017ec681f3Smrg          */
2027ec681f3Smrg      } else if (n > 0) {
2037ec681f3Smrg         validate_assert(ctx, (last_reg->flags & IR3_REG_HALF) ==
2047ec681f3Smrg                                 (reg->flags & IR3_REG_HALF));
2057ec681f3Smrg      }
2067ec681f3Smrg
2077ec681f3Smrg      last_reg = reg;
2087ec681f3Smrg   }
2097ec681f3Smrg
2107ec681f3Smrg   for (unsigned i = 0; i < instr->dsts_count; i++) {
2117ec681f3Smrg      struct ir3_register *reg = instr->dsts[i];
2127ec681f3Smrg
2137ec681f3Smrg      validate_dst(ctx, instr, reg);
2147ec681f3Smrg   }
2157ec681f3Smrg
2167ec681f3Smrg   _mesa_set_add(ctx->defs, instr);
2177ec681f3Smrg
2187ec681f3Smrg   /* Check that src/dst types match the register types, and for
2197ec681f3Smrg    * instructions that have different opcodes depending on type,
2207ec681f3Smrg    * that the opcodes are correct.
2217ec681f3Smrg    */
2227ec681f3Smrg   switch (opc_cat(instr->opc)) {
2237ec681f3Smrg   case 1: /* move instructions */
2247ec681f3Smrg      if (instr->opc == OPC_MOVMSK || instr->opc == OPC_BALLOT_MACRO) {
2257ec681f3Smrg         validate_assert(ctx, instr->dsts_count == 1);
2267ec681f3Smrg         validate_assert(ctx, instr->dsts[0]->flags & IR3_REG_SHARED);
2277ec681f3Smrg         validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
2287ec681f3Smrg         validate_assert(
2297ec681f3Smrg            ctx, util_is_power_of_two_or_zero(instr->dsts[0]->wrmask + 1));
2307ec681f3Smrg      } else if (instr->opc == OPC_ANY_MACRO || instr->opc == OPC_ALL_MACRO ||
2317ec681f3Smrg                 instr->opc == OPC_READ_FIRST_MACRO ||
2327ec681f3Smrg                 instr->opc == OPC_READ_COND_MACRO) {
2337ec681f3Smrg         /* nothing yet */
2347ec681f3Smrg      } else if (instr->opc == OPC_ELECT_MACRO) {
2357ec681f3Smrg         validate_assert(ctx, instr->dsts_count == 1);
2367ec681f3Smrg         validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_SHARED));
2377ec681f3Smrg      } else {
2387ec681f3Smrg         foreach_dst (dst, instr)
2397ec681f3Smrg            validate_reg_size(ctx, dst, instr->cat1.dst_type);
2407ec681f3Smrg         foreach_src (src, instr) {
2417ec681f3Smrg            if (!src->tied && src != instr->address)
2427ec681f3Smrg               validate_reg_size(ctx, src, instr->cat1.src_type);
2437ec681f3Smrg         }
2447ec681f3Smrg
2457ec681f3Smrg         switch (instr->opc) {
2467ec681f3Smrg         case OPC_SWZ:
2477ec681f3Smrg            validate_assert(ctx, instr->srcs_count == 2);
2487ec681f3Smrg            validate_assert(ctx, instr->dsts_count == 2);
2497ec681f3Smrg            break;
2507ec681f3Smrg         case OPC_GAT:
2517ec681f3Smrg            validate_assert(ctx, instr->srcs_count == 4);
2527ec681f3Smrg            validate_assert(ctx, instr->dsts_count == 1);
2537ec681f3Smrg            break;
2547ec681f3Smrg         case OPC_SCT:
2557ec681f3Smrg            validate_assert(ctx, instr->srcs_count == 1);
2567ec681f3Smrg            validate_assert(ctx, instr->dsts_count == 4);
2577ec681f3Smrg            break;
2587ec681f3Smrg         default:
2597ec681f3Smrg            break;
2607ec681f3Smrg         }
2617ec681f3Smrg      }
2627ec681f3Smrg
2637ec681f3Smrg      if (instr->opc != OPC_MOV)
2647ec681f3Smrg         validate_assert(ctx, !instr->address);
2657ec681f3Smrg
2667ec681f3Smrg      break;
2677ec681f3Smrg   case 3:
2687ec681f3Smrg      /* Validate that cat3 opc matches the src type.  We've already checked
2697ec681f3Smrg       * that all the src regs are same type
2707ec681f3Smrg       */
2717ec681f3Smrg      if (instr->srcs[0]->flags & IR3_REG_HALF) {
2727ec681f3Smrg         validate_assert(ctx, instr->opc == cat3_half_opc(instr->opc));
2737ec681f3Smrg      } else {
2747ec681f3Smrg         validate_assert(ctx, instr->opc == cat3_full_opc(instr->opc));
2757ec681f3Smrg      }
2767ec681f3Smrg      break;
2777ec681f3Smrg   case 4:
2787ec681f3Smrg      /* Validate that cat4 opc matches the dst type: */
2797ec681f3Smrg      if (instr->dsts[0]->flags & IR3_REG_HALF) {
2807ec681f3Smrg         validate_assert(ctx, instr->opc == cat4_half_opc(instr->opc));
2817ec681f3Smrg      } else {
2827ec681f3Smrg         validate_assert(ctx, instr->opc == cat4_full_opc(instr->opc));
2837ec681f3Smrg      }
2847ec681f3Smrg      break;
2857ec681f3Smrg   case 5:
2867ec681f3Smrg      validate_reg_size(ctx, instr->dsts[0], instr->cat5.type);
2877ec681f3Smrg      break;
2887ec681f3Smrg   case 6:
2897ec681f3Smrg      switch (instr->opc) {
2907ec681f3Smrg      case OPC_RESINFO:
2917ec681f3Smrg      case OPC_RESFMT:
2927ec681f3Smrg         validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
2937ec681f3Smrg         validate_reg_size(ctx, instr->srcs[0], instr->cat6.type);
2947ec681f3Smrg         break;
2957ec681f3Smrg      case OPC_L2G:
2967ec681f3Smrg      case OPC_G2L:
2977ec681f3Smrg         validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF));
2987ec681f3Smrg         validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
2997ec681f3Smrg         break;
3007ec681f3Smrg      case OPC_STG:
3017ec681f3Smrg         validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
3027ec681f3Smrg         validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
3037ec681f3Smrg         validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
3047ec681f3Smrg         validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
3057ec681f3Smrg         break;
3067ec681f3Smrg      case OPC_STG_A:
3077ec681f3Smrg         validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
3087ec681f3Smrg         validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
3097ec681f3Smrg         validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF));
3107ec681f3Smrg         validate_reg_size(ctx, instr->srcs[4], instr->cat6.type);
3117ec681f3Smrg         validate_assert(ctx, !(instr->srcs[5]->flags & IR3_REG_HALF));
3127ec681f3Smrg         break;
3137ec681f3Smrg      case OPC_STL:
3147ec681f3Smrg      case OPC_STP:
3157ec681f3Smrg      case OPC_STLW:
3167ec681f3Smrg      case OPC_SPILL_MACRO:
3177ec681f3Smrg         validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
3187ec681f3Smrg         validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
3197ec681f3Smrg         validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
3207ec681f3Smrg         break;
3217ec681f3Smrg      case OPC_STIB:
3227ec681f3Smrg         if (instr->flags & IR3_INSTR_B) {
3237ec681f3Smrg            validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
3247ec681f3Smrg            validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
3257ec681f3Smrg            validate_reg_size(ctx, instr->srcs[2], instr->cat6.type);
3267ec681f3Smrg         } else {
3277ec681f3Smrg            validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
3287ec681f3Smrg            validate_reg_size(ctx, instr->srcs[1], instr->cat6.type);
3297ec681f3Smrg            validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF));
3307ec681f3Smrg         }
3317ec681f3Smrg         break;
3327ec681f3Smrg      default:
3337ec681f3Smrg         validate_reg_size(ctx, instr->dsts[0], instr->cat6.type);
3347ec681f3Smrg         validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));
3357ec681f3Smrg         if (instr->srcs_count > 1)
3367ec681f3Smrg            validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF));
3377ec681f3Smrg         break;
3387ec681f3Smrg      }
3397ec681f3Smrg   }
3407ec681f3Smrg
3417ec681f3Smrg   if (instr->opc == OPC_META_PARALLEL_COPY) {
3427ec681f3Smrg      foreach_src_n (src, n, instr) {
3437ec681f3Smrg         validate_assert(ctx, reg_class_flags(src) ==
3447ec681f3Smrg                         reg_class_flags(instr->dsts[n]));
3457ec681f3Smrg      }
3467ec681f3Smrg   }
3477ec681f3Smrg}
3487ec681f3Smrg
3497ec681f3Smrgstatic bool
3507ec681f3Smrgis_physical_successor(struct ir3_block *block, struct ir3_block *succ)
3517ec681f3Smrg{
3527ec681f3Smrg   for (unsigned i = 0; i < ARRAY_SIZE(block->physical_successors); i++)
3537ec681f3Smrg      if (block->physical_successors[i] == succ)
3547ec681f3Smrg         return true;
3557ec681f3Smrg   return false;
3567ec681f3Smrg}
3577ec681f3Smrg
3587ec681f3Smrgvoid
3597ec681f3Smrgir3_validate(struct ir3 *ir)
3607ec681f3Smrg{
3617ec681f3Smrg#ifdef NDEBUG
3627ec681f3Smrg#define VALIDATE 0
3637ec681f3Smrg#else
3647ec681f3Smrg#define VALIDATE 1
3657ec681f3Smrg#endif
3667ec681f3Smrg
3677ec681f3Smrg   if (!VALIDATE)
3687ec681f3Smrg      return;
3697ec681f3Smrg
3707ec681f3Smrg   struct ir3_validate_ctx *ctx = ralloc_size(NULL, sizeof(*ctx));
3717ec681f3Smrg
3727ec681f3Smrg   ctx->ir = ir;
3737ec681f3Smrg   ctx->defs = _mesa_pointer_set_create(ctx);
3747ec681f3Smrg
3757ec681f3Smrg   foreach_block (block, &ir->block_list) {
3767ec681f3Smrg      ctx->current_block = block;
3777ec681f3Smrg      ctx->current_instr = NULL;
3787ec681f3Smrg
3797ec681f3Smrg      /* We require that the first block does not have any predecessors,
3807ec681f3Smrg       * which allows us to assume that phi nodes and meta:input's do not
3817ec681f3Smrg       * appear in the same basic block.
3827ec681f3Smrg       */
3837ec681f3Smrg      validate_assert(
3847ec681f3Smrg         ctx, block != ir3_start_block(ir) || block->predecessors_count == 0);
3857ec681f3Smrg
3867ec681f3Smrg      struct ir3_instruction *prev = NULL;
3877ec681f3Smrg      foreach_instr (instr, &block->instr_list) {
3887ec681f3Smrg         ctx->current_instr = instr;
3897ec681f3Smrg         if (instr->opc == OPC_META_PHI) {
3907ec681f3Smrg            /* phis must be the first in the block */
3917ec681f3Smrg            validate_assert(ctx, prev == NULL || prev->opc == OPC_META_PHI);
3927ec681f3Smrg            validate_phi(ctx, instr);
3937ec681f3Smrg         } else {
3947ec681f3Smrg            validate_instr(ctx, instr);
3957ec681f3Smrg         }
3967ec681f3Smrg         prev = instr;
3977ec681f3Smrg      }
3987ec681f3Smrg
3997ec681f3Smrg      for (unsigned i = 0; i < 2; i++) {
4007ec681f3Smrg         if (block->successors[i]) {
4017ec681f3Smrg            validate_phi_src(ctx, block->successors[i], block);
4027ec681f3Smrg
4037ec681f3Smrg            ctx->current_instr = NULL;
4047ec681f3Smrg
4057ec681f3Smrg            /* Each logical successor should also be a physical successor: */
4067ec681f3Smrg            validate_assert(ctx, is_physical_successor(block, block->successors[i]));
4077ec681f3Smrg         }
4087ec681f3Smrg      }
4097ec681f3Smrg
4107ec681f3Smrg      validate_assert(ctx, block->successors[0] || !block->successors[1]);
4117ec681f3Smrg      validate_assert(ctx, block->physical_successors[0] || !block->physical_successors[1]);
4127ec681f3Smrg   }
4137ec681f3Smrg
4147ec681f3Smrg   ralloc_free(ctx);
4157ec681f3Smrg}
416