Skip to content

Commit ed85b35

Browse files
committed
[VPlan] Add VPSymbolicValueSC for typed VPValues w/o underlying IR value
This introduces a new VPSymbolicValueSC to be used for typed live-in VPValues without underlying IR. VPValue is updated to store either the type or an underlying value in an union. This allows keeping the size of VPValue unchanged. The main motivation for adding the type is to not require passing the canonical IV type to VPTypeAnalysis. While with this patch, we still need to pass the LLVMContext, this can also be removed in a future patch (see 9493c38)
1 parent 437d587 commit ed85b35

File tree

11 files changed

+76
-55
lines changed

11 files changed

+76
-55
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4478,7 +4478,7 @@ void LoopVectorizationPlanner::emitInvalidCostRemarks(
44784478
static bool willGenerateVectors(VPlan &Plan, ElementCount VF,
44794479
const TargetTransformInfo &TTI) {
44804480
assert(VF.isVector() && "Checking a scalar VF?");
4481-
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType());
4481+
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType()->getContext());
44824482
DenseSet<VPRecipeBase *> EphemeralRecipes;
44834483
collectEphemeralRecipesForVPlan(Plan, EphemeralRecipes);
44844484
// Set of already visited types.
@@ -9069,7 +9069,7 @@ static VPInstruction *addResumePhiRecipeForInduction(
90699069
/// \p IVEndValues.
90709070
static void addScalarResumePhis(VPRecipeBuilder &Builder, VPlan &Plan,
90719071
DenseMap<VPValue *, VPValue *> &IVEndValues) {
9072-
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType());
9072+
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType()->getContext());
90739073
auto *ScalarPH = Plan.getScalarPreheader();
90749074
auto *MiddleVPBB = cast<VPBasicBlock>(ScalarPH->getSinglePredecessor());
90759075
VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
@@ -9312,7 +9312,8 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
93129312
return !CM.requiresScalarEpilogue(VF.isVector());
93139313
},
93149314
Range);
9315-
auto Plan = std::make_unique<VPlan>(OrigLoop);
9315+
auto Plan =
9316+
std::make_unique<VPlan>(OrigLoop, Legal->getWidestInductionType());
93169317
// Build hierarchical CFG.
93179318
// Convert to VPlan-transform and consoliate all transforms for VPlan
93189319
// creation.
@@ -9618,7 +9619,8 @@ VPlanPtr LoopVectorizationPlanner::buildVPlan(VFRange &Range) {
96189619
assert(EnableVPlanNativePath && "VPlan-native path is not enabled.");
96199620

96209621
// Create new empty VPlan
9621-
auto Plan = std::make_unique<VPlan>(OrigLoop);
9622+
auto Plan =
9623+
std::make_unique<VPlan>(OrigLoop, Legal->getWidestInductionType());
96229624
// Build hierarchical CFG
96239625
VPlanHCFGBuilder HCFGBuilder(OrigLoop, LI, *Plan);
96249626
HCFGBuilder.buildHierarchicalCFG();

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ VPTransformState::VPTransformState(const TargetTransformInfo *TTI,
221221
Loop *CurrentParentLoop, Type *CanonicalIVTy)
222222
: TTI(TTI), VF(VF), CFG(DT), LI(LI), Builder(Builder), ILV(ILV), Plan(Plan),
223223
CurrentParentLoop(CurrentParentLoop), LVer(nullptr),
224-
TypeAnalysis(CanonicalIVTy) {}
224+
TypeAnalysis(CanonicalIVTy->getContext()) {}
225225

226226
Value *VPTransformState::get(const VPValue *Def, const VPLane &Lane) {
227227
if (Def->isLiveIn())
@@ -847,7 +847,8 @@ void VPRegionBlock::print(raw_ostream &O, const Twine &Indent,
847847
}
848848
#endif
849849

850-
VPlan::VPlan(Loop *L) {
850+
VPlan::VPlan(Loop *L, Type *InductionTy)
851+
: VectorTripCount(InductionTy), VF(InductionTy), VFxUF(InductionTy) {
851852
setEntry(createVPIRBasicBlock(L->getLoopPreheader()));
852853
ScalarHeader = createVPIRBasicBlock(L->getHeader());
853854

@@ -858,7 +859,7 @@ VPlan::VPlan(Loop *L) {
858859
}
859860

860861
VPlan::~VPlan() {
861-
VPValue DummyValue;
862+
VPValue DummyValue((Type *)nullptr);
862863

863864
for (auto *VPB : CreatedBlocks) {
864865
if (auto *VPBB = dyn_cast<VPBasicBlock>(VPB)) {
@@ -888,10 +889,10 @@ void VPlan::prepareToExecute(Value *TripCountV, Value *VectorTripCountV,
888889
IRBuilder<> Builder(State.CFG.PrevBB->getTerminator());
889890
auto *TCMO = Builder.CreateSub(TripCountV, ConstantInt::get(TCTy, 1),
890891
"trip.count.minus.1");
891-
BackedgeTakenCount->setUnderlyingValue(TCMO);
892+
BackedgeTakenCount->replaceAllUsesWith(getOrAddLiveIn(TCMO));
892893
}
893894

894-
VectorTripCount.setUnderlyingValue(VectorTripCountV);
895+
VectorTripCount.replaceAllUsesWith(getOrAddLiveIn(VectorTripCountV));
895896

896897
IRBuilder<> Builder(State.CFG.PrevBB->getTerminator());
897898
// FIXME: Model VF * UF computation completely in VPlan.
@@ -900,12 +901,13 @@ void VPlan::prepareToExecute(Value *TripCountV, Value *VectorTripCountV,
900901
unsigned UF = getUF();
901902
if (VF.getNumUsers()) {
902903
Value *RuntimeVF = getRuntimeVF(Builder, TCTy, State.VF);
903-
VF.setUnderlyingValue(RuntimeVF);
904-
VFxUF.setUnderlyingValue(
904+
VF.replaceAllUsesWith(getOrAddLiveIn(RuntimeVF));
905+
VFxUF.replaceAllUsesWith(getOrAddLiveIn(
905906
UF > 1 ? Builder.CreateMul(RuntimeVF, ConstantInt::get(TCTy, UF))
906-
: RuntimeVF);
907+
: RuntimeVF));
907908
} else {
908-
VFxUF.setUnderlyingValue(createStepForVF(Builder, TCTy, State.VF, UF));
909+
VFxUF.replaceAllUsesWith(
910+
getOrAddLiveIn(createStepForVF(Builder, TCTy, State.VF, UF)));
909911
}
910912
}
911913

@@ -1166,7 +1168,8 @@ VPlan *VPlan::duplicate() {
11661168
return VPIRBB && VPIRBB->getIRBasicBlock() == ScalarHeaderIRBB;
11671169
}));
11681170
// Create VPlan, clone live-ins and remap operands in the cloned blocks.
1169-
auto *NewPlan = new VPlan(cast<VPBasicBlock>(NewEntry), NewScalarHeader);
1171+
auto *NewPlan = new VPlan(cast<VPBasicBlock>(NewEntry), NewScalarHeader,
1172+
getCanonicalIV()->getScalarType());
11701173
DenseMap<VPValue *, VPValue *> Old2NewVPValues;
11711174
for (VPValue *OldLiveIn : getLiveIns()) {
11721175
Old2NewVPValues[OldLiveIn] =
@@ -1176,7 +1179,7 @@ VPlan *VPlan::duplicate() {
11761179
Old2NewVPValues[&VF] = &NewPlan->VF;
11771180
Old2NewVPValues[&VFxUF] = &NewPlan->VFxUF;
11781181
if (BackedgeTakenCount) {
1179-
NewPlan->BackedgeTakenCount = new VPValue();
1182+
NewPlan->BackedgeTakenCount = new VPValue((Type *)nullptr);
11801183
Old2NewVPValues[BackedgeTakenCount] = NewPlan->BackedgeTakenCount;
11811184
}
11821185
assert(TripCount && "trip count must be set");
@@ -1379,6 +1382,11 @@ static bool isDefinedInsideLoopRegions(const VPValue *VPV) {
13791382
DefR->getParent()->getEnclosingLoopRegion());
13801383
}
13811384

1385+
Type *VPValue::getType() const {
1386+
assert(isLiveIn());
1387+
return SubclassID == VPSymbolicValueSC ? Ty : getUnderlyingValue()->getType();
1388+
}
1389+
13821390
bool VPValue::isDefinedOutsideLoopRegions() const {
13831391
return !isDefinedInsideLoopRegions(this);
13841392
}

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3475,8 +3475,9 @@ class VPlan {
34753475

34763476
/// Construct a VPlan with \p Entry to the plan and with \p ScalarHeader
34773477
/// wrapping the original header of the scalar loop.
3478-
VPlan(VPBasicBlock *Entry, VPIRBasicBlock *ScalarHeader)
3479-
: Entry(Entry), ScalarHeader(ScalarHeader) {
3478+
VPlan(VPBasicBlock *Entry, VPIRBasicBlock *ScalarHeader, Type *InductionTy)
3479+
: Entry(Entry), ScalarHeader(ScalarHeader), VectorTripCount(InductionTy),
3480+
VF(InductionTy), VFxUF(InductionTy) {
34803481
Entry->setPlan(this);
34813482
assert(ScalarHeader->getNumSuccessors() == 0 &&
34823483
"scalar header must be a leaf node");
@@ -3486,11 +3487,12 @@ class VPlan {
34863487
/// Construct a VPlan for \p L. This will create VPIRBasicBlocks wrapping the
34873488
/// original preheader and scalar header of \p L, to be used as entry and
34883489
/// scalar header blocks of the new VPlan.
3489-
VPlan(Loop *L);
3490+
VPlan(Loop *L, Type *InductionTy);
34903491

34913492
/// Construct a VPlan with a new VPBasicBlock as entry, a VPIRBasicBlock
34923493
/// wrapping \p ScalarHeaderBB and a trip count of \p TC.
3493-
VPlan(BasicBlock *ScalarHeaderBB, VPValue *TC) {
3494+
VPlan(BasicBlock *ScalarHeaderBB, VPValue *TC, Type *InductionTy)
3495+
: VectorTripCount(InductionTy), VF(InductionTy), VFxUF(InductionTy) {
34943496
setEntry(createVPBasicBlock("preheader"));
34953497
ScalarHeader = createVPIRBasicBlock(ScalarHeaderBB);
34963498
TripCount = TC;
@@ -3582,7 +3584,7 @@ class VPlan {
35823584
/// The backedge taken count of the original loop.
35833585
VPValue *getOrCreateBackedgeTakenCount() {
35843586
if (!BackedgeTakenCount)
3585-
BackedgeTakenCount = new VPValue();
3587+
BackedgeTakenCount = new VPValue(getCanonicalIV()->getScalarType());
35863588
return BackedgeTakenCount;
35873589
}
35883590

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,8 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
224224
if (Type *CachedTy = CachedTypes.lookup(V))
225225
return CachedTy;
226226

227-
if (V->isLiveIn()) {
228-
if (auto *IRValue = V->getLiveInIRValue())
229-
return IRValue->getType();
230-
// All VPValues without any underlying IR value (like the vector trip count
231-
// or the backedge-taken count) have the same type as the canonical IV.
232-
return CanonicalIVTy;
233-
}
227+
if (V->isLiveIn())
228+
return V->getType();
234229

235230
Type *ResultTy =
236231
TypeSwitch<const VPRecipeBase *, Type *>(V->getDefiningRecipe())

llvm/lib/Transforms/Vectorize/VPlanAnalysis.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ class Type;
3939
/// of the previously inferred types.
4040
class VPTypeAnalysis {
4141
DenseMap<const VPValue *, Type *> CachedTypes;
42-
/// Type of the canonical induction variable. Used for all VPValues without
43-
/// any underlying IR value (like the vector trip count or the backedge-taken
44-
/// count).
45-
Type *CanonicalIVTy;
4642
LLVMContext &Ctx;
4743

4844
Type *inferScalarTypeForRecipe(const VPBlendRecipe *R);
@@ -55,8 +51,7 @@ class VPTypeAnalysis {
5551
Type *inferScalarTypeForRecipe(const VPReplicateRecipe *R);
5652

5753
public:
58-
VPTypeAnalysis(Type *CanonicalIVTy)
59-
: CanonicalIVTy(CanonicalIVTy), Ctx(CanonicalIVTy->getContext()) {}
54+
VPTypeAnalysis(LLVMContext &Ctx) : Ctx(Ctx) {}
6055

6156
/// Infer the type of \p V. Returns the scalar type of \p V.
6257
Type *inferScalarType(const VPValue *V);

llvm/lib/Transforms/Vectorize/VPlanHelpers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ struct VPCostContext {
375375
VPCostContext(const TargetTransformInfo &TTI, const TargetLibraryInfo &TLI,
376376
Type *CanIVTy, LoopVectorizationCostModel &CM,
377377
TargetTransformInfo::TargetCostKind CostKind)
378-
: TTI(TTI), TLI(TLI), Types(CanIVTy), LLVMCtx(CanIVTy->getContext()),
379-
CM(CM), CostKind(CostKind) {}
378+
: TTI(TTI), TLI(TLI), Types(CanIVTy->getContext()),
379+
LLVMCtx(CanIVTy->getContext()), CM(CM), CostKind(CostKind) {}
380380

381381
/// Return the cost for \p UI with \p VF using the legacy cost model as
382382
/// fallback until computing the cost of all recipes migrates to VPlan.

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind,
545545

546546
// Truncate base induction if needed.
547547
Type *CanonicalIVType = CanonicalIV->getScalarType();
548-
VPTypeAnalysis TypeInfo(CanonicalIVType);
548+
VPTypeAnalysis TypeInfo(CanonicalIVType->getContext());
549549
Type *ResultTy = TypeInfo.inferScalarType(BaseIV);
550550
if (TruncI) {
551551
Type *TruncTy = TruncI->getType();
@@ -751,7 +751,7 @@ void VPlanTransforms::optimizeInductionExitUsers(
751751
assert(PredVPBB == Plan.getMiddleBlock() &&
752752
"predecessor must be the middle block");
753753

754-
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType());
754+
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType()->getContext());
755755
VPBuilder B(Plan.getMiddleBlock()->getTerminator());
756756
for (VPRecipeBase &R : *ExitVPBB) {
757757
auto *ExitIRI = cast<VPIRInstruction>(&R);
@@ -944,8 +944,11 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
944944
#ifndef NDEBUG
945945
// Verify that the cached type info is for both A and its users is still
946946
// accurate by comparing it to freshly computed types.
947-
VPTypeAnalysis TypeInfo2(
948-
R.getParent()->getPlan()->getCanonicalIV()->getScalarType());
947+
VPTypeAnalysis TypeInfo2(R.getParent()
948+
->getPlan()
949+
->getCanonicalIV()
950+
->getScalarType()
951+
->getContext());
949952
assert(TypeInfo.inferScalarType(A) == TypeInfo2.inferScalarType(A));
950953
for (VPUser *U : A->users()) {
951954
auto *R = cast<VPRecipeBase>(U);
@@ -988,7 +991,7 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
988991
void VPlanTransforms::simplifyRecipes(VPlan &Plan, Type &CanonicalIVTy) {
989992
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
990993
Plan.getEntry());
991-
VPTypeAnalysis TypeInfo(&CanonicalIVTy);
994+
VPTypeAnalysis TypeInfo(CanonicalIVTy.getContext());
992995
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
993996
for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
994997
simplifyRecipe(R, TypeInfo);
@@ -1338,7 +1341,7 @@ void VPlanTransforms::truncateToMinimalBitwidths(
13381341
// typed.
13391342
DenseMap<VPValue *, VPWidenCastRecipe *> ProcessedTruncs;
13401343
Type *CanonicalIVType = Plan.getCanonicalIV()->getScalarType();
1341-
VPTypeAnalysis TypeInfo(CanonicalIVType);
1344+
VPTypeAnalysis TypeInfo(CanonicalIVType->getContext());
13421345
VPBasicBlock *PH = Plan.getVectorPreheader();
13431346
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
13441347
vp_depth_first_deep(Plan.getVectorLoopRegion()))) {
@@ -1730,8 +1733,8 @@ static VPRecipeBase *createEVLRecipe(VPValue *HeaderMask,
17301733
/// Replace recipes with their EVL variants.
17311734
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
17321735
Type *CanonicalIVType = Plan.getCanonicalIV()->getScalarType();
1733-
VPTypeAnalysis TypeInfo(CanonicalIVType);
17341736
LLVMContext &Ctx = CanonicalIVType->getContext();
1737+
VPTypeAnalysis TypeInfo(Ctx);
17351738
VPValue *AllOneMask = Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx));
17361739
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
17371740
VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();

llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class UnrollState {
7373

7474
public:
7575
UnrollState(VPlan &Plan, unsigned UF, LLVMContext &Ctx)
76-
: Plan(Plan), UF(UF), TypeInfo(Plan.getCanonicalIV()->getScalarType()) {}
76+
: Plan(Plan), UF(UF), TypeInfo(Ctx) {}
7777

7878
void unrollBlock(VPBlockBase *VPB);
7979

llvm/lib/Transforms/Vectorize/VPlanValue.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,22 @@ class VPValue {
6161
SmallVector<VPUser *, 1> Users;
6262

6363
protected:
64-
// Hold the underlying Value, if any, attached to this VPValue.
65-
Value *UnderlyingVal;
64+
union {
65+
// Hold the underlying Value, if any, attached to this non-symbolic VPValue.
66+
Value *UnderlyingVal;
67+
// Hold the type of this VPValue, if it is symbolic.
68+
Type *Ty;
69+
};
6670

6771
/// Pointer to the VPDef that defines this VPValue. If it is nullptr, the
6872
/// VPValue is not defined by any recipe modeled in VPlan.
6973
VPDef *Def;
7074

7175
VPValue(const unsigned char SC, Value *UV = nullptr, VPDef *Def = nullptr);
7276

73-
/// Create a live-in VPValue.
74-
VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV, nullptr) {}
77+
/// Create a live-in IR VPValue.
78+
VPValue(Value *UV) : VPValue(VPValueSC, UV, nullptr) {}
79+
VPValue(Type *Ty) : SubclassID(VPSymbolicValueSC), Ty(Ty), Def(nullptr) {}
7580
/// Create a VPValue for a \p Def which is a subclass of VPValue.
7681
VPValue(VPDef *Def, Value *UV = nullptr) : VPValue(VPVRecipeSC, UV, Def) {}
7782
/// Create a VPValue for a \p Def which defines multiple values.
@@ -86,14 +91,18 @@ class VPValue {
8691

8792
public:
8893
/// Return the underlying Value attached to this VPValue.
89-
Value *getUnderlyingValue() const { return UnderlyingVal; }
94+
Value *getUnderlyingValue() const {
95+
return SubclassID == VPSymbolicValueSC ? nullptr : UnderlyingVal;
96+
}
9097

9198
/// An enumeration for keeping track of the concrete subclass of VPValue that
9299
/// are actually instantiated.
93100
enum {
94-
VPValueSC, /// A generic VPValue, like live-in values or defined by a recipe
95-
/// that defines multiple values.
96-
VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase.
101+
VPValueSC, /// A generic non-symbolic VPValue, like live-in IR values or
102+
/// defined by a recipe that defines multiple values.
103+
VPSymbolicValueSC, /// A generic VPValue, like live-in values or defined by
104+
/// a recipe that defines multiple values.
105+
VPVRecipeSC /// A VPValue sub-class that is a VPRecipeBase.
97106
};
98107

99108
VPValue(const VPValue &) = delete;
@@ -172,6 +181,10 @@ class VPValue {
172181
/// Returns true if this VPValue is a live-in, i.e. defined outside the VPlan.
173182
bool isLiveIn() const { return !hasDefiningRecipe(); }
174183

184+
bool isSymbolic() const { return SubclassID == VPSymbolicValueSC; }
185+
186+
Type *getType() const;
187+
175188
/// Returns the underlying IR value, if this VPValue is defined outside the
176189
/// scope of VPlan. Returns nullptr if the VPValue is defined by a VPDef
177190
/// inside a VPlan.

llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,10 @@ bool VPlanVerifier::verify(const VPlan &Plan) {
415415
bool llvm::verifyVPlanIsValid(const VPlan &Plan) {
416416
VPDominatorTree VPDT;
417417
VPDT.recalculate(const_cast<VPlan &>(Plan));
418-
VPTypeAnalysis TypeInfo(
419-
const_cast<VPlan &>(Plan).getCanonicalIV()->getScalarType());
418+
VPTypeAnalysis TypeInfo(const_cast<VPlan &>(Plan)
419+
.getCanonicalIV()
420+
->getScalarType()
421+
->getContext());
420422
VPlanVerifier Verifier(VPDT, TypeInfo);
421423
return Verifier.verify(Plan);
422424
}

0 commit comments

Comments
 (0)