Skip to content

Commit 0d736e2

Browse files
authored
[VPlan] Add getSCEVExprForVPValue util, use to get trip count SCEV (NFC) (#94464)
Add a new getSCEVExprForVPValue utility which can be used to get a SCEV expression for a VPValue. The initial implementation only returns SCEVs for live-in IR values (by constructing a SCEV based on the live-in IR value) and VPExpandSCEVRecipe. This is enough to serve its first use, getting a SCEV for a VPlan's trip count, but will be extended in the future. It also removes createTripCountSCEV, as the new helper can be used to retrieve the SCEV from the VPlan. PR: #94464
1 parent ce74d5f commit 0d736e2

File tree

9 files changed

+62
-38
lines changed

9 files changed

+62
-38
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -905,15 +905,6 @@ Value *getRuntimeVF(IRBuilderBase &B, Type *Ty, ElementCount VF) {
905905
return B.CreateElementCount(Ty, VF);
906906
}
907907

908-
const SCEV *createTripCountSCEV(Type *IdxTy, PredicatedScalarEvolution &PSE,
909-
Loop *OrigLoop) {
910-
const SCEV *BackedgeTakenCount = PSE.getBackedgeTakenCount();
911-
assert(!isa<SCEVCouldNotCompute>(BackedgeTakenCount) && "Invalid loop count");
912-
913-
ScalarEvolution &SE = *PSE.getSE();
914-
return SE.getTripCountFromExitCount(BackedgeTakenCount, IdxTy, OrigLoop);
915-
}
916-
917908
void reportVectorizationFailure(const StringRef DebugMsg,
918909
const StringRef OREMsg, const StringRef ORETag,
919910
OptimizationRemarkEmitter *ORE, Loop *TheLoop,
@@ -4750,7 +4741,10 @@ VectorizationFactor LoopVectorizationPlanner::selectEpilogueVectorizationFactor(
47504741
if (!MainLoopVF.isScalable() && !NextVF.Width.isScalable()) {
47514742
// TODO: extend to support scalable VFs.
47524743
if (!RemainingIterations) {
4753-
const SCEV *TC = createTripCountSCEV(TCType, PSE, OrigLoop);
4744+
const SCEV *TC = vputils::getSCEVExprForVPValue(
4745+
getPlanFor(NextVF.Width).getTripCount(), SE);
4746+
assert(!isa<SCEVCouldNotCompute>(TC) &&
4747+
"Trip count SCEV must be computable");
47544748
RemainingIterations = SE.getURemExpr(
47554749
TC, SE.getConstant(TCType, MainLoopVF.getKnownMinValue() * IC));
47564750
}
@@ -8863,10 +8857,9 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
88638857
return !CM.requiresScalarEpilogue(VF.isVector());
88648858
},
88658859
Range);
8866-
VPlanPtr Plan = VPlan::createInitialVPlan(
8867-
createTripCountSCEV(Legal->getWidestInductionType(), PSE, OrigLoop),
8868-
*PSE.getSE(), RequiresScalarEpilogueCheck, CM.foldTailByMasking(),
8869-
OrigLoop);
8860+
VPlanPtr Plan = VPlan::createInitialVPlan(Legal->getWidestInductionType(),
8861+
PSE, RequiresScalarEpilogueCheck,
8862+
CM.foldTailByMasking(), OrigLoop);
88708863

88718864
// Don't use getDecisionAndClampRange here, because we don't know the UF
88728865
// so this function is better to be conservative, rather than to split
@@ -9081,9 +9074,8 @@ VPlanPtr LoopVectorizationPlanner::buildVPlan(VFRange &Range) {
90819074
assert(EnableVPlanNativePath && "VPlan-native path is not enabled.");
90829075

90839076
// Create new empty VPlan
9084-
auto Plan = VPlan::createInitialVPlan(
9085-
createTripCountSCEV(Legal->getWidestInductionType(), PSE, OrigLoop),
9086-
*PSE.getSE(), true, false, OrigLoop);
9077+
auto Plan = VPlan::createInitialVPlan(Legal->getWidestInductionType(), PSE,
9078+
true, false, OrigLoop);
90879079

90889080
// Build hierarchical CFG
90899081
VPlanHCFGBuilder HCFGBuilder(OrigLoop, LI, *Plan);

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,14 +869,23 @@ static VPIRBasicBlock *createVPIRBasicBlockFor(BasicBlock *BB) {
869869
return VPIRBB;
870870
}
871871

872-
VPlanPtr VPlan::createInitialVPlan(const SCEV *TripCount, ScalarEvolution &SE,
872+
VPlanPtr VPlan::createInitialVPlan(Type *InductionTy,
873+
PredicatedScalarEvolution &PSE,
873874
bool RequiresScalarEpilogueCheck,
874875
bool TailFolded, Loop *TheLoop) {
875876
VPIRBasicBlock *Entry = createVPIRBasicBlockFor(TheLoop->getLoopPreheader());
876877
VPBasicBlock *VecPreheader = new VPBasicBlock("vector.ph");
877878
auto Plan = std::make_unique<VPlan>(Entry, VecPreheader);
879+
880+
// Create SCEV and VPValue for the trip count.
881+
const SCEV *BackedgeTakenCount = PSE.getBackedgeTakenCount();
882+
assert(!isa<SCEVCouldNotCompute>(BackedgeTakenCount) && "Invalid loop count");
883+
ScalarEvolution &SE = *PSE.getSE();
884+
const SCEV *TripCount =
885+
SE.getTripCountFromExitCount(BackedgeTakenCount, InductionTy, TheLoop);
878886
Plan->TripCount =
879887
vputils::getOrCreateVPValueForSCEVExpr(*Plan, TripCount, SE);
888+
880889
// Create VPRegionBlock, with empty header and latch blocks, to be filled
881890
// during processing later.
882891
VPBasicBlock *HeaderVPBB = new VPBasicBlock("vector.body");

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ Value *getRuntimeVF(IRBuilderBase &B, Type *Ty, ElementCount VF);
8383
Value *createStepForVF(IRBuilderBase &B, Type *Ty, ElementCount VF,
8484
int64_t Step);
8585

86-
const SCEV *createTripCountSCEV(Type *IdxTy, PredicatedScalarEvolution &PSE,
87-
Loop *CurLoop = nullptr);
88-
8986
/// A helper function that returns the reciprocal of the block probability of
9087
/// predicated blocks. If we return X, we are assuming the predicated block
9188
/// will execute once for every X iterations of the loop header.
@@ -3477,8 +3474,10 @@ class VPlan {
34773474
/// middle VPBasicBlock. If a check is needed to guard executing the scalar
34783475
/// epilogue loop, it will be added to the middle block, together with
34793476
/// VPBasicBlocks for the scalar preheader and exit blocks.
3480-
static VPlanPtr createInitialVPlan(const SCEV *TripCount,
3481-
ScalarEvolution &PSE,
3477+
/// \p InductionTy is the type of the canonical induction and used for related
3478+
/// values, like the trip count expression.
3479+
static VPlanPtr createInitialVPlan(Type *InductionTy,
3480+
PredicatedScalarEvolution &PSE,
34823481
bool RequiresScalarEpilogueCheck,
34833482
bool TailFolded, Loop *TheLoop);
34843483

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "VPlanCFG.h"
1212
#include "VPlanDominatorTree.h"
1313
#include "llvm/ADT/TypeSwitch.h"
14+
#include "llvm/Analysis/ScalarEvolution.h"
1415
#include "llvm/IR/Instruction.h"
1516
#include "llvm/IR/PatternMatch.h"
1617
#include "llvm/Support/GenericDomTreeConstruction.h"

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,10 +685,11 @@ void VPlanTransforms::optimizeForVFAndUF(VPlan &Plan, ElementCount BestVF,
685685
m_BranchOnCond(m_Not(m_ActiveLaneMask(m_VPValue(), m_VPValue())))))
686686
return;
687687

688-
Type *IdxTy =
689-
Plan.getCanonicalIV()->getStartValue()->getLiveInIRValue()->getType();
690-
const SCEV *TripCount = createTripCountSCEV(IdxTy, PSE);
691688
ScalarEvolution &SE = *PSE.getSE();
689+
const SCEV *TripCount =
690+
vputils::getSCEVExprForVPValue(Plan.getTripCount(), SE);
691+
assert(!isa<SCEVCouldNotCompute>(TripCount) &&
692+
"Trip count SCEV must be computable");
692693
ElementCount NumElements = BestVF.multiplyCoefficientBy(BestUF);
693694
const SCEV *C = SE.getElementCount(TripCount->getType(), NumElements);
694695
if (TripCount->isZero() ||

llvm/lib/Transforms/Vectorize/VPlanUtils.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "VPlanUtils.h"
1010
#include "VPlanPatternMatch.h"
11+
#include "llvm/ADT/TypeSwitch.h"
1112
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
1213

1314
using namespace llvm;
@@ -60,3 +61,14 @@ bool vputils::isHeaderMask(const VPValue *V, VPlan &Plan) {
6061
return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) &&
6162
IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount();
6263
}
64+
65+
const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) {
66+
if (V->isLiveIn())
67+
return SE.getSCEV(V->getLiveInIRValue());
68+
69+
// TODO: Support constructing SCEVs for more recipes as needed.
70+
return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe())
71+
.Case<VPExpandSCEVRecipe>(
72+
[](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })
73+
.Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
74+
}

llvm/lib/Transforms/Vectorize/VPlanUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111

1212
#include "VPlan.h"
1313

14+
namespace llvm {
15+
class ScalarEvolution;
16+
class SCEV;
17+
} // namespace llvm
18+
1419
namespace llvm::vputils {
1520
/// Returns true if only the first lane of \p Def is used.
1621
bool onlyFirstLaneUsed(const VPValue *Def);
@@ -26,6 +31,10 @@ bool onlyFirstPartUsed(const VPValue *Def);
2631
VPValue *getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
2732
ScalarEvolution &SE);
2833

34+
/// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no
35+
/// SCEV expression could be constructed.
36+
const SCEV *getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE);
37+
2938
/// Returns true if \p VPV is uniform after vectorization.
3039
inline bool isUniformAfterVectorization(const VPValue *VPV) {
3140
// A value defined outside the vector region must be uniform after

llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,12 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
101101
raw_string_ostream OS(FullDump);
102102
Plan->printDOT(OS);
103103
const char *ExpectedStr = R"(digraph VPlan {
104-
graph [labelloc=t, fontsize=30; label="Vectorization Plan\n for UF\>=1\nLive-in vp\<%0\> = vector-trip-count\nvp\<%1\> = original trip-count\n"]
104+
graph [labelloc=t, fontsize=30; label="Vectorization Plan\n for UF\>=1\nLive-in vp\<%0\> = vector-trip-count\nLive-in ir\<%N\> = original trip-count\n"]
105105
node [shape=rect, fontname=Courier, fontsize=30]
106106
edge [fontname=Courier, fontsize=30]
107107
compound=true
108108
N0 [label =
109109
"ir-bb\<entry\>:\l" +
110-
" EMIT vp\<%1\> = EXPAND SCEV (-1 + %N)\l" +
111110
"No successors\l"
112111
]
113112
N1 [label =
@@ -134,8 +133,8 @@ compound=true
134133
N2 -> N4 [ label="" ltail=cluster_N3]
135134
N4 [label =
136135
"middle.block:\l" +
137-
" EMIT vp\<%2\> = icmp eq vp\<%1\>, vp\<%0\>\l" +
138-
" EMIT branch-on-cond vp\<%2\>\l" +
136+
" EMIT vp\<%1\> = icmp eq ir\<%N\>, vp\<%0\>\l" +
137+
" EMIT branch-on-cond vp\<%1\>\l" +
139138
"Successor(s): ir-bb\<for.end\>, scalar.ph\l"
140139
]
141140
N4 -> N5 [ label="T"]

llvm/unittests/Transforms/Vectorize/VPlanTestBase.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ class VPlanTestBase : public testing::Test {
6767
assert(!verifyFunction(F) && "input function must be valid");
6868
doAnalysis(F);
6969

70-
auto Plan = VPlan::createInitialVPlan(
71-
SE->getBackedgeTakenCount(LI->getLoopFor(LoopHeader)), *SE, true, false,
72-
LI->getLoopFor(LoopHeader));
73-
VPlanHCFGBuilder HCFGBuilder(LI->getLoopFor(LoopHeader), LI.get(), *Plan);
70+
Loop *L = LI->getLoopFor(LoopHeader);
71+
PredicatedScalarEvolution PSE(*SE, *L);
72+
auto Plan = VPlan::createInitialVPlan(IntegerType::get(*Ctx, 64), PSE, true,
73+
false, L);
74+
VPlanHCFGBuilder HCFGBuilder(L, LI.get(), *Plan);
7475
HCFGBuilder.buildHierarchicalCFG();
7576
return Plan;
7677
}
@@ -81,10 +82,11 @@ class VPlanTestBase : public testing::Test {
8182
assert(!verifyFunction(F) && "input function must be valid");
8283
doAnalysis(F);
8384

84-
auto Plan = VPlan::createInitialVPlan(
85-
SE->getBackedgeTakenCount(LI->getLoopFor(LoopHeader)), *SE, true, false,
86-
LI->getLoopFor(LoopHeader));
87-
VPlanHCFGBuilder HCFGBuilder(LI->getLoopFor(LoopHeader), LI.get(), *Plan);
85+
Loop *L = LI->getLoopFor(LoopHeader);
86+
PredicatedScalarEvolution PSE(*SE, *L);
87+
auto Plan = VPlan::createInitialVPlan(IntegerType::get(*Ctx, 64), PSE, true,
88+
false, L);
89+
VPlanHCFGBuilder HCFGBuilder(L, LI.get(), *Plan);
8890
HCFGBuilder.buildPlainCFG();
8991
return Plan;
9092
}

0 commit comments

Comments
 (0)