[llvm] [VPlan] Expand VPWidenIntOrFpInductionRecipe into separate recipes (PR #118638)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 17 07:45:55 PDT 2025
================
@@ -2518,6 +2507,128 @@ void VPlanTransforms::createInterleaveGroups(
}
}
+/// Expand a VPWidenIntOrFpInduction into executable recipes, for the initial
+/// value, phi and backedge value. In the following 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.start> = ...
+/// vp<%induction.increment> = ...
+///
+/// Successor(s): vector loop
+///
+/// <x1> vector loop: {
+/// vector.body:
+/// ir<%i> = WIDEN-PHI vp<%induction.start>, vp<%vec.ind.next>
+/// ...
+/// vp<%vec.ind.next> = add ir<%i>, vp<%induction.increment>
+/// 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();
+ DebugLoc DL = WidenIVR->getDebugLoc();
+
+ // The value from the original loop to which we are mapping the new induction
+ // variable.
+ Type *Ty = TypeInfo.inferScalarType(WidenIVR);
+
+ const InductionDescriptor &ID = WidenIVR->getInductionDescriptor();
+ Instruction::BinaryOps AddOp;
+ Instruction::BinaryOps MulOp;
+ VPIRFlags Flags;
+ if (ID.getKind() == InductionDescriptor::IK_IntInduction) {
+ AddOp = Instruction::Add;
+ MulOp = Instruction::Mul;
+ } else {
+ AddOp = ID.getInductionOpcode();
+ MulOp = Instruction::FMul;
+ Flags = ID.getInductionBinOp()->getFastMathFlags();
+ }
+
+ // If the phi is truncated, truncate the start and step values.
+ VPBuilder Builder(Plan->getVectorPreheader());
+ Type *StepTy = TypeInfo.inferScalarType(Step);
+ if (Ty->getScalarSizeInBits() < StepTy->getScalarSizeInBits()) {
+ assert(StepTy->isIntegerTy() && "Truncation requires an integer type");
+ Step = Builder.createScalarCast(Instruction::Trunc, Step, Ty, DL);
+ Start = Builder.createScalarCast(Instruction::Trunc, Start, Ty, DL);
+ StepTy = Ty;
+ }
+
+ // Construct the initial value of the vector IV in the vector loop preheader.
+ Type *IVIntTy =
+ IntegerType::get(StepTy->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);
+
+ // FIXME: The newly created binary instructions should contain nsw/nuw
+ // flags, which can be found from the original scalar operations.
----------------
fhahn wrote:
Fixme better moved to where `Flags` is defined?
https://github.com/llvm/llvm-project/pull/118638
More information about the llvm-commits
mailing list