Skip to content

Commit 6391ca9

Browse files
committed
[VPlan] Don't reset canonical IV start value.
Instead of re-setting the start value of the canonical IV when vectorizing the epilogue we can emit an Add VPInstruction to provide canonical IV value, adjusted by the resume value from the main loop. This is in preparation to make the canonical IV a VPValue defined by loop regions. It ensures that the canonical IV always starts at 0.
1 parent 1d01a84 commit 6391ca9

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9549,13 +9549,12 @@ static SmallVector<Instruction *> preparePlanForEpilogueVectorLoop(
95499549
VPBasicBlock *Header = VectorLoop->getEntryBasicBlock();
95509550
Header->setName("vec.epilog.vector.body");
95519551

9552-
// Ensure that the start values for all header phi recipes are updated before
9553-
// vectorizing the epilogue loop.
95549552
VPCanonicalIVPHIRecipe *IV = Plan.getCanonicalIV();
9555-
// When vectorizing the epilogue loop, the canonical induction start
9556-
// value needs to be changed from zero to the value after the main
9557-
// vector loop. Find the resume value created during execution of the main
9558-
// VPlan. It must be the first phi in the loop preheader.
9553+
// When vectorizing the epilogue loop, the canonical induction needs to be
9554+
// adjusted by the value after the main vector loop. Find the resume value
9555+
// created during execution of the main VPlan. It must be the first phi in the
9556+
// loop preheader. Use the value to increment the canonical IV, and update all
9557+
// users in the loop region to use the adjusted value.
95599558
// FIXME: Improve modeling for canonical IV start values in the epilogue
95609559
// loop.
95619560
using namespace llvm::PatternMatch;
@@ -9590,10 +9589,16 @@ static SmallVector<Instruction *> preparePlanForEpilogueVectorLoop(
95909589
}) &&
95919590
"the canonical IV should only be used by its increment or "
95929591
"ScalarIVSteps when resetting the start value");
9593-
IV->setOperand(0, VPV);
9592+
VPBuilder Builder(Header, Header->getFirstNonPhi());
9593+
VPInstruction *Add = Builder.createNaryOp(Instruction::Add, {IV, VPV});
9594+
IV->replaceAllUsesWith(Add);
9595+
Add->setOperand(0, IV);
95949596

95959597
DenseMap<Value *, Value *> ToFrozen;
95969598
SmallVector<Instruction *> InstsToMove;
9599+
// Ensure that the start values for all header phi recipes are updated before
9600+
// vectorizing the epilogue loop. Skip the canonical IV, which has been
9601+
// handled above.
95979602
for (VPRecipeBase &R : drop_begin(Header->phis())) {
95989603
Value *ResumeV = nullptr;
95999604
// TODO: Move setting of resume values to prepareToExecute.

llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,12 @@ m_c_Binary(const Op0_t &Op0, const Op1_t &Op1) {
431431
return AllRecipe_commutative_match<Opcode, Op0_t, Op1_t>(Op0, Op1);
432432
}
433433

434+
template <typename Op0_t, typename Op1_t>
435+
inline AllRecipe_match<Instruction::Add, Op0_t, Op1_t> m_Add(const Op0_t &Op0,
436+
const Op1_t &Op1) {
437+
return m_Binary<Instruction::Add, Op0_t, Op1_t>(Op0, Op1);
438+
}
439+
434440
template <typename Op0_t, typename Op1_t>
435441
inline AllRecipe_commutative_match<Instruction::Add, Op0_t, Op1_t>
436442
m_c_Add(const Op0_t &Op0, const Op1_t &Op1) {

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,17 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
12341234
if (!Plan->isUnrolled())
12351235
return;
12361236

1237+
if (match(Def, m_Add(m_VPValue(X), m_VPValue(Y))) && Y->isLiveIn() &&
1238+
isa<VPPhi>(X)) {
1239+
auto *Phi = cast<VPPhi>(X);
1240+
if (Phi->getOperand(1) != Def && match(Phi->getOperand(0), m_ZeroInt()) &&
1241+
Phi->getNumUsers() == 1 && (*Phi->user_begin() == &R)) {
1242+
Phi->setOperand(0, Y);
1243+
Def->replaceAllUsesWith(Phi);
1244+
return;
1245+
}
1246+
}
1247+
12371248
// VPVectorPointer for part 0 can be replaced by their start pointer.
12381249
if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(&R)) {
12391250
if (VecPtr->isFirstPart()) {

0 commit comments

Comments
 (0)