Skip to content

Commit 2b55ef1

Browse files
authored
[VPlan] Add helper to run VPlan passes, verify after run (NFC). (#123640)
Add new runPass helpers to run a VPlan transformation. This makes it easier to add additional checks/functionality for each transform run. In this patch, an option is added to run the verifier after each VPlan transform. Follow-ups will use the same helper to also support printing VPlans after each transform. Note that the verifier at the moment requires there to be a canonical IV and vector loop region, so the final lowering transforms aren't run via runPass yet. PR: #123640
1 parent 36b3c43 commit 2b55ef1

File tree

4 files changed

+77
-34
lines changed

4 files changed

+77
-34
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,16 @@ cl::opt<bool> EnableVPlanNativePath(
355355
"enable-vplan-native-path", cl::Hidden,
356356
cl::desc("Enable VPlan-native vectorization path with "
357357
"support for outer loop vectorization."));
358+
359+
cl::opt<bool>
360+
VerifyEachVPlan("vplan-verify-each",
361+
#ifdef EXPENSIVE_CHECKS
362+
cl::init(true),
363+
#else
364+
cl::init(false),
365+
#endif
366+
cl::Hidden,
367+
cl::desc("Verfiy VPlans after VPlan transforms."));
358368
} // namespace llvm
359369

360370
// This flag enables the stress testing of the VPlan H-CFG construction in the
@@ -7651,8 +7661,8 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
76517661

76527662
// TODO: Move to VPlan transform stage once the transition to the VPlan-based
76537663
// cost model is complete for better cost estimates.
7654-
VPlanTransforms::unrollByUF(BestVPlan, BestUF,
7655-
OrigLoop->getHeader()->getContext());
7664+
VPlanTransforms::runPass(VPlanTransforms::unrollByUF, BestVPlan, BestUF,
7665+
OrigLoop->getHeader()->getContext());
76567666
VPlanTransforms::optimizeForVFAndUF(BestVPlan, BestVF, BestUF, PSE);
76577667
VPlanTransforms::convertToConcreteRecipes(BestVPlan);
76587668

@@ -8908,13 +8918,14 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
89088918
if (auto Plan = tryToBuildVPlanWithVPRecipes(SubRange)) {
89098919
// Now optimize the initial VPlan.
89108920
if (!Plan->hasVF(ElementCount::getFixed(1)))
8911-
VPlanTransforms::truncateToMinimalBitwidths(*Plan,
8912-
CM.getMinimalBitwidths());
8921+
VPlanTransforms::runPass(VPlanTransforms::truncateToMinimalBitwidths,
8922+
*Plan, CM.getMinimalBitwidths());
89138923
VPlanTransforms::optimize(*Plan);
89148924
// TODO: try to put it close to addActiveLaneMask().
89158925
// Discard the plan if it is not EVL-compatible
8916-
if (CM.foldTailWithEVL() && !VPlanTransforms::tryAddExplicitVectorLength(
8917-
*Plan, CM.getMaxSafeElements()))
8926+
if (CM.foldTailWithEVL() &&
8927+
!VPlanTransforms::runPass(VPlanTransforms::tryAddExplicitVectorLength,
8928+
*Plan, CM.getMaxSafeElements()))
89188929
break;
89198930
assert(verifyVPlanIsValid(*Plan) && "VPlan is invalid");
89208931
VPlans.push_back(std::move(Plan));
@@ -9423,8 +9434,9 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
94239434
// Interleave memory: for each Interleave Group we marked earlier as relevant
94249435
// for this VPlan, replace the Recipes widening its memory instructions with a
94259436
// single VPInterleaveRecipe at its insertion point.
9426-
VPlanTransforms::createInterleaveGroups(
9427-
*Plan, InterleaveGroups, RecipeBuilder, CM.isScalarEpilogueAllowed());
9437+
VPlanTransforms::runPass(VPlanTransforms::createInterleaveGroups, *Plan,
9438+
InterleaveGroups, RecipeBuilder,
9439+
CM.isScalarEpilogueAllowed());
94289440

94299441
for (ElementCount VF : Range)
94309442
Plan->addVF(VF);
@@ -9466,13 +9478,16 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
94669478
}
94679479
}
94689480

9469-
VPlanTransforms::dropPoisonGeneratingRecipes(*Plan, [this](BasicBlock *BB) {
9481+
auto BlockNeedsPredication = [this](BasicBlock *BB) {
94709482
return Legal->blockNeedsPredication(BB);
9471-
});
9483+
};
9484+
VPlanTransforms::runPass(VPlanTransforms::dropPoisonGeneratingRecipes, *Plan,
9485+
BlockNeedsPredication);
94729486

