Skip to content

Commit 300d2c6

Browse files
committed
[VPlan] Move SCEV expansion to VPlan transform. (NFCI).
Move the logic to expand SCEVs directly to a late VPlan transform that expands SCEVs in the entry block. This turns VPExpandSCEVRecipe into an abstract recipe without execute, which clarifies how the recipe is handled, i.e. it is not executed like regular recipes. It also helps to simplify construction, as now scalar evolution isn't required to be passed to the recipe.
1 parent 38f0b9e commit 300d2c6

File tree

9 files changed

+62
-59
lines changed

9 files changed

+62
-59
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7306,6 +7306,16 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
73067306
VPlanTransforms::materializeVFAndVFxUF(BestVPlan, VectorPH, BestVF);
73077307
VPlanTransforms::simplifyRecipes(BestVPlan);
73087308

7309+
// 0. Generate SCEV-dependent code in the entry, including TripCount, before
7310+
// making any changes to the CFG.
7311+
DenseMap<const SCEV *, Value *> ExpandedSCEVs =
7312+
VPlanTransforms::expandSCEVs(BestVPlan, *PSE.getSE());
7313+
if (!ILV.getTripCount())
7314+
ILV.setTripCount(BestVPlan.getTripCount()->getLiveInIRValue());
7315+
else
7316+
assert(VectorizingEpilogue && "should only re-use the existing trip "
7317+
"count during epilogue vectorization");
7318+
73097319
// Perform the actual loop transformation.
73107320
VPTransformState State(&TTI, BestVF, LI, DT, ILV.AC, ILV.Builder, &BestVPlan,
73117321
OrigLoop->getParentLoop(),
@@ -7315,30 +7325,6 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
73157325
assert(DT->verify(DominatorTree::VerificationLevel::Fast));
73167326
#endif
73177327

7318-
// 0. Generate SCEV-dependent code in the entry, including TripCount, before
7319-
// making any changes to the CFG.
7320-
DenseMap<const SCEV *, Value *> ExpandedSCEVs;
7321-
auto *Entry = cast<VPIRBasicBlock>(BestVPlan.getEntry());
7322-
State.Builder.SetInsertPoint(Entry->getIRBasicBlock()->getTerminator());
7323-
for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
7324-
auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
7325-
if (!ExpSCEV)
7326-
continue;
7327-
ExpSCEV->execute(State);
7328-
ExpandedSCEVs[ExpSCEV->getSCEV()] = State.get(ExpSCEV, VPLane(0));
7329-
VPValue *Exp = BestVPlan.getOrAddLiveIn(ExpandedSCEVs[ExpSCEV->getSCEV()]);
7330-
ExpSCEV->replaceAllUsesWith(Exp);
7331-
if (BestVPlan.getTripCount() == ExpSCEV)
7332-
BestVPlan.resetTripCount(Exp);
7333-
ExpSCEV->eraseFromParent();
7334-
}
7335-
7336-
if (!ILV.getTripCount())
7337-
ILV.setTripCount(State.get(BestVPlan.getTripCount(), VPLane(0)));
7338-
else
7339-
assert(VectorizingEpilogue && "should only re-use the existing trip "
7340-
"count during epilogue vectorization");
7341-
73427328
// 1. Set up the skeleton for vectorization, including vector pre-header and
73437329
// middle block. The vector loop is created during VPlan execution.
73447330
BasicBlock *EntryBB =
@@ -7776,7 +7762,7 @@ createWidenInductionRecipes(PHINode *Phi, Instruction *PhiOrTrunc,
77767762
"step must be loop invariant");
77777763

