diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp --- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp @@ -133,7 +133,9 @@ verifyRegionRec(TopRegion); } -static bool verifyVPBasicBlock(const VPBasicBlock *VPBB) { +static bool +verifyVPBasicBlock(const VPBasicBlock *VPBB, + DenseMap &BlockNumbering) { // Verify that phi-like recipes are at the beginning of the block, with no // other recipes in between. auto RecipeI = VPBB->begin(); @@ -165,15 +167,73 @@ RecipeI++; } + // Verify that defs in VPBB dominate all their uses. The current + // implementation is still incomplete. + DenseMap RecipeNumbering; + unsigned Cnt = 0; + for (const VPRecipeBase &R : *VPBB) + RecipeNumbering[&R] = Cnt++; + + for (const VPRecipeBase &R : *VPBB) { + for (const VPValue *V : R.definedValues()) { + for (const VPUser *U : V->users()) { + auto *UI = dyn_cast(U); + if (!UI || isa(UI)) + continue; + + // If the user is in the same block, check it comes after R in the + // block. + if (UI->getParent() == VPBB) { + if (RecipeNumbering[UI] < RecipeNumbering[&R]) { + errs() << "Use before def!\n"; + return false; + } + continue; + } + + // Skip blocks outside any region for now + auto *ParentR = VPBB->getParent(); + if (!ParentR) + continue; + + // For replicators, verify that VPPRedInstPHIRecipe defs are only used + // in subsequent blocks. + if (ParentR->isReplicator()) { + if (isa(&R)) { + if (BlockNumbering[UI->getParent()] < BlockNumbering[ParentR]) { + errs() << "Use before def!\n"; + return false; + } + continue; + } + + // All non-VPPredInstPHIRecipe recipes in the block must be used in + // the replicate region only. + if (UI->getParent()->getParent() != ParentR) { + errs() << "Use before def!\n"; + return false; + } + } + } + } + } return true; } bool VPlanVerifier::verifyPlanIsValid(const VPlan &Plan) { + DenseMap BlockNumbering; + unsigned Cnt = 0; + auto Iter1 = depth_first( + VPBlockRecursiveTraversalWrapper(Plan.getEntry())); + + for (const VPBlockBase *VPB : Iter1) + BlockNumbering[VPB] = Cnt++; + auto Iter = depth_first( VPBlockRecursiveTraversalWrapper(Plan.getEntry())); for (const VPBasicBlock *VPBB : VPBlockUtils::blocksOnly(Iter)) { - if (!verifyVPBasicBlock(VPBB)) + if (!verifyVPBasicBlock(VPBB, BlockNumbering)) return false; }