94739487
// Sink users of fixed-order recurrence past the recipe defining the previous
94749488
// value and introduce FirstOrderRecurrenceSplice VPInstructions.
9475-
if (!VPlanTransforms::adjustFixedOrderRecurrences(*Plan, Builder))
9489+
if (!VPlanTransforms::runPass(VPlanTransforms::adjustFixedOrderRecurrences,
9490+
*Plan, Builder))
94769491
return nullptr;
94779492

94789493
if (useActiveLaneMask(Style)) {
@@ -9815,10 +9830,10 @@ void LoopVectorizationPlanner::adjustRecipesForReductions(
98159830
PhiR->setOperand(0, Plan->getOrAddLiveIn(RdxDesc.getSentinelValue()));
98169831
}
98179832
}
9818-
9819-
VPlanTransforms::clearReductionWrapFlags(*Plan);
98209833
for (VPRecipeBase *R : ToDelete)
98219834
R->eraseFromParent();
9835+
9836+
VPlanTransforms::runPass(VPlanTransforms::clearReductionWrapFlags, *Plan);
98229837
}
98239838

98249839
void VPDerivedIVRecipe::execute(VPTransformState &State) {
@@ -10182,7 +10197,7 @@ static void preparePlanForMainVectorLoop(VPlan &MainPlan, VPlan &EpiPlan) {
1018210197
VPIRInst->eraseFromParent();
1018310198
ResumePhi->eraseFromParent();
1018410199
}
10185-
VPlanTransforms::removeDeadRecipes(MainPlan);
10200+
VPlanTransforms::runPass(VPlanTransforms::removeDeadRecipes, MainPlan);
1018610201

1018710202
using namespace VPlanPatternMatch;
1018810203
VPBasicBlock *MainScalarPH = MainPlan.getScalarPreheader();

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ using namespace llvm::VPlanPatternMatch;
5252
namespace llvm {
5353
extern cl::opt<bool> EnableVPlanNativePath;
5454
}
55+
5556
extern cl::opt<unsigned> ForceTargetInstructionCost;
5657

5758
static cl::opt<bool> PrintVPlansInDotFormat(

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "VPlanDominatorTree.h"
2020
#include "VPlanPatternMatch.h"
2121
#include "VPlanUtils.h"
22+
#include "VPlanVerifier.h"
2223
#include "llvm/ADT/PostOrderIterator.h"
2324
#include "llvm/ADT/STLExtras.h"
2425
#include "llvm/ADT/SetVector.h"
@@ -964,10 +965,10 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
964965

965966
/// Try to simplify the recipes in \p Plan. Use \p CanonicalIVTy as type for all
966967
/// un-typed live-ins in VPTypeAnalysis.
967-
static void simplifyRecipes(VPlan &Plan, Type *CanonicalIVTy) {
968+
static void simplifyRecipes(VPlan &Plan, Type &CanonicalIVTy) {
968969
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
969970
Plan.getEntry());
970-
VPTypeAnalysis TypeInfo(CanonicalIVTy);
971+
VPTypeAnalysis TypeInfo(&CanonicalIVTy);
971972
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
972973
for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
973974
simplifyRecipe(R, TypeInfo);
@@ -1029,7 +1030,7 @@ void VPlanTransforms::optimizeForVFAndUF(VPlan &Plan, ElementCount BestVF,
10291030

10301031
VPBlockUtils::connectBlocks(Preheader, Header);
10311032
VPBlockUtils::connectBlocks(ExitingVPBB, Exit);
1032-
simplifyRecipes(Plan, CanIVTy);
1033+
simplifyRecipes(Plan, *CanIVTy);
10331034
} else {
10341035
// The vector region contains header phis for which we cannot remove the
10351036
// loop region yet.
@@ -1439,19 +1440,19 @@ void VPlanTransforms::truncateToMinimalBitwidths(
14391440
}
14401441

14411442
void VPlanTransforms::optimize(VPlan &Plan) {
1442-
removeRedundantCanonicalIVs(Plan);
1443-
removeRedundantInductionCasts(Plan);
1444-
1445-
simplifyRecipes(Plan, Plan.getCanonicalIV()->getScalarType());
1446-
removeDeadRecipes(Plan);
1447-
legalizeAndOptimizeInductions(Plan);
1448-
removeRedundantExpandSCEVRecipes(Plan);
1449-
simplifyRecipes(Plan, Plan.getCanonicalIV()->getScalarType());
1450-
removeDeadRecipes(Plan);
1451-
1452-
createAndOptimizeReplicateRegions(Plan);
1453-
mergeBlocksIntoPredecessors(Plan);
1454-
licm(Plan);
1443+
runPass(removeRedundantCanonicalIVs, Plan);
1444+
runPass(removeRedundantInductionCasts, Plan);
1445+
1446+
runPass(simplifyRecipes, Plan, *Plan.getCanonicalIV()->getScalarType());
1447+
runPass(removeDeadRecipes, Plan);
1448+
runPass(legalizeAndOptimizeInductions, Plan);
1449+
runPass(removeRedundantExpandSCEVRecipes, Plan);
1450+
runPass(simplifyRecipes, Plan, *Plan.getCanonicalIV()->getScalarType());
1451+
runPass(removeDeadRecipes, Plan);
1452+
1453+
runPass(createAndOptimizeReplicateRegions, Plan);
1454+
runPass(mergeBlocksIntoPredecessors, Plan);
1455+
runPass(licm, Plan);
14551456
}
14561457

14571458
// Add a VPActiveLaneMaskPHIRecipe and related recipes to \p Plan and replace
@@ -1871,7 +1872,8 @@ bool VPlanTransforms::tryAddExplicitVectorLength(
18711872
}
18721873

18731874
void VPlanTransforms::dropPoisonGeneratingRecipes(
1874-
VPlan &Plan, function_ref<bool(BasicBlock *)> BlockNeedsPredication) {
1875+
VPlan &Plan,
1876+
const std::function<bool(BasicBlock *)> &BlockNeedsPredication) {
18751877
// Collect recipes in the backward slice of `Root` that may generate a poison
18761878
// value that is used after vectorization.
18771879
SmallPtrSet<VPRecipeBase *, 16> Visited;
@@ -1971,7 +1973,7 @@ void VPlanTransforms::createInterleaveGroups(
19711973
VPlan &Plan,
19721974
const SmallPtrSetImpl<const InterleaveGroup<Instruction> *>
19731975
&InterleaveGroups,
1974-
VPRecipeBuilder &RecipeBuilder, bool ScalarEpilogueAllowed) {
1976+
VPRecipeBuilder &RecipeBuilder, const bool &ScalarEpilogueAllowed) {
19751977
if (InterleaveGroups.empty())
19761978
return;
19771979

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#define LLVM_TRANSFORMS_VECTORIZE_VPLANTRANSFORMS_H
1515

1616
#include "VPlan.h"
17+
#include "VPlanVerifier.h"
1718
#include "llvm/ADT/STLFunctionalExtras.h"
19+
#include "llvm/Support/CommandLine.h"
1820

1921
namespace llvm {
2022

@@ -27,7 +29,29 @@ class TargetLibraryInfo;
2729
class VPBuilder;
2830
class VPRecipeBuilder;
2931

32+
extern cl::opt<bool> VerifyEachVPlan;
33+
3034
struct VPlanTransforms {
35+
/// Helper to run a VPlan transform \p Transform on \p VPlan, forwarding extra
36+
/// arguments to the transform. Returns the boolean returned by the transform.
37+
template <typename... ArgsTy>
38+
static bool runPass(bool (*Transform)(VPlan &, ArgsTy...), VPlan &Plan,
39+
typename std::remove_reference<ArgsTy>::type &...Args) {
40+
bool Res = Transform(Plan, Args...);
41+
if (VerifyEachVPlan)
42+
verifyVPlanIsValid(Plan);
43+
return Res;
44+
}
45+
/// Helper to run a VPlan transform \p Transform on \p VPlan, forwarding extra
46+
/// arguments to the transform.
47+
template <typename... ArgsTy>
48+
static void runPass(void (*Fn)(VPlan &, ArgsTy...), VPlan &Plan,
49+
typename std::remove_reference<ArgsTy>::type &...Args) {
50+
Fn(Plan, Args...);
51+
if (VerifyEachVPlan)
52+
verifyVPlanIsValid(Plan);
53+
}
54+
3155
/// Replaces the VPInstructions in \p Plan with corresponding
3256
/// widen recipes.
3357
static void
@@ -100,7 +124,8 @@ struct VPlanTransforms {
100124
/// TODO: Replace BlockNeedsPredication callback with retrieving info from
101125
/// VPlan directly.
102126
static void dropPoisonGeneratingRecipes(
103-
VPlan &Plan, function_ref<bool(BasicBlock *)> BlockNeedsPredication);
127+
VPlan &Plan,
128+
const std::function<bool(BasicBlock *)> &BlockNeedsPredication);
104129

105130
/// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and
106131
/// replaces all uses except the canonical IV increment of
@@ -119,7 +144,7 @@ struct VPlanTransforms {
119144
VPlan &Plan,
120145
const SmallPtrSetImpl<const InterleaveGroup<Instruction> *>
121146
&InterleaveGroups,
122-
VPRecipeBuilder &RecipeBuilder, bool ScalarEpilogueAllowed);
147+
VPRecipeBuilder &RecipeBuilder, const bool &ScalarEpilogueAllowed);
123148

124149
/// Remove dead recipes from \p Plan.
125150
static void removeDeadRecipes(VPlan &Plan);

0 commit comments

Comments
 (0)