[PATCH] D121615: [VPlan] Add VPWidenPointerInductionRecipe.

Ayal Zaks via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 16 00:23:55 PDT 2022


Ayal accepted this revision.
Ayal added a comment.
This revision is now accepted and ready to land.

Nice clean-up, effectively retiring ILV's widenPHIInstruction(), completing its refactoring into more specific recipes.
Adding various nits.



================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:494
   /// a block. This method handles the induction variable canonicalization. It
   /// supports both VF = 1 for unrolled loops and arbitrary length vectors.
   void widenPHIInstruction(Instruction *PN, VPWidenPHIRecipe *PhiR,
----------------
Above comment needs updating.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:4233
   }
-
-  assert(PN->getParent() == OrigLoop->getHeader() &&
-         "Non-header phis should have been handled elsewhere");
-
-  // In order to support recurrences we need to be able to vectorize Phi nodes.
-  // Phi nodes have cycles, so we need to vectorize them in two stages. This is
-  // stage #1: We create a new vector PHI node with no incoming edges. We'll use
-  // this value when we vectorize all of the instructions that use the PHI.
-
-  assert(!Legal->isReductionVariable(P) &&
-         "reductions should be handled elsewhere");
-
-  setDebugLocFromInst(P);
-
-  // This PHINode must be an induction variable.
-  // Make sure that we know about it.
-  assert(Legal->getInductionVars().count(P) && "Not an induction variable");
-
-  InductionDescriptor II = Legal->getInductionVars().lookup(P);
-  const DataLayout &DL = OrigLoop->getHeader()->getModule()->getDataLayout();
-
-  auto *IVR = PhiR->getParent()->getPlan()->getCanonicalIV();
-  PHINode *CanonicalIV = cast<PHINode>(State.get(IVR, 0));
-
-  // FIXME: The newly created binary instructions should contain nsw/nuw flags,
-  // which can be found from the original scalar operations.
-  switch (II.getKind()) {
-  case InductionDescriptor::IK_NoInduction:
-    llvm_unreachable("Unknown induction");
-  case InductionDescriptor::IK_IntInduction:
-  case InductionDescriptor::IK_FpInduction:
-    llvm_unreachable("Integer/fp induction is handled elsewhere.");
-  case InductionDescriptor::IK_PtrInduction: {
-    // Handle the pointer induction variable case.
-    assert(P->getType()->isPointerTy() && "Unexpected type.");
-
-    if (all_of(PhiR->users(), [PhiR](const VPUser *U) {
-          return cast<VPRecipeBase>(U)->usesScalars(PhiR);
-        })) {
-      // This is the normalized GEP that starts counting at zero.
-      Value *PtrInd =
-          Builder.CreateSExtOrTrunc(CanonicalIV, II.getStep()->getType());
-      // Determine the number of scalars we need to generate for each unroll
-      // iteration. If the instruction is uniform, we only need to generate the
-      // first lane. Otherwise, we generate all VF values.
-      bool IsUniform = vputils::onlyFirstLaneUsed(PhiR);
-      assert((IsUniform || !State.VF.isScalable()) &&
-             "Cannot scalarize a scalable VF");
-      unsigned Lanes = IsUniform ? 1 : State.VF.getFixedValue();
-
-      for (unsigned Part = 0; Part < UF; ++Part) {
-        Value *PartStart =
-            createStepForVF(Builder, PtrInd->getType(), VF, Part);
-
-        for (unsigned Lane = 0; Lane < Lanes; ++Lane) {
-          Value *Idx = Builder.CreateAdd(
-              PartStart, ConstantInt::get(PtrInd->getType(), Lane));
-          Value *GlobalIdx = Builder.CreateAdd(PtrInd, Idx);
-
-          Value *Step = CreateStepValue(II.getStep(), *PSE.getSE(),
-                                        State.CFG.PrevBB->getTerminator());
-          Value *SclrGep = emitTransformedIndex(Builder, GlobalIdx,
-                                                II.getStartValue(), Step, II);
-          SclrGep->setName("next.gep");
-          State.set(PhiR, SclrGep, VPIteration(Part, Lane));
-        }
-      }
-      return;
-    }
-    assert(isa<SCEVConstant>(II.getStep()) &&
-           "Induction step not a SCEV constant!");
-    Type *PhiType = II.getStep()->getType();
-
-    // Build a pointer phi
-    Value *ScalarStartValue = PhiR->getStartValue()->getLiveInIRValue();
-    Type *ScStValueType = ScalarStartValue->getType();
-    PHINode *NewPointerPhi =
-        PHINode::Create(ScStValueType, 2, "pointer.phi", CanonicalIV);
-    NewPointerPhi->addIncoming(ScalarStartValue, LoopVectorPreHeader);
-
-    // A pointer induction, performed by using a gep
-    BasicBlock *LoopLatch = LI->getLoopFor(State.CFG.PrevBB)->getLoopLatch();
-    Instruction *InductionLoc = LoopLatch->getTerminator();
-    const SCEV *ScalarStep = II.getStep();
-    SCEVExpander Exp(*PSE.getSE(), DL, "induction");
-    Value *ScalarStepValue =
-        Exp.expandCodeFor(ScalarStep, PhiType, InductionLoc);
-    Value *RuntimeVF = getRuntimeVF(Builder, PhiType, VF);
-    Value *NumUnrolledElems =
-        Builder.CreateMul(RuntimeVF, ConstantInt::get(PhiType, State.UF));
-    Value *InductionGEP = GetElementPtrInst::Create(
-        II.getElementType(), NewPointerPhi,
-        Builder.CreateMul(ScalarStepValue, NumUnrolledElems), "ptr.ind",
-        InductionLoc);
-    NewPointerPhi->addIncoming(InductionGEP, LoopLatch);
-
-    // Create UF many actual address geps that use the pointer
-    // phi as base and a vectorized version of the step value
-    // (<step*0, ..., step*N>) as offset.
-    for (unsigned Part = 0; Part < State.UF; ++Part) {
-      Type *VecPhiType = VectorType::get(PhiType, State.VF);
-      Value *StartOffsetScalar =
-          Builder.CreateMul(RuntimeVF, ConstantInt::get(PhiType, Part));
-      Value *StartOffset =
-          Builder.CreateVectorSplat(State.VF, StartOffsetScalar);
-      // Create a vector of consecutive numbers from zero to VF.
-      StartOffset =
-          Builder.CreateAdd(StartOffset, Builder.CreateStepVector(VecPhiType));
-
-      Value *GEP = Builder.CreateGEP(
-          II.getElementType(), NewPointerPhi,
-          Builder.CreateMul(
-              StartOffset, Builder.CreateVectorSplat(State.VF, ScalarStepValue),
-              "vector.gep"));
-      State.set(PhiR, GEP, Part);
-    }
-  }
-  }
+  llvm_unreachable(
+      "Non-native vplans are not expected to have VPWidenPHIRecipes.");
----------------
assert(EnableVPlanNativePath && "...") at the outset?


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8213
 
-VPWidenIntOrFpInductionRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI(
+VPRecipeBase *VPRecipeBuilder::tryToOptimizeInductionPHI(
     PHINode *Phi, ArrayRef<VPValue *> Operands, VFRange &Range) const {
----------------
Return a pointer to VPHeaderPhiRecipe ?


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8217
   // Check if this is an integer or fp induction. If so, build the recipe that
   // produces its scalar and vector values.
   if (auto *II = Legal->getIntOrFpInductionDescriptor(Phi))
----------------
Can augment the comment to also mention pointer induction.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:8223
+  auto I = Legal->getInductionVars().find(Phi);
+  if (I != Legal->getInductionVars().end())
+    return new VPWidenPointerInductionRecipe(Phi, Operands[0], I->second,
----------------
Fold into Legal->getPointerInductionDescriptor(Phi)?


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:9543
+void VPWidenPointerInductionRecipe::execute(VPTransformState &State) {
+  assert(IndDesc.getKind() == InductionDescriptor::IK_PtrInduction);
+
----------------
Add message to assert.


================
Comment at: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:9604
+  SCEVExpander Exp(SE, DL, "induction");
+  Value *ScalarStepValue = Exp.expandCodeFor(ScalarStep, PhiType, InductionLoc);
+  Value *RuntimeVF = getRuntimeVF(State.Builder, PhiType, State.VF);
----------------
Should this be refactored out into a SCEV expand recipe (in a follow-up patch)?


================
Comment at: llvm/lib/Transforms/Vectorize/VPlan.cpp:1285
+  O << " = WIDEN-POINTER-INDUCTION ";
+  getOperand(0)->printAsOperand(O, SlotTracker);
+  O << ", ";
----------------
getStartValue()?


================
Comment at: llvm/lib/Transforms/Vectorize/VPlan.cpp:1287
+  O << ", ";
+  O << *IndDesc.getStep();
+}
----------------
Can fold on one line.


================
Comment at: llvm/lib/Transforms/Vectorize/VPlan.h:1213
+public:
+  /// Create a new VPWidenPHIRecipe for \p Phi with start value \p Start.
+  VPWidenPointerInductionRecipe(PHINode *Phi, VPValue *Start,
----------------
Comment needs updating.


================
Comment at: llvm/lib/Transforms/Vectorize/VPlan.h:1236
+
+  /// Generate
+  void execute(VPTransformState &State) override;
----------------
Comment needs completion.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121615/new/

https://reviews.llvm.org/D121615



More information about the llvm-commits mailing list