[llvm] [VPlan] Explicitly unroll replicate-regions without live-outs by VF. (PR #170212)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 27 03:31:45 PDT 2026


================
@@ -617,43 +653,144 @@ cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy,
       // Skip lane 0: an absent start index is implicitly zero.
       unsigned KnownLane = Lane.getKnownLane();
       if (KnownLane != 0) {
-        VPTypeAnalysis TypeInfo(Plan);
-        Type *BaseIVTy = TypeInfo.inferScalarType(DefR->getOperand(0));
-
-        VPValue *StartIndex = Steps->getStartIndex();
-        VPValue *LaneOffset;
-        unsigned AddOp;
-        VPIRFlags Flags;
-        if (BaseIVTy->isFloatingPointTy()) {
-          int SignedLane = static_cast<int>(KnownLane);
-          if (!StartIndex && Steps->getInductionOpcode() == Instruction::FSub)
-            SignedLane = -SignedLane;
-          LaneOffset =
-              Plan.getOrAddLiveIn(ConstantFP::get(BaseIVTy, SignedLane));
-          AddOp = Steps->getInductionOpcode();
-          Flags = VPIRFlags(FastMathFlags());
-        } else {
-          unsigned BaseIVBits = BaseIVTy->getScalarSizeInBits();
-          LaneOffset = Plan.getConstantInt(APInt(BaseIVBits, KnownLane,
-                                                 /*isSigned*/ false,
-                                                 /*implicitTrunc*/ true));
-          AddOp = Instruction::Add;
-          Flags = VPIRFlags(VPIRFlags::WrapFlagsTy(false, false));
-        }
-
-        if (StartIndex) {
-          VPBuilder LaneBuilder(DefR);
-          LaneOffset =
-              LaneBuilder.createNaryOp(AddOp, {StartIndex, LaneOffset}, Flags);
-        }
-        Steps->setStartIndex(LaneOffset);
+        Steps->insertBefore(DefR);
+        addLaneToStartIndex(Steps, KnownLane, Plan);
+        return New;
       }
     }
   }
   New->insertBefore(DefR);
   return New;
 }
 
+/// Convert recipes in region blocks to operate on a single lane 0.
+/// VPReplicateRecipes are converted to single-scalar ones, branch-on-mask is
+/// converted into BranchOnCond and extracts are created as needed.
+static void convertRecipesInRegionBlocksToSingleScalar(VPlan &Plan, Type *IdxTy,
+                                                       VPBlockBase *Entry) {
+  VPValue *Idx0 = Plan.getZero(IdxTy);
+  for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
+    for (VPRecipeBase &OldR : make_early_inc_range(cast<VPBasicBlock>(*VPB))) {
+      VPBuilder Builder(&OldR);
+      assert(!match(&OldR, m_ExtractElement(m_VPValue(), m_VPValue())) &&
+             "must not contain extracts before conversion");
+      for (const auto &[I, Op] : enumerate(OldR.operands())) {
+        // Skip operands that don't need extraction: values defined in the
+        // same block (already scalar), or values that are already single
+        // scalars.
+        auto *DefR = Op->getDefiningRecipe();
+        if ((DefR && DefR->getParent() == VPB) || vputils::isSingleScalar(Op))
+          continue;
----------------
ayalz wrote:

Hmm, may be missing something here, curious to see an example/test which fails when checking only isSingleScalar, dropping the check for same basic block.

https://github.com/llvm/llvm-project/pull/170212


More information about the llvm-commits mailing list