Skip to content

Commit 89a1b3a

Browse files
committed
[VPlan] Add VPWidenInduction recipe as common base class (NFC).
This helps to simplify some existing code and new code (#112145)
1 parent bbdc0bb commit 89a1b3a

File tree

5 files changed

+78
-73
lines changed

5 files changed

+78
-73
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7941,10 +7941,8 @@ BasicBlock *EpilogueVectorizerMainLoop::createEpilogueVectorizedLoopSkeleton(
79417941
SmallPtrSet<PHINode *, 4> WideIVs;
79427942
for (VPRecipeBase &H :
79437943
EPI.EpiloguePlan.getVectorLoopRegion()->getEntryBasicBlock()->phis()) {
7944-
if (auto *WideIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&H))
7944+
if (auto *WideIV = dyn_cast<VPWidenInductionRecipe>(&H))
79457945
WideIVs.insert(WideIV->getPHINode());
7946-
else if (auto *PtrIV = dyn_cast<VPWidenPointerInductionRecipe>(&H))
7947-
WideIVs.insert(cast<PHINode>(PtrIV->getUnderlyingValue()));
79487946
}
79497947
createInductionResumeVPValues(ExpandedSCEVs, nullptr, &WideIVs);
79507948

@@ -10131,13 +10129,7 @@ preparePlanForEpilogueVectorLoop(VPlan &Plan, Loop *L,
1013110129
} else {
1013210130
// Retrieve the induction resume values for wide inductions from
1013310131
// their original phi nodes in the scalar loop.
10134-
PHINode *IndPhi = nullptr;
10135-
if (auto *Ind = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
10136-
IndPhi = cast<PHINode>(Ind->getUnderlyingValue());
10137-
} else {
10138-
auto *WidenInd = cast<VPWidenIntOrFpInductionRecipe>(&R);
10139-
IndPhi = WidenInd->getPHINode();
10140-
}
10132+
PHINode *IndPhi = dyn_cast<VPWidenInductionRecipe>(&R)->getPHINode();
1014110133
// Hook up to the PHINode generated by a ResumePhi recipe of main
1014210134
// loop VPlan, which feeds the scalar loop.
1014310135
ResumeV = IndPhi->getIncomingValueForBlock(L->getLoopPreheader());

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ void VPlan::execute(VPTransformState *State) {
10471047
if (isa<VPWidenPHIRecipe>(&R))
10481048
continue;
10491049

1050-
if (isa<VPWidenPointerInductionRecipe, VPWidenIntOrFpInductionRecipe>(&R)) {
1050+
if (isa<VPWidenInductionRecipe>(&R)) {
10511051
PHINode *Phi = nullptr;
10521052
if (isa<VPWidenIntOrFpInductionRecipe>(&R)) {
10531053
Phi = cast<PHINode>(State->get(R.getVPSingleValue()));

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,38 +2099,81 @@ class VPHeaderPHIRecipe : public VPSingleDefRecipe {
20992099
}
21002100
};
21012101

2102+
/// Base class for widened induction (VPWidenIntOrFpInductionRecipe and
2103+
/// VPWidenPointerInductionRecipe), providing shared functionality, including
2104+
/// retrieving the step value, induction descriptor and original phi node.
2105+
class VPWidenInductionRecipe : public VPHeaderPHIRecipe {
2106+
const InductionDescriptor &IndDesc;
2107+
2108+
public:
2109+
VPWidenInductionRecipe(unsigned char Kind, PHINode *IV, VPValue *Start,
2110+
VPValue *Step, const InductionDescriptor &IndDesc,
2111+
DebugLoc DL)
2112+
: VPHeaderPHIRecipe(Kind, IV, Start, DL), IndDesc(IndDesc) {
2113+
addOperand(Step);
2114+
}
2115+
2116+
static inline bool classof(const VPRecipeBase *R) {
2117+
return R->getVPDefID() == VPDef::VPWidenIntOrFpInductionSC ||
2118+
R->getVPDefID() == VPDef::VPWidenPointerInductionSC;
2119+
}
2120+
2121+
virtual void execute(VPTransformState &State) override = 0;
2122+
2123+
/// Returns the step value of the induction.
2124+
VPValue *getStepValue() { return getOperand(1); }
2125+
const VPValue *getStepValue() const { return getOperand(1); }
2126+
2127+
PHINode *getPHINode() const { return cast<PHINode>(getUnderlyingValue()); }
2128+
2129+
/// Returns the induction descriptor for the recipe.
2130+
const InductionDescriptor &getInductionDescriptor() const { return IndDesc; }
2131+
2132+
VPValue *getBackedgeValue() override {
2133+
// TODO: All operands of base recipe must exist and be at same index in
2134+
// derived recipe.
2135+
llvm_unreachable(
2136+
"VPWidenIntOrFpInductionRecipe generates its own backedge value");
2137+
}
2138+
2139+
VPRecipeBase &getBackedgeRecipe() override {
2140+
// TODO: All operands of base recipe must exist and be at same index in
2141+
// derived recipe.
2142+
llvm_unreachable(
2143+
"VPWidenIntOrFpInductionRecipe generates its own backedge value");
2144+
}
2145+
};
2146+
21022147
/// A recipe for handling phi nodes of integer and floating-point inductions,
21032148
/// producing their vector values.
2104-
class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
2105-
PHINode *IV;
2149+
class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe {
21062150
TruncInst *Trunc;
2107-
const InductionDescriptor &IndDesc;
21082151

21092152
public:
21102153
VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step,
21112154
VPValue *VF, const InductionDescriptor &IndDesc,
21122155
DebugLoc DL)
2113-
: VPHeaderPHIRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start, DL),
2114-
IV(IV), Trunc(nullptr), IndDesc(IndDesc) {
2115-
addOperand(Step);
2156+
: VPWidenInductionRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start,
2157+
Step, IndDesc, DL),
2158+
Trunc(nullptr) {
21162159
addOperand(VF);
21172160
}
21182161

21192162
VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step,
21202163
VPValue *VF, const InductionDescriptor &IndDesc,
21212164
TruncInst *Trunc, DebugLoc DL)
2122-
: VPHeaderPHIRecipe(VPDef::VPWidenIntOrFpInductionSC, Trunc, Start, DL),
2123-
IV(IV), Trunc(Trunc), IndDesc(IndDesc) {
2124-
addOperand(Step);
2165+
: VPWidenInductionRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start,
2166+
Step, IndDesc, DL),
2167+
Trunc(Trunc) {
21252168
addOperand(VF);
21262169
}
21272170

21282171
~VPWidenIntOrFpInductionRecipe() override = default;
21292172

21302173
VPWidenIntOrFpInductionRecipe *clone() override {
2131-
return new VPWidenIntOrFpInductionRecipe(IV, getStartValue(),
2132-
getStepValue(), getVFValue(),
2133-
IndDesc, Trunc, getDebugLoc());
2174+
return new VPWidenIntOrFpInductionRecipe(
2175+
getPHINode(), getStartValue(), getStepValue(), getVFValue(),
2176+
getInductionDescriptor(), Trunc, getDebugLoc());
21342177
}
21352178

21362179
VP_CLASSOF_IMPL(VPDef::VPWidenIntOrFpInductionSC)
@@ -2145,24 +2188,6 @@ class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
21452188
VPSlotTracker &SlotTracker) const override;
21462189
#endif
21472190

2148-
VPValue *getBackedgeValue() override {
2149-
// TODO: All operands of base recipe must exist and be at same index in
2150-
// derived recipe.
2151-
llvm_unreachable(
2152-
"VPWidenIntOrFpInductionRecipe generates its own backedge value");
2153-
}
2154-
2155-
VPRecipeBase &getBackedgeRecipe() override {
2156-
// TODO: All operands of base recipe must exist and be at same index in
2157-
// derived recipe.
2158-
llvm_unreachable(
2159-
"VPWidenIntOrFpInductionRecipe generates its own backedge value");
2160-
}
2161-
2162-
/// Returns the step value of the induction.
2163-
VPValue *getStepValue() { return getOperand(1); }
2164-
const VPValue *getStepValue() const { return getOperand(1); }
2165-
21662191
VPValue *getVFValue() { return getOperand(2); }
21672192
const VPValue *getVFValue() const { return getOperand(2); }
21682193

@@ -2177,19 +2202,14 @@ class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
21772202
TruncInst *getTruncInst() { return Trunc; }
21782203
const TruncInst *getTruncInst() const { return Trunc; }
21792204

2180-
PHINode *getPHINode() { return IV; }
2181-
2182-
/// Returns the induction descriptor for the recipe.
2183-
const InductionDescriptor &getInductionDescriptor() const { return IndDesc; }
2184-
21852205
/// Returns true if the induction is canonical, i.e. starting at 0 and
21862206
/// incremented by UF * VF (= the original IV is incremented by 1) and has the
21872207
/// same type as the canonical induction.
21882208
bool isCanonical() const;
21892209

21902210
/// Returns the scalar type of the induction.
21912211
Type *getScalarType() const {
2192-
return Trunc ? Trunc->getType() : IV->getType();
2212+
return Trunc ? Trunc->getType() : getPHINode()->getType();
21932213
}
21942214

21952215
/// Returns the VPValue representing the value of this induction at
@@ -2200,10 +2220,8 @@ class VPWidenIntOrFpInductionRecipe : public VPHeaderPHIRecipe {
22002220
}
22012221
};
22022222

2203-
class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe,
2223+
class VPWidenPointerInductionRecipe : public VPWidenInductionRecipe,
22042224
public VPUnrollPartAccessor<3> {
2205-
const InductionDescriptor &IndDesc;
2206-
22072225
bool IsScalarAfterVectorization;
22082226

22092227
public:
@@ -2212,19 +2230,16 @@ class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe,
22122230
VPWidenPointerInductionRecipe(PHINode *Phi, VPValue *Start, VPValue *Step,
22132231
const InductionDescriptor &IndDesc,
22142232
bool IsScalarAfterVectorization, DebugLoc DL)
2215-
: VPHeaderPHIRecipe(VPDef::VPWidenPointerInductionSC, Phi, nullptr, DL),
2216-
IndDesc(IndDesc),
2217-
IsScalarAfterVectorization(IsScalarAfterVectorization) {
2218-
addOperand(Start);
2219-
addOperand(Step);
2220-
}
2233+
: VPWidenInductionRecipe(VPDef::VPWidenPointerInductionSC, Phi, Start,
2234+
Step, IndDesc, DL),
2235+
IsScalarAfterVectorization(IsScalarAfterVectorization) {}
22212236

22222237
~VPWidenPointerInductionRecipe() override = default;
22232238

22242239
VPWidenPointerInductionRecipe *clone() override {
22252240
return new VPWidenPointerInductionRecipe(
22262241
cast<PHINode>(getUnderlyingInstr()), getOperand(0), getOperand(1),
2227-
IndDesc, IsScalarAfterVectorization, getDebugLoc());
2242+
getInductionDescriptor(), IsScalarAfterVectorization, getDebugLoc());
22282243
}
22292244

22302245
VP_CLASSOF_IMPL(VPDef::VPWidenPointerInductionSC)
@@ -2235,9 +2250,6 @@ class VPWidenPointerInductionRecipe : public VPHeaderPHIRecipe,
22352250
/// Returns true if only scalar values will be generated.
22362251
bool onlyScalarsGenerated(bool IsScalable);
22372252

2238-
/// Returns the induction descriptor for the recipe.
2239-
const InductionDescriptor &getInductionDescriptor() const { return IndDesc; }
2240-
22412253
/// Returns the VPValue representing the value of this induction at
22422254
/// the first unrolled part, if it exists. Returns itself if unrolling did not
22432255
/// take place.

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,12 +1660,13 @@ void VPWidenIntOrFpInductionRecipe::execute(VPTransformState &State) {
16601660
const InductionDescriptor &ID = getInductionDescriptor();
16611661
TruncInst *Trunc = getTruncInst();
16621662
IRBuilderBase &Builder = State.Builder;
1663-
assert(IV->getType() == ID.getStartValue()->getType() && "Types must match");
1663+
assert(getPHINode()->getType() == ID.getStartValue()->getType() &&
1664+
"Types must match");
16641665
assert(State.VF.isVector() && "must have vector VF");
16651666

16661667
// The value from the original loop to which we are mapping the new induction
16671668
// variable.
1668-
Instruction *EntryVal = Trunc ? cast<Instruction>(Trunc) : IV;
1669+
Instruction *EntryVal = Trunc ? cast<Instruction>(Trunc) : getPHINode();
16691670

16701671
// Fast-math-flags propagate from the original induction instruction.
16711672
IRBuilder<>::FastMathFlagGuard FMFG(Builder);
@@ -1755,13 +1756,12 @@ void VPWidenIntOrFpInductionRecipe::execute(VPTransformState &State) {
17551756
void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O, const Twine &Indent,
17561757
VPSlotTracker &SlotTracker) const {
17571758
O << Indent << "WIDEN-INDUCTION";
1758-
if (getTruncInst()) {
1759+
if (auto *TI = getTruncInst()) {
17591760
O << "\\l\"";
1760-
O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\"";
1761-
O << " +\n" << Indent << "\" ";
1762-
getVPValue(0)->printAsOperand(O, SlotTracker);
1761+
O << " +\n" << Indent << "\" " << VPlanIngredient(getPHINode()) << "\\l\"";
1762+
O << " +\n" << Indent << "\" " << VPlanIngredient(TI);
17631763
} else
1764-
O << " " << VPlanIngredient(IV);
1764+
O << " " << VPlanIngredient(getPHINode());
17651765

17661766
O << ", ";
17671767
getStepValue()->printAsOperand(O, SlotTracker);
@@ -3157,7 +3157,8 @@ bool VPWidenPointerInductionRecipe::onlyScalarsGenerated(bool IsScalable) {
31573157
}
31583158

31593159
void VPWidenPointerInductionRecipe::execute(VPTransformState &State) {
3160-
assert(IndDesc.getKind() == InductionDescriptor::IK_PtrInduction &&
3160+
assert(getInductionDescriptor().getKind() ==
3161+
InductionDescriptor::IK_PtrInduction &&
31613162
"Not a pointer induction according to InductionDescriptor!");
31623163
assert(cast<PHINode>(getUnderlyingInstr())->getType()->isPointerTy() &&
31633164
"Unexpected type.");
@@ -3193,8 +3194,8 @@ void VPWidenPointerInductionRecipe::execute(VPTransformState &State) {
31933194

31943195
// A pointer induction, performed by using a gep
31953196
BasicBlock::iterator InductionLoc = State.Builder.GetInsertPoint();
3196-
Value *ScalarStepValue = State.get(getOperand(1), VPLane(0));
3197-
Type *PhiType = State.TypeAnalysis.inferScalarType(getOperand(1));
3197+
Value *ScalarStepValue = State.get(getStepValue(), VPLane(0));
3198+
Type *PhiType = State.TypeAnalysis.inferScalarType(getStepValue());
31983199
Value *RuntimeVF = getRuntimeVF(State.Builder, PhiType, State.VF);
31993200
// Add induction update using an incorrect block temporarily. The phi node
32003201
// will be fixed after VPlan execution. Note that at this point the latch
@@ -3247,7 +3248,7 @@ void VPWidenPointerInductionRecipe::print(raw_ostream &O, const Twine &Indent,
32473248
O << " = WIDEN-POINTER-INDUCTION ";
32483249
getStartValue()->printAsOperand(O, SlotTracker);
32493250
O << ", ";
3250-
getOperand(1)->printAsOperand(O, SlotTracker);
3251+
getStepValue()->printAsOperand(O, SlotTracker);
32513252
if (getNumOperands() == 4) {
32523253
O << ", ";
32533254
getOperand(2)->printAsOperand(O, SlotTracker);

llvm/test/Transforms/LoopVectorize/vplan-printing.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,10 +655,10 @@ define void @print_expand_scev(i64 %y, ptr %ptr) {
655655
; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[CAN_IV_NEXT:%.+]]>
656656
; CHECK-NEXT: WIDEN-INDUCTION\l" +
657657
; CHECK-NEXT: " %iv = phi %iv.next, 0\l" +
658-
; CHECK-NEXT: " ir<%v2>, vp<[[EXP_SCEV]]>, vp<[[VF]]>
658+
; CHECK-NEXT: " %v2 = trunc %iv, vp<[[EXP_SCEV]]>, vp<[[VF]]>
659659
; CHECK-NEXT: vp<[[DERIVED_IV:%.+]]> = DERIVED-IV ir<0> + vp<[[CAN_IV]]> * vp<[[EXP_SCEV]]>
660660
; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[DERIVED_IV]]>, vp<[[EXP_SCEV]]>
661-
; CHECK-NEXT: WIDEN ir<%v3> = add nuw ir<%v2>, ir<1>
661+
; CHECK-NEXT: WIDEN ir<%v3> = add nuw ir<%iv>, ir<1>
662662
; CHECK-NEXT: REPLICATE ir<%gep> = getelementptr inbounds ir<%ptr>, vp<[[STEPS]]>
663663
; CHECK-NEXT: REPLICATE store ir<%v3>, ir<%gep>
664664
; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>

0 commit comments

Comments
 (0)