77787764
VPValue *Step =
7779-
vputils::getOrCreateVPValueForSCEVExpr(Plan, IndDesc.getStep(), SE);
7765+
vputils::getOrCreateVPValueForSCEVExpr(Plan, IndDesc.getStep());
77807766
if (auto *TruncI = dyn_cast<TruncInst>(PhiOrTrunc)) {
77817767
return new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, &Plan.getVF(),
77827768
IndDesc, TruncI,
@@ -7798,8 +7784,7 @@ VPHeaderPHIRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI(
77987784

77997785
// Check if this is pointer induction. If so, build the recipe for it.
78007786
if (auto *II = Legal->getPointerInductionDescriptor(Phi)) {
7801-
VPValue *Step = vputils::getOrCreateVPValueForSCEVExpr(Plan, II->getStep(),
7802-
*PSE.getSE());
7787+
VPValue *Step = vputils::getOrCreateVPValueForSCEVExpr(Plan, II->getStep());
78037788
return new VPWidenPointerInductionRecipe(
78047789
Phi, Operands[0], Step, &Plan.getVFxUF(), *II,
78057790
LoopVectorizationPlanner::getDecisionAndClampRange(
@@ -8957,7 +8942,7 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VFRange &Range) {
89578942
[this](PHINode *P) {
89588943
return Legal->getIntOrFpInductionDescriptor(P);
89598944
},
8960-
*PSE.getSE(), *TLI))
8945+
*TLI))
89618946
return nullptr;
89628947

89638948
// Collect mapping of IR header phis to header phi recipes, to be used in

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3253,22 +3253,20 @@ struct VPWidenStoreEVLRecipe final : public VPWidenMemoryRecipe {
32533253
/// Recipe to expand a SCEV expression.
32543254
class VPExpandSCEVRecipe : public VPSingleDefRecipe {
32553255
const SCEV *Expr;
3256-
ScalarEvolution &SE;
32573256

32583257
public:
3259-
VPExpandSCEVRecipe(const SCEV *Expr, ScalarEvolution &SE)
3260-
: VPSingleDefRecipe(VPDef::VPExpandSCEVSC, {}), Expr(Expr), SE(SE) {}
3258+
VPExpandSCEVRecipe(const SCEV *Expr)
3259+
: VPSingleDefRecipe(VPDef::VPExpandSCEVSC, {}), Expr(Expr) {}
32613260

32623261
~VPExpandSCEVRecipe() override = default;
32633262

3264-
VPExpandSCEVRecipe *clone() override {
3265-
return new VPExpandSCEVRecipe(Expr, SE);
3266-
}
3263+
VPExpandSCEVRecipe *clone() override { return new VPExpandSCEVRecipe(Expr); }
32673264

32683265
VP_CLASSOF_IMPL(VPDef::VPExpandSCEVSC)
32693266

3270-
/// Generate a canonical vector induction variable of the vector loop, with
3271-
void execute(VPTransformState &State) override;
3267+
void execute(VPTransformState &State) override {
3268+
llvm_unreachable("SCEV expressions must be expanded before final execute");
3269+
}
32723270

32733271
/// Return the cost of this VPExpandSCEVRecipe.
32743272
InstructionCost computeCost(ElementCount VF,

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,7 @@ static void addInitialSkeleton(VPlan &Plan, Type *InductionTy, DebugLoc IVDL,
487487
ScalarEvolution &SE = *PSE.getSE();
488488
const SCEV *TripCount = SE.getTripCountFromExitCount(BackedgeTakenCountSCEV,
489489
InductionTy, TheLoop);
490-
Plan.setTripCount(
491-
vputils::getOrCreateVPValueForSCEVExpr(Plan, TripCount, SE));
490+
Plan.setTripCount(vputils::getOrCreateVPValueForSCEVExpr(Plan, TripCount));
492491

493492
VPBasicBlock *ScalarPH = Plan.createVPBasicBlock("scalar.ph");
494493
VPBlockUtils::connectBlocks(ScalarPH, Plan.getScalarHeader());

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
3838
#include "llvm/Transforms/Utils/LoopUtils.h"
3939
#include "llvm/Transforms/Utils/LoopVersioning.h"
40-
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
4140
#include <cassert>
4241

4342
using namespace llvm;
@@ -3803,18 +3802,7 @@ void VPWidenPointerInductionRecipe::print(raw_ostream &O, const Twine &Indent,
38033802
getOperand(4)->printAsOperand(O, SlotTracker);
38043803
}
38053804
}
3806-
#endif
3807-
3808-
void VPExpandSCEVRecipe::execute(VPTransformState &State) {
3809-
assert(!State.Lane && "cannot be used in per-lane");
3810-
const DataLayout &DL = SE.getDataLayout();
3811-
SCEVExpander Exp(SE, DL, "induction", /*PreserveLCSSA=*/true);
3812-
Value *Res = Exp.expandCodeFor(Expr, Expr->getType(),
3813-
&*State.Builder.GetInsertPoint());
3814-
State.set(this, Res, VPLane(0));
3815-
}
38163805

3817-
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
38183806
void VPExpandSCEVRecipe::print(raw_ostream &O, const Twine &Indent,
38193807
VPSlotTracker &SlotTracker) const {
38203808
O << Indent << "EMIT ";

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "llvm/IR/MDBuilder.h"
3535
#include "llvm/Support/Casting.h"
3636
#include "llvm/Support/TypeSize.h"
37+
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
3738

3839
using namespace llvm;
3940
using namespace VPlanPatternMatch;
@@ -42,7 +43,7 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
4243
VPlanPtr &Plan,
4344
function_ref<const InductionDescriptor *(PHINode *)>
4445
GetIntOrFpInductionDescriptor,
45-
ScalarEvolution &SE, const TargetLibraryInfo &TLI) {
46+
const TargetLibraryInfo &TLI) {
4647

4748
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
4849
Plan->getVectorLoopRegion());
@@ -73,7 +74,7 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
7374
} else {
7475
VPValue *Start = Plan->getOrAddLiveIn(II->getStartValue());
7576
VPValue *Step =
76-
vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE);
77+
vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep());
7778
NewRecipe = new VPWidenIntOrFpInductionRecipe(
7879
Phi, Start, Step, &Plan->getVF(), *II, Ingredient.getDebugLoc());
7980
}
@@ -3468,6 +3469,33 @@ void VPlanTransforms::materializeVFAndVFxUF(VPlan &Plan, VPBasicBlock *VectorPH,
34683469
VFxUF.replaceAllUsesWith(MulByUF);
34693470
}
34703471

3472+
DenseMap<const SCEV *, Value *>
3473+
VPlanTransforms::expandSCEVs(VPlan &Plan, ScalarEvolution &SE) {
3474+
const DataLayout &DL = SE.getDataLayout();
3475+
SCEVExpander Expander(SE, DL, "induction", /*PreserveLCSSA=*/true);
3476+
3477+
auto *Entry = cast<VPIRBasicBlock>(Plan.getEntry());
3478+
BasicBlock *EntryBB = Entry->getIRBasicBlock();
3479+
DenseMap<const SCEV *, Value *> ExpandedSCEVs;
3480+
for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
3481+
if (isa<VPIRInstruction, VPIRPhi>(&R))
3482+
continue;
3483+
auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
3484+
if (!ExpSCEV)
3485+
break;
3486+
const SCEV *Expr = ExpSCEV->getSCEV();
3487+
Value *Res =
3488+
Expander.expandCodeFor(Expr, Expr->getType(), EntryBB->getTerminator());
3489+
ExpandedSCEVs[ExpSCEV->getSCEV()] = Res;
3490+
VPValue *Exp = Plan.getOrAddLiveIn(Res);
3491+
ExpSCEV->replaceAllUsesWith(Exp);
3492+
if (Plan.getTripCount() == ExpSCEV)
3493+
Plan.resetTripCount(Exp);
3494+
ExpSCEV->eraseFromParent();
3495+
}
3496+
return ExpandedSCEVs;
3497+
}
3498+
34713499
/// Returns true if \p V is VPWidenLoadRecipe or VPInterleaveRecipe that can be
34723500
/// converted to a narrower recipe. \p V is used by a wide recipe that feeds a
34733501
/// store interleave group at index \p Idx, \p WideMember0 is the recipe feeding

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct VPlanTransforms {
100100
VPlanPtr &Plan,
101101
function_ref<const InductionDescriptor *(PHINode *)>
102102
GetIntOrFpInductionDescriptor,
103-
ScalarEvolution &SE, const TargetLibraryInfo &TLI);
103+
const TargetLibraryInfo &TLI);
104104

105105
/// Try to have all users of fixed-order recurrences appear after the recipe
106106
/// defining their previous value, by either sinking users or hoisting recipes
@@ -282,6 +282,13 @@ struct VPlanTransforms {
282282
static void materializeVFAndVFxUF(VPlan &Plan, VPBasicBlock *VectorPH,
283283
ElementCount VF);
284284

285+
/// Expand VPExpandSCEVRecipes in \p Plan's entry block. Each
286+
/// VPExpandSCEVRecipe is replaced with a live-in wrapping the expanded IR
287+
/// value. A mapping from SCEV expressions to their expanded IR value is
288+
/// returned.
289+
static DenseMap<const SCEV *, Value *> expandSCEVs(VPlan &Plan,
290+
ScalarEvolution &SE);
291+
285292
/// Try to convert a plan with interleave groups with VF elements to a plan
286293
/// with the interleave groups replaced by wide loads and stores processing VF
287294
/// elements, if all transformed interleave groups access the full vector

llvm/lib/Transforms/Vectorize/VPlanUtils.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ bool vputils::onlyScalarValuesUsed(const VPValue *Def) {
2929
[Def](const VPUser *U) { return U->usesScalars(Def); });
3030
}
3131

32-
VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
33-
ScalarEvolution &SE) {
32+
VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr) {
3433
if (auto *Expanded = Plan.getSCEVExpansion(Expr))
3534
return Expanded;
3635
VPValue *Expanded = nullptr;
@@ -45,7 +44,7 @@ VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
4544
if (U && !isa<Instruction>(U->getValue())) {
4645
Expanded = Plan.getOrAddLiveIn(U->getValue());
4746
} else {
48-
Expanded = new VPExpandSCEVRecipe(Expr, SE);
47+
Expanded = new VPExpandSCEVRecipe(Expr);
4948
Plan.getEntry()->appendRecipe(Expanded->getDefiningRecipe());
5049
}
5150
}

llvm/lib/Transforms/Vectorize/VPlanUtils.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ bool onlyScalarValuesUsed(const VPValue *Def);
3333
/// value. Otherwise return a VPExpandSCEVRecipe to expand \p Expr. If \p Plan's
3434
/// pre-header already contains a recipe expanding \p Expr, return it. If not,
3535
/// create a new one.
36-
VPValue *getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
37-
ScalarEvolution &SE);
36+
VPValue *getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr);
3837

3938
/// Return the SCEV expression for \p V. Returns SCEVCouldNotCompute if no
4039
/// SCEV expression could be constructed.

llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) {
203203
VPInstruction::BranchOnCond,
204204
{Plan->getOrAddLiveIn(ConstantInt::getTrue(F->getContext()))}));
205205
VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
206-
Plan, [](PHINode *P) { return nullptr; }, *SE, TLI);
206+
Plan, [](PHINode *P) { return nullptr; }, TLI);
207207

208208
VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
209209
EXPECT_EQ(0u, Entry->getNumPredecessors());

0 commit comments

Comments
 (0)