[llvm] [VPlan] Expand VPWidenIntOrFpInductionRecipe into separate recipes (PR #118638)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Tue May 13 08:55:25 PDT 2025
================
@@ -2390,6 +2380,129 @@ void VPlanTransforms::createInterleaveGroups(
}
}
+/// Expand a VPWidenIntOrFpInduction into executable recipes. for the initial
+/// value, phi and backedge value. In the followng example:
+///
+/// vector.ph:
+/// Successor(s): vector loop
+///
+/// <x1> vector loop: {
+/// vector.body:
+/// WIDEN-INDUCTION %i = phi %start, %step, %vf
+/// ...
+/// EMIT branch-on-count ...
+/// No successors
+/// }
+///
+/// WIDEN-INDUCTION will get expanded to:
+///
+/// vector.ph:
+/// ...
+/// vp<%induction> = ...
+/// vp<%inc> = ...
+///
+/// Successor(s): vector loop
+///
+/// <x1> vector loop: {
+/// vector.body:
+/// ir<%i> = WIDEN-PHI vp<%induction>, vp<%vec.ind.next>
+/// ...
+/// vp<%vec.ind.next> = add ir<%i>, vp<%inc>
+/// EMIT branch-on-count ...
+/// No successors
+/// }
+static void
+expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR,
+ VPTypeAnalysis &TypeInfo) {
+ VPlan *Plan = WidenIVR->getParent()->getPlan();
+ VPValue *Start = WidenIVR->getStartValue();
+ VPValue *Step = WidenIVR->getStepValue();
+ VPValue *VF = WidenIVR->getVFValue();
+ TruncInst *Trunc = WidenIVR->getTruncInst();
+ DebugLoc DL = WidenIVR->getDebugLoc();
+
+ // The value from the original loop to which we are mapping the new induction
+ // variable.
+ Instruction *IV = Trunc ? cast<Instruction>(Trunc) : WidenIVR->getPHINode();
+ Type *Ty = IV->getType();
+
+ const InductionDescriptor &ID = WidenIVR->getInductionDescriptor();
+ Instruction::BinaryOps AddOp;
+ Instruction::BinaryOps MulOp;
+ std::optional<FastMathFlags> FMFs;
+ if (ID.getKind() == InductionDescriptor::IK_IntInduction) {
+ AddOp = Instruction::Add;
+ MulOp = Instruction::Mul;
+ } else {
+ AddOp = ID.getInductionOpcode();
+ MulOp = Instruction::FMul;
+ FMFs = ID.getInductionBinOp()->getFastMathFlags();
+ }
+
+ // If the phi is truncated, truncate the start and step values.
+ VPBuilder Builder(Plan->getVectorPreheader());
+ if (isa<TruncInst>(IV)) {
+ assert(Start->getUnderlyingValue()->getType()->isIntegerTy() &&
+ "Truncation requires an integer type");
+ Step = Builder.createScalarCast(Instruction::Trunc, Step, Ty, DL);
+ Start = Builder.createScalarCast(Instruction::Trunc, Start, Ty, DL);
+ }
+
+ // Construct the initial value of the vector IV in the vector loop preheader.
+ Type *StepTy = TypeInfo.inferScalarType(Step);
+ Type *IVIntTy =
+ IntegerType::get(IV->getContext(), StepTy->getScalarSizeInBits());
+ VPValue *Init = Builder.createNaryOp(VPInstruction::StepVector, {}, IVIntTy);
+ if (StepTy->isFloatingPointTy())
+ Init = Builder.createWidenCast(Instruction::UIToFP, Init, StepTy);
+
+ VPValue *SplatStart = Builder.createNaryOp(VPInstruction::Broadcast, Start);
+ VPValue *SplatStep = Builder.createNaryOp(VPInstruction::Broadcast, Step);
----------------
fhahn wrote:
Could materializeBroadcasts take care of this? I assume there's currently a phase-ordering issue?
https://github.com/llvm/llvm-project/pull/118638
More information about the llvm-commits
mailing list