Skip to content

Commit f5a5d65

Browse files
fhahnlukel97
authored andcommitted
[VPlan] Add opcode to create step for wide inductions.
This patch adds a WideIVStep opcode that can be used to create a vector with the steps to increment a wide induction. The opcode has 3 operands * the vector step * the scale of the vector step * a constant indicating the target type of the VPInstruction (this is working around having explicit types for VPInstructions, we could also introduce a dedicated recipe, at the cost of a lot more scaffolding) The opcode is later converted into a sequence of recipes that convert the scale and step to the target type, if needed, and then multiply vector step by scale. This simplifies code that needs to materialize step vectors, e.g. replacing wide IVs as follow up to llvm#108378 with an increment of the wide IV step.
1 parent 339fbee commit f5a5d65

File tree

4 files changed

+62
-39
lines changed

4 files changed

+62
-39
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,7 @@ class VPInstruction : public VPRecipeWithIRFlags,
12281228
CalculateTripCountMinusVF,
12291229
// Increment the canonical IV separately for each unrolled part.
12301230
CanonicalIVIncrementForPart,
1231+
WideIVStep,
12311232
BranchOnCount,
12321233
BranchOnCond,
12331234
ComputeReductionResult,

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,8 @@ bool VPInstruction::isFPMathOp() const {
678678
return Opcode == Instruction::FAdd || Opcode == Instruction::FMul ||
679679
Opcode == Instruction::FNeg || Opcode == Instruction::FSub ||
680680
Opcode == Instruction::FDiv || Opcode == Instruction::FRem ||
681-
Opcode == Instruction::FCmp || Opcode == Instruction::Select;
681+
Opcode == Instruction::FCmp || Opcode == Instruction::Select ||
682+
Opcode == VPInstruction::WideIVStep;
682683
}
683684
#endif
684685

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,7 +1962,8 @@ expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR,
19621962
}
19631963

19641964
void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
1965-
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType());
1965+
Type *CanonicalIVType = Plan.getCanonicalIV()->getScalarType();
1966+
VPTypeAnalysis TypeInfo(CanonicalIVType);
19661967

19671968
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
19681969
vp_depth_first_deep(Plan.getEntry()))) {
@@ -1979,23 +1980,61 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
19791980
PointerIVs.push_back(&R);
19801981
for (VPRecipeBase *R : PointerIVs)
19811982
R->moveBefore(*VPBB, VPBB->getFirstNonPhi());
1982-
1983-
for (VPRecipeBase &R : make_early_inc_range(VPBB->phis())) {
1983+
1984+
for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
19841985
if (auto *WidenIVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
19851986
expandVPWidenIntOrFpInduction(WidenIVR, TypeInfo);
19861987
continue;
19871988
}
1988-
if (!isa<VPCanonicalIVPHIRecipe, VPEVLBasedIVPHIRecipe>(&R))
1989+
if (isa<VPCanonicalIVPHIRecipe, VPEVLBasedIVPHIRecipe>(&R)) {
1990+
auto *PhiR = cast<VPHeaderPHIRecipe>(&R);
1991+
StringRef Name =
1992+
isa<VPCanonicalIVPHIRecipe>(PhiR) ? "index" : "evl.based.iv";
1993+
auto *ScalarR = new VPScalarPHIRecipe(PhiR->getStartValue(),
1994+
PhiR->getBackedgeValue(),
1995+
PhiR->getDebugLoc(), Name);
1996+
ScalarR->insertBefore(PhiR);
1997+
PhiR->replaceAllUsesWith(ScalarR);
1998+
PhiR->eraseFromParent();
19891999
continue;
1990-
auto *PhiR = cast<VPHeaderPHIRecipe>(&R);
1991-
StringRef Name =
1992-
isa<VPCanonicalIVPHIRecipe>(PhiR) ? "index" : "evl.based.iv";
1993-
auto *ScalarR =
1994-
new VPScalarPHIRecipe(PhiR->getStartValue(), PhiR->getBackedgeValue(),
1995-
PhiR->getDebugLoc(), Name);
1996-
ScalarR->insertBefore(PhiR);
1997-
PhiR->replaceAllUsesWith(ScalarR);
1998-
PhiR->eraseFromParent();
2000+
}
2001+
2002+
auto *VPI = dyn_cast<VPInstruction>(&R);
2003+
if (VPI && VPI->getOpcode() == VPInstruction::WideIVStep) {
2004+
VPBuilder Builder(VPI->getParent(), VPI->getIterator());
2005+
VPValue *VectorStep = VPI->getOperand(0);
2006+
Type *IVTy = TypeInfo.inferScalarType(VPI->getOperand(2));
2007+
if (TypeInfo.inferScalarType(VectorStep) != IVTy) {
2008+
Instruction::CastOps CastOp = IVTy->isFloatingPointTy()
2009+
? Instruction::UIToFP
2010+
: Instruction::Trunc;
2011+
VectorStep = Builder.createWidenCast(CastOp, VectorStep, IVTy);
2012+
}
2013+
2014+
VPValue *ScalarStep = VPI->getOperand(1);
2015+
auto *ConstStep =
2016+
ScalarStep->isLiveIn()
2017+
? dyn_cast<ConstantInt>(ScalarStep->getLiveInIRValue())
2018+
: nullptr;
2019+
if (!ConstStep || ConstStep->getValue() != 1) {
2020+
if (TypeInfo.inferScalarType(ScalarStep) != IVTy) {
2021+
ScalarStep =
2022+
Builder.createWidenCast(Instruction::Trunc, ScalarStep, IVTy);
2023+
}
2024+
2025+
std::optional<FastMathFlags> FMFs;
2026+
if (IVTy->isFloatingPointTy())
2027+
FMFs = VPI->getFastMathFlags();
2028+
2029+
unsigned MulOpc =
2030+
IVTy->isFloatingPointTy() ? Instruction::FMul : Instruction::Mul;
2031+
VPInstruction *Mul = Builder.createNaryOp(
2032+
MulOpc, {VectorStep, ScalarStep}, FMFs, R.getDebugLoc());
2033+
VectorStep = Mul;
2034+
}
2035+
VPI->replaceAllUsesWith(VectorStep);
2036+
VPI->eraseFromParent();
2037+
}
19992038
}
20002039
}
20012040
}

llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -155,33 +155,15 @@ void UnrollState::unrollWidenInductionByUF(
155155
if (isa_and_present<FPMathOperator>(ID.getInductionBinOp()))
156156
FMFs = ID.getInductionBinOp()->getFastMathFlags();
157157

158-
VPValue *VectorStep = &Plan.getVF();
159-
VPBuilder Builder(PH);
160-
if (TypeInfo.inferScalarType(VectorStep) != IVTy) {
161-
Instruction::CastOps CastOp =
162-
IVTy->isFloatingPointTy() ? Instruction::UIToFP : Instruction::Trunc;
163-
VectorStep = Builder.createWidenCast(CastOp, VectorStep, IVTy);
164-
ToSkip.insert(VectorStep->getDefiningRecipe());
165-
}
166-
167158
VPValue *ScalarStep = IV->getStepValue();
168-
auto *ConstStep = ScalarStep->isLiveIn()
169-
? dyn_cast<ConstantInt>(ScalarStep->getLiveInIRValue())
170-
: nullptr;
171-
if (!ConstStep || ConstStep->getValue() != 1) {
172-
if (TypeInfo.inferScalarType(ScalarStep) != IVTy) {
173-
ScalarStep =
174-
Builder.createWidenCast(Instruction::Trunc, ScalarStep, IVTy);
175-
ToSkip.insert(ScalarStep->getDefiningRecipe());
176-
}
159+
VPBuilder Builder(PH);
160+
VPInstruction *VectorStep =
161+
Builder.createNaryOp(VPInstruction::WideIVStep,
162+
{&Plan.getVF(), ScalarStep,
163+
Plan.getOrAddLiveIn(Constant::getNullValue(IVTy))},
164+
FMFs, IV->getDebugLoc());
177165

178-
unsigned MulOpc =
179-
IVTy->isFloatingPointTy() ? Instruction::FMul : Instruction::Mul;
180-
VPInstruction *Mul = Builder.createNaryOp(MulOpc, {VectorStep, ScalarStep},
181-
FMFs, IV->getDebugLoc());
182-
VectorStep = Mul;
183-
ToSkip.insert(Mul);
184-
}
166+
ToSkip.insert(VectorStep);
185167

186168
// Now create recipes to compute the induction steps for part 1 .. UF. Part 0
187169
// remains the header phi. Parts > 0 are computed by adding Step to the

0 commit comments

Comments
 (0)