Skip to content

Commit 26ae445

Browse files
committed
[VPlan] Expand WidenInt inductions with nuw/nsw
1 parent 6058c0c commit 26ae445

File tree

7 files changed

+48
-22
lines changed

7 files changed

+48
-22
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7543,22 +7543,27 @@ VPRecipeBuilder::tryToWidenMemory(Instruction *I, ArrayRef<VPValue *> Operands,
75437543
static VPWidenIntOrFpInductionRecipe *
75447544
createWidenInductionRecipes(PHINode *Phi, Instruction *PhiOrTrunc,
75457545
VPValue *Start, const InductionDescriptor &IndDesc,
7546-
VPlan &Plan, ScalarEvolution &SE, Loop &OrigLoop) {
7546+
VPlan &Plan, ScalarEvolution &SE, Loop &OrigLoop,
7547+
bool FoldTailByMasking) {
75477548
assert(IndDesc.getStartValue() ==
75487549
Phi->getIncomingValueForBlock(OrigLoop.getLoopPreheader()));
75497550
assert(SE.isLoopInvariant(IndDesc.getStep(), &OrigLoop) &&
75507551
"step must be loop invariant");
75517552

7553+
// When folding tail by masking, we may execute more lanes than the original
7554+
// scalar loop, and should hence not set NoWrap flags.
7555+
VPIRFlags Flags =
7556+
vputils::getNoWrapFlagsFromIndDesc(IndDesc, FoldTailByMasking);
75527557
VPValue *Step =
75537558
vputils::getOrCreateVPValueForSCEVExpr(Plan, IndDesc.getStep());
75547559
if (auto *TruncI = dyn_cast<TruncInst>(PhiOrTrunc)) {
75557560
return new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, &Plan.getVF(),
7556-
IndDesc, TruncI,
7561+
IndDesc, TruncI, Flags,
75577562
TruncI->getDebugLoc());
75587563
}
75597564
assert(isa<PHINode>(PhiOrTrunc) && "must be a phi node here");
75607565
return new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, &Plan.getVF(),
7561-
IndDesc, Phi->getDebugLoc());
7566+
IndDesc, Flags, Phi->getDebugLoc());
75627567
}
75637568

75647569
VPHeaderPHIRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI(
@@ -7568,7 +7573,8 @@ VPHeaderPHIRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI(
75687573
// produces its scalar and vector values.
75697574
if (auto *II = Legal->getIntOrFpInductionDescriptor(Phi))
75707575
return createWidenInductionRecipes(Phi, Phi, Operands[0], *II, Plan,
7571-
*PSE.getSE(), *OrigLoop);
7576+
*PSE.getSE(), *OrigLoop,
7577+
CM.foldTailByMasking());
75727578

75737579
// Check if this is pointer induction. If so, build the recipe for it.
75747580
if (auto *II = Legal->getPointerInductionDescriptor(Phi)) {
@@ -7608,7 +7614,7 @@ VPWidenIntOrFpInductionRecipe *VPRecipeBuilder::tryToOptimizeInductionTruncate(
76087614
const InductionDescriptor &II = *Legal->getIntOrFpInductionDescriptor(Phi);
76097615
VPValue *Start = Plan.getOrAddLiveIn(II.getStartValue());
76107616
return createWidenInductionRecipes(Phi, I, Start, II, Plan, *PSE.getSE(),
7611-
*OrigLoop);
7617+
*OrigLoop, CM.foldTailByMasking());
76127618
}
76137619
return nullptr;
76147620
}
@@ -8499,7 +8505,7 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VFRange &Range) {
84998505
[this](PHINode *P) {
85008506
return Legal->getIntOrFpInductionDescriptor(P);
85018507
},
8502-
*TLI))
8508+
*TLI, CM.foldTailByMasking()))
85038509
return nullptr;
85048510

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

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,7 +2118,8 @@ class VPWidenInductionRecipe : public VPHeaderPHIRecipe {
21182118
/// A recipe for handling phi nodes of integer and floating-point inductions,
21192119
/// producing their vector values. This is an abstract recipe and must be
21202120
/// converted to concrete recipes before executing.
2121-
class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe {
2121+
class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe,
2122+
public VPIRFlags {
21222123
TruncInst *Trunc;
21232124

21242125
// If this recipe is unrolled it will have 2 additional operands.
@@ -2127,19 +2128,20 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe {
21272128
public:
21282129
VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step,
21292130
VPValue *VF, const InductionDescriptor &IndDesc,
2130-
DebugLoc DL)
2131+
const VPIRFlags &Flags, DebugLoc DL)
21312132
: VPWidenInductionRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start,
21322133
Step, IndDesc, DL),
2133-
Trunc(nullptr) {
2134+
VPIRFlags(Flags), Trunc(nullptr) {
21342135
addOperand(VF);
21352136
}
21362137

21372138
VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step,
21382139
VPValue *VF, const InductionDescriptor &IndDesc,
2139-
TruncInst *Trunc, DebugLoc DL)
2140+
TruncInst *Trunc, const VPIRFlags &Flags,
2141+
DebugLoc DL)
21402142
: VPWidenInductionRecipe(VPDef::VPWidenIntOrFpInductionSC, IV, Start,
21412143
Step, IndDesc, DL),
2142-
Trunc(Trunc) {
2144+
VPIRFlags(Flags), Trunc(Trunc) {
21432145
addOperand(VF);
21442146
SmallVector<std::pair<unsigned, MDNode *>> Metadata;
21452147
(void)Metadata;
@@ -2153,7 +2155,7 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe {
21532155
VPWidenIntOrFpInductionRecipe *clone() override {
21542156
return new VPWidenIntOrFpInductionRecipe(
21552157
getPHINode(), getStartValue(), getStepValue(), getVFValue(),
2156-
getInductionDescriptor(), Trunc, getDebugLoc());
2158+
getInductionDescriptor(), Trunc, *this, getDebugLoc());
21572159
}
21582160

21592161
VP_CLASSOF_IMPL(VPDef::VPWidenIntOrFpInductionSC)

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
4848
VPlan &Plan,
4949
function_ref<const InductionDescriptor *(PHINode *)>
5050
GetIntOrFpInductionDescriptor,
51-
const TargetLibraryInfo &TLI) {
51+
const TargetLibraryInfo &TLI, bool FoldTailByMasking) {
5252

5353
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
5454
Plan.getVectorLoopRegion());
@@ -80,8 +80,13 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
8080
VPValue *Start = Plan.getOrAddLiveIn(II->getStartValue());
8181
VPValue *Step =
8282
vputils::getOrCreateVPValueForSCEVExpr(Plan, II->getStep());
83+
// When folding tail by masking, we may execute more lanes than the
84+
// original scalar loop, and should hence not set NoWrap flags.
85+
VPIRFlags Flags =
86+
vputils::getNoWrapFlagsFromIndDesc(*II, FoldTailByMasking);
8387
NewRecipe = new VPWidenIntOrFpInductionRecipe(
84-
Phi, Start, Step, &Plan.getVF(), *II, Ingredient.getDebugLoc());
88+
Phi, Start, Step, &Plan.getVF(), *II, Flags,
89+
Ingredient.getDebugLoc());
8590
}
8691
} else {
8792
assert(isa<VPInstruction>(&Ingredient) &&
@@ -3199,16 +3204,13 @@ expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR,
31993204
const InductionDescriptor &ID = WidenIVR->getInductionDescriptor();
32003205
Instruction::BinaryOps AddOp;
32013206
Instruction::BinaryOps MulOp;
3202-
// FIXME: The newly created binary instructions should contain nsw/nuw
3203-
// flags, which can be found from the original scalar operations.
3204-
VPIRFlags Flags;
3207+
VPIRFlags Flags = *WidenIVR;
32053208
if (ID.getKind() == InductionDescriptor::IK_IntInduction) {
32063209
AddOp = Instruction::Add;
32073210
MulOp = Instruction::Mul;
32083211
} else {
32093212
AddOp = ID.getInductionOpcode();
32103213
MulOp = Instruction::FMul;
3211-
Flags = ID.getInductionBinOp()->getFastMathFlags();
32123214
}
32133215

32143216
// If the phi is truncated, truncate the start and step values.

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ struct VPlanTransforms {
141141
VPlan &Plan,
142142
function_ref<const InductionDescriptor *(PHINode *)>
143143
GetIntOrFpInductionDescriptor,
144-
const TargetLibraryInfo &TLI);
144+
const TargetLibraryInfo &TLI, bool FoldTailByMasking);
145145

146146
/// Try to have all users of fixed-order recurrences appear after the recipe
147147
/// defining their previous value, by either sinking users or hoisting recipes

llvm/lib/Transforms/Vectorize/VPlanUtils.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ std::optional<VPValue *>
122122
getRecipesForUncountableExit(VPlan &Plan,
123123
SmallVectorImpl<VPRecipeBase *> &Recipes,
124124
SmallVectorImpl<VPRecipeBase *> &GEPs);
125+
126+
/// Extracts and returns nowrap flags from the induction binop in \p ID. \p
127+
/// DropNWFlags tells us whether whether we should drop NoWrap flags, which we
128+
/// should when tail-folding, for example.
129+
inline VPIRFlags getNoWrapFlagsFromIndDesc(const InductionDescriptor &ID,
130+
bool DropNWFlags) {
131+
if (ID.getKind() == InductionDescriptor::IK_FpInduction)
132+
return ID.getInductionBinOp()->getFastMathFlags();
133+
134+
if (auto *OBO = dyn_cast_if_present<OverflowingBinaryOperator>(
135+
ID.getInductionBinOp()))
136+
return DropNWFlags ? VPIRFlags::WrapFlagsTy(false, false)
137+
: VPIRFlags::WrapFlagsTy(OBO->hasNoUnsignedWrap(),
138+
OBO->hasNoSignedWrap());
139+
return {};
140+
}
125141
} // namespace vputils
126142

127143
//===----------------------------------------------------------------------===//

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; }, TLI);
206+
*Plan, [](PHINode *P) { return nullptr; }, TLI, false);
207207

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

llvm/unittests/Transforms/Vectorize/VPlanUncountableExitTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ TEST_F(VPUncountableExitTest, FindUncountableExitRecipes) {
4848
BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
4949
auto Plan = buildVPlan(LoopHeader, /*HasUncountableExit=*/true);
5050
VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
51-
*Plan, [](PHINode *P) { return nullptr; }, *TLI);
51+
*Plan, [](PHINode *P) { return nullptr; }, *TLI, false);
5252
VPlanTransforms::runPass(VPlanTransforms::optimize, *Plan);
5353

5454
SmallVector<VPRecipeBase *> Recipes;
@@ -85,7 +85,7 @@ TEST_F(VPUncountableExitTest, NoUncountableExit) {
8585
BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
8686
auto Plan = buildVPlan(LoopHeader);
8787
VPlanTransforms::tryToConvertVPInstructionsToVPRecipes(
88-
*Plan, [](PHINode *P) { return nullptr; }, *TLI);
88+
*Plan, [](PHINode *P) { return nullptr; }, *TLI, false);
8989
VPlanTransforms::runPass(VPlanTransforms::optimize, *Plan);
9090

9191
SmallVector<VPRecipeBase *> Recipes;

0 commit comments

Comments
 (0)