VPlanVerifier.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //===-- VPlanVerifier.cpp -------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// This file defines the class VPlanVerifier, which contains utility functions
  11. /// to check the consistency and invariants of a VPlan.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #include "VPlanVerifier.h"
  15. #include "VPlan.h"
  16. #include "llvm/ADT/DepthFirstIterator.h"
  17. #include "llvm/Support/CommandLine.h"
  18. #define DEBUG_TYPE "loop-vectorize"
  19. using namespace llvm;
  20. static cl::opt<bool> EnableHCFGVerifier("vplan-verify-hcfg", cl::init(false),
  21. cl::Hidden,
  22. cl::desc("Verify VPlan H-CFG."));
  23. #ifndef NDEBUG
  24. /// Utility function that checks whether \p VPBlockVec has duplicate
  25. /// VPBlockBases.
  26. static bool hasDuplicates(const SmallVectorImpl<VPBlockBase *> &VPBlockVec) {
  27. SmallDenseSet<const VPBlockBase *, 8> VPBlockSet;
  28. for (const auto *Block : VPBlockVec) {
  29. if (VPBlockSet.count(Block))
  30. return true;
  31. VPBlockSet.insert(Block);
  32. }
  33. return false;
  34. }
  35. #endif
  36. /// Helper function that verifies the CFG invariants of the VPBlockBases within
  37. /// \p Region. Checks in this function are generic for VPBlockBases. They are
  38. /// not specific for VPBasicBlocks or VPRegionBlocks.
  39. static void verifyBlocksInRegion(const VPRegionBlock *Region) {
  40. for (const VPBlockBase *VPB :
  41. make_range(df_iterator<const VPBlockBase *>::begin(Region->getEntry()),
  42. df_iterator<const VPBlockBase *>::end(Region->getExit()))) {
  43. // Check block's parent.
  44. assert(VPB->getParent() == Region && "VPBlockBase has wrong parent");
  45. // Check block's condition bit.
  46. if (VPB->getNumSuccessors() > 1)
  47. assert(VPB->getCondBit() && "Missing condition bit!");
  48. else
  49. assert(!VPB->getCondBit() && "Unexpected condition bit!");
  50. // Check block's successors.
  51. const auto &Successors = VPB->getSuccessors();
  52. // There must be only one instance of a successor in block's successor list.
  53. // TODO: This won't work for switch statements.
  54. assert(!hasDuplicates(Successors) &&
  55. "Multiple instances of the same successor.");
  56. for (const VPBlockBase *Succ : Successors) {
  57. // There must be a bi-directional link between block and successor.
  58. const auto &SuccPreds = Succ->getPredecessors();
  59. assert(llvm::is_contained(SuccPreds, VPB) && "Missing predecessor link.");
  60. (void)SuccPreds;
  61. }
  62. // Check block's predecessors.
  63. const auto &Predecessors = VPB->getPredecessors();
  64. // There must be only one instance of a predecessor in block's predecessor
  65. // list.
  66. // TODO: This won't work for switch statements.
  67. assert(!hasDuplicates(Predecessors) &&
  68. "Multiple instances of the same predecessor.");
  69. for (const VPBlockBase *Pred : Predecessors) {
  70. // Block and predecessor must be inside the same region.
  71. assert(Pred->getParent() == VPB->getParent() &&
  72. "Predecessor is not in the same region.");
  73. // There must be a bi-directional link between block and predecessor.
  74. const auto &PredSuccs = Pred->getSuccessors();
  75. assert(llvm::is_contained(PredSuccs, VPB) && "Missing successor link.");
  76. (void)PredSuccs;
  77. }
  78. }
  79. }
  80. /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
  81. /// VPBlockBases. Do not recurse inside nested VPRegionBlocks.
  82. static void verifyRegion(const VPRegionBlock *Region) {
  83. const VPBlockBase *Entry = Region->getEntry();
  84. const VPBlockBase *Exit = Region->getExit();
  85. // Entry and Exit shouldn't have any predecessor/successor, respectively.
  86. assert(!Entry->getNumPredecessors() && "Region entry has predecessors.");
  87. assert(!Exit->getNumSuccessors() && "Region exit has successors.");
  88. (void)Entry;
  89. (void)Exit;
  90. verifyBlocksInRegion(Region);
  91. }
  92. /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
  93. /// VPBlockBases. Recurse inside nested VPRegionBlocks.
  94. static void verifyRegionRec(const VPRegionBlock *Region) {
  95. verifyRegion(Region);
  96. // Recurse inside nested regions.
  97. for (const VPBlockBase *VPB :
  98. make_range(df_iterator<const VPBlockBase *>::begin(Region->getEntry()),
  99. df_iterator<const VPBlockBase *>::end(Region->getExit()))) {
  100. if (const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB))
  101. verifyRegionRec(SubRegion);
  102. }
  103. }
  104. void VPlanVerifier::verifyHierarchicalCFG(
  105. const VPRegionBlock *TopRegion) const {
  106. if (!EnableHCFGVerifier)
  107. return;
  108. LLVM_DEBUG(dbgs() << "Verifying VPlan H-CFG.\n");
  109. assert(!TopRegion->getParent() && "VPlan Top Region should have no parent.");
  110. verifyRegionRec(TopRegion);
  111. }
  112. bool VPlanVerifier::verifyPlanIsValid(const VPlan &Plan) {
  113. auto Iter = depth_first(
  114. VPBlockRecursiveTraversalWrapper<const VPBlockBase *>(Plan.getEntry()));
  115. for (const VPBasicBlock *VPBB :
  116. VPBlockUtils::blocksOnly<const VPBasicBlock>(Iter)) {
  117. // Verify that phi-like recipes are at the beginning of the block, with no
  118. // other recipes in between.
  119. auto RecipeI = VPBB->begin();
  120. auto End = VPBB->end();
  121. while (RecipeI != End && RecipeI->isPhi())
  122. RecipeI++;
  123. while (RecipeI != End) {
  124. if (RecipeI->isPhi() && !isa<VPBlendRecipe>(&*RecipeI)) {
  125. errs() << "Found phi-like recipe after non-phi recipe";
  126. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  127. errs() << ": ";
  128. RecipeI->dump();
  129. errs() << "after\n";
  130. std::prev(RecipeI)->dump();
  131. #endif
  132. return false;
  133. }
  134. RecipeI++;
  135. }
  136. }
  137. const VPRegionBlock *TopRegion = cast<VPRegionBlock>(Plan.getEntry());
  138. const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
  139. if (!Entry) {
  140. errs() << "VPlan entry block is not a VPBasicBlock\n";
  141. return false;
  142. }
  143. if (!isa<VPCanonicalIVPHIRecipe>(&*Entry->begin())) {
  144. errs() << "VPlan vector loop header does not start with a "
  145. "VPCanonicalIVPHIRecipe\n";
  146. return false;
  147. }
  148. const VPBasicBlock *Exit = dyn_cast<VPBasicBlock>(TopRegion->getExit());
  149. if (!Exit) {
  150. errs() << "VPlan exit block is not a VPBasicBlock\n";
  151. return false;
  152. }
  153. if (Exit->empty()) {
  154. errs() << "VPlan vector loop exit must end with BranchOnCount "
  155. "VPInstruction but is empty\n";
  156. return false;
  157. }
  158. auto *LastInst = dyn_cast<VPInstruction>(std::prev(Exit->end()));
  159. if (!LastInst || LastInst->getOpcode() != VPInstruction::BranchOnCount) {
  160. errs() << "VPlan vector loop exit must end with BranchOnCount "
  161. "VPInstruction\n";
  162. return false;
  163. }
  164. for (const VPRegionBlock *Region :
  165. VPBlockUtils::blocksOnly<const VPRegionBlock>(
  166. depth_first(VPBlockRecursiveTraversalWrapper<const VPBlockBase *>(
  167. Plan.getEntry())))) {
  168. if (Region->getEntry()->getNumPredecessors() != 0) {
  169. errs() << "region entry block has predecessors\n";
  170. return false;
  171. }
  172. if (Region->getExit()->getNumSuccessors() != 0) {
  173. errs() << "region exit block has successors\n";
  174. return false;
  175. }
  176. }
  177. return true;
  178. }