[llvm] [VPlan] Expand VPWidenIntOrFpInductionRecipe into separate recipes (PR #118638)
Alexey Bataev via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 27 06:24:46 PST 2025
================
@@ -2013,10 +2013,147 @@ void VPlanTransforms::createInterleaveGroups(
}
}
-void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
+/// 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 *IVIntTy = IntegerType::get(IV->getContext(), Ty->getScalarSizeInBits());
+ VPValue *Init = Builder.createStepVector(IVIntTy);
+ if (Ty->isFloatingPointTy())
+ Init = Builder.createWidenCast(Instruction::UIToFP, Init, Ty);
+
+ // FIXME: The newly created binary instructions should contain nsw/nuw
+ // flags, which can be found from the original scalar operations.
+ Init = Builder.createNaryOp(MulOp, {Init, Step}, FMFs);
+ Init = Builder.createNaryOp(AddOp, {Start, Init}, FMFs, {}, "induction");
+
+ // Create the widened phi of the vector IV.
+ auto *WidePHI =
+ new VPWidenPHIRecipe(IV, nullptr, WidenIVR->getDebugLoc(), "vec.ind");
+ WidePHI->addOperand(Init);
+ WidePHI->insertBefore(WidenIVR);
+
+ // Create the backedge value for the vector IV.
+ VPValue *Inc;
+ VPValue *Prev;
+ // If unrolled, use the increment and prev value from the operands.
+ if (WidenIVR->getNumOperands() == 5) {
+ Inc = WidenIVR->getSplatVFValue();
+ Prev = WidenIVR->getLastUnrolledPartOperand();
+ assert(Inc && Prev);
----------------
alexey-bataev wrote:
Add the assertion message
https://github.com/llvm/llvm-project/pull/118638
More information about the llvm-commits
mailing list