[llvm] [VPlan] Introduce vputils::getSingleScalarClone (PR #161667)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 02:53:56 PST 2025


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/161667

>From 888245f1413e3ab2f6c3901f3d5661fc694a61f5 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Thu, 2 Oct 2025 14:21:01 +0100
Subject: [PATCH] [VPlan] Introduce vputils::getSingleScalarClone

---
 .../Transforms/Vectorize/VPlanTransforms.cpp  | 25 +++------------
 llvm/lib/Transforms/Vectorize/VPlanUtils.cpp  | 32 +++++++++++++++++++
 llvm/lib/Transforms/Vectorize/VPlanUtils.h    |  4 +++
 3 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index b3ba38f6c630e..330c231aa5837 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -272,20 +272,7 @@ static bool sinkScalarOperands(VPlan &Plan) {
     if (NeedsDuplicating) {
       if (ScalarVFOnly)
         continue;
-      VPSingleDefRecipe *Clone;
-      if (auto *SinkCandidateRepR =
-              dyn_cast<VPReplicateRecipe>(SinkCandidate)) {
-        // TODO: Handle converting to uniform recipes as separate transform,
-        // then cloning should be sufficient here.
-        Instruction *I = SinkCandidate->getUnderlyingInstr();
-        Clone = new VPReplicateRecipe(I, SinkCandidate->operands(), true,
-                                      nullptr /*Mask*/, *SinkCandidateRepR,
-                                      *SinkCandidateRepR);
-        // TODO: add ".cloned" suffix to name of Clone's VPValue.
-      } else {
-        Clone = SinkCandidate->clone();
-      }
-
+      VPSingleDefRecipe *Clone = vputils::getSingleScalarClone(SinkCandidate);
       Clone->insertBefore(SinkCandidate);
       SinkCandidate->replaceUsesWithIf(Clone, [SinkTo](VPUser &U, unsigned) {
         return cast<VPRecipeBase>(&U)->getParent() != SinkTo;
@@ -1506,10 +1493,8 @@ static void narrowToSingleScalarRecipes(VPlan &Plan) {
       auto *RepOrWidenR = cast<VPRecipeWithIRFlags>(&R);
       if (RepR && isa<StoreInst>(RepR->getUnderlyingInstr()) &&
           vputils::isSingleScalar(RepR->getOperand(1))) {
-        auto *Clone = new VPReplicateRecipe(
-            RepOrWidenR->getUnderlyingInstr(), RepOrWidenR->operands(),
-            true /*IsSingleScalar*/, nullptr /*Mask*/, *RepR /*Flags*/,
-            *RepR /*Metadata*/, RepR->getDebugLoc());
+        auto *Clone =
+            cast<VPReplicateRecipe>(vputils::getSingleScalarClone(RepOrWidenR));
         Clone->insertBefore(RepOrWidenR);
         unsigned ExtractOpc =
             vputils::isUniformAcrossVFsAndUFs(RepR->getOperand(1))
@@ -1558,9 +1543,7 @@ static void narrowToSingleScalarRecipes(VPlan &Plan) {
           }))
         continue;
 
-      auto *Clone = new VPReplicateRecipe(
-          RepOrWidenR->getUnderlyingInstr(), RepOrWidenR->operands(),
-          true /*IsSingleScalar*/, nullptr, *RepOrWidenR);
+      VPSingleDefRecipe *Clone = vputils::getSingleScalarClone(RepOrWidenR);
       Clone->insertBefore(RepOrWidenR);
       RepOrWidenR->replaceAllUsesWith(Clone);
       if (isDeadRecipe(*RepOrWidenR))
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
index d36975699c4a8..1b70effd1d43e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
@@ -378,6 +378,38 @@ vputils::getRecipesForUncountableExit(VPlan &Plan,
   return UncountableCondition;
 }
 
+VPSingleDefRecipe *vputils::getSingleScalarClone(VPSingleDefRecipe *R) {
+  return TypeSwitch<VPSingleDefRecipe *, VPSingleDefRecipe *>(R)
+      .Case<VPInstruction, VPWidenRecipe, VPWidenSelectRecipe,
+            VPWidenCallRecipe, VPReplicateRecipe>([](auto *I) {
+        assert(I->getUnderlyingValue() &&
+               "Cannot clone recipe without underlying value");
+        return new VPReplicateRecipe(I->getUnderlyingInstr(), I->operands(),
+                                     /*IsSingleScalar*/ true,
+                                     /*Mask*/ nullptr, /*Flags*/ *I,
+                                     /*Metadata*/ *I, I->getDebugLoc());
+      })
+      .Case<VPWidenGEPRecipe>([](auto *I) {
+        assert(I->getUnderlyingValue() &&
+               "Cannot clone recipe without underlying value");
+        // WidenGEP does not have metadata.
+        return new VPReplicateRecipe(I->getUnderlyingInstr(), I->operands(),
+                                     /*IsSingleScalar*/ true, /*Mask*/ nullptr,
+                                     /*Flags*/ *I, /*Metadata*/ {},
+                                     I->getDebugLoc());
+      })
+      .Case<VPWidenCastRecipe>([](auto *I) {
+        return new VPInstructionWithType(
+            I->getOpcode(), I->operands(), I->getResultType(),
+            /*Flags*/ *I, /*Metadata*/ *I, I->getDebugLoc());
+      })
+      .Default([](auto *I) {
+        assert(isa<VPScalarIVStepsRecipe>(I) &&
+               "Don't know how to convert to single-scalar");
+        return I->clone();
+      });
+}
+
 bool VPBlockUtils::isHeader(const VPBlockBase *VPB,
                             const VPDominatorTree &VPDT) {
   auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.h b/llvm/lib/Transforms/Vectorize/VPlanUtils.h
index 6f74a99f3738e..59d56f14852cb 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.h
@@ -95,6 +95,10 @@ inline VPIRFlags getFlagsFromIndDesc(const InductionDescriptor &ID) {
          "Expected int induction");
   return VPIRFlags::WrapFlagsTy(false, false);
 }
+
+/// Returns a single-scalar version of \p R, creating a fresh single-scalar
+/// VPReplicateRecipe or just cloning the recipe.
+VPSingleDefRecipe *getSingleScalarClone(VPSingleDefRecipe *R);
 } // namespace vputils
 
 //===----------------------------------------------------------------------===//



More information about the llvm-commits mailing list