[llvm] [NFCI][LV] Remove unsupported variable mask position for vector variants. (PR #197192)

Graham Hunter via llvm-commits llvm-commits at lists.llvm.org
Tue May 12 07:03:57 PDT 2026


https://github.com/huntergr-arm updated https://github.com/llvm/llvm-project/pull/197192

>From db57d90308bd9672b8cc6f08da44816415e2f84a Mon Sep 17 00:00:00 2001
From: Graham Hunter <graham.hunter at arm.com>
Date: Tue, 12 May 2026 13:10:17 +0000
Subject: [PATCH 1/2] [NFCI][LV] Remove unsupported variable mask position for
 vector variants.

We only support masks as the last argument of a vector function variant.
Make it official and remove the interface to query the position of the
mask.
---
 llvm/include/llvm/IR/VFABIDemangler.h         | 22 +++++-----------
 llvm/lib/CodeGen/ReplaceWithVeclib.cpp        |  5 ++--
 .../Transforms/Vectorize/LoopVectorize.cpp    | 26 +++++++++----------
 3 files changed, 21 insertions(+), 32 deletions(-)

diff --git a/llvm/include/llvm/IR/VFABIDemangler.h b/llvm/include/llvm/IR/VFABIDemangler.h
index 7576b0f706eb3..aae1808297e00 100644
--- a/llvm/include/llvm/IR/VFABIDemangler.h
+++ b/llvm/include/llvm/IR/VFABIDemangler.h
@@ -128,31 +128,23 @@ struct VFInfo {
   std::string VectorName; /// Vector Function Name associated to this VFInfo.
   VFISAKind ISA;          /// Instruction Set Architecture.
 
-  /// Returns the index of the first parameter with the kind 'GlobalPredicate',
-  /// if any exist.
-  std::optional<unsigned> getParamIndexForOptionalMask() const {
-    unsigned ParamCount = Shape.Parameters.size();
-
+  /// Returns true if the last operand to the vectorized function has the
+  /// kind 'GlobalPredicate'.
+  bool isMasked() const {
+    // There should be at most one GlobalPredicate parameter.
 #ifndef NDEBUG
     unsigned NumMaskParams =
         llvm::count_if(Shape.Parameters, [](const VFParameter &I) {
           return I.ParamKind == VFParamKind::GlobalPredicate;
         });
     assert(NumMaskParams <= 1 && "Unexpected number of mask parameters");
-    assert((!NumMaskParams || Shape.Parameters[ParamCount - 1].ParamKind ==
+    assert((!NumMaskParams || Shape.Parameters.back().ParamKind ==
                                   VFParamKind::GlobalPredicate) &&
            "Mask parameter in unexpected position");
 #endif
-
-    if (!ParamCount || Shape.Parameters[ParamCount - 1].ParamKind !=
-                           VFParamKind::GlobalPredicate)
-      return std::nullopt;
-    return ParamCount - 1;
+    return !Shape.Parameters.empty() &&
+           Shape.Parameters.back().ParamKind == VFParamKind::GlobalPredicate;
   }
-
-  /// Returns true if at least one of the operands to the vectorized function
-  /// has the kind 'GlobalPredicate'.
-  bool isMasked() const { return getParamIndexForOptionalMask().has_value(); }
 };
 
 namespace VFABI {
diff --git a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
index 407d6d503cb10..587bed5f9bc00 100644
--- a/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
+++ b/llvm/lib/CodeGen/ReplaceWithVeclib.cpp
@@ -80,11 +80,10 @@ static void replaceWithTLIFunction(IntrinsicInst *II, VFInfo &Info,
                                    Function *TLIVecFunc) {
   IRBuilder<> IRBuilder(II);
   SmallVector<Value *> Args(II->args());
-  if (auto OptMaskpos = Info.getParamIndexForOptionalMask()) {
+  if (Info.isMasked()) {
     auto *MaskTy =
         VectorType::get(Type::getInt1Ty(II->getContext()), Info.Shape.VF);
-    Args.insert(Args.begin() + OptMaskpos.value(),
-                Constant::getAllOnesValue(MaskTy));
+    Args.push_back(Constant::getAllOnesValue(MaskTy));
   }
 
   // Preserve the operand bundles.
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 61c2d3cd228ec..41bd6ef17edc6 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -994,16 +994,15 @@ class LoopVectorizationCostModel {
     InstWidening Kind;
     Function *Variant;
     Intrinsic::ID IID;
-    std::optional<unsigned> MaskPos;
+    bool RequiresMask;
     InstructionCost Cost;
   };
 
   void setCallWideningDecision(CallInst *CI, ElementCount VF, InstWidening Kind,
                                Function *Variant, Intrinsic::ID IID,
-                               std::optional<unsigned> MaskPos,
-                               InstructionCost Cost) {
+                               bool RequiresMask, InstructionCost Cost) {
     assert(!VF.isScalar() && "Expected vector VF");
-    CallWideningDecisions[{CI, VF}] = {Kind, Variant, IID, MaskPos, Cost};
+    CallWideningDecisions[{CI, VF}] = {Kind, Variant, IID, RequiresMask, Cost};
   }
 
   CallWideningDecision getCallWideningDecision(CallInst *CI,
@@ -1011,7 +1010,7 @@ class LoopVectorizationCostModel {
     assert(!VF.isScalar() && "Expected vector VF");
     auto I = CallWideningDecisions.find({CI, VF});
     if (I == CallWideningDecisions.end())
-      return {CM_Unknown, nullptr, Intrinsic::not_intrinsic, std::nullopt, 0};
+      return {CM_Unknown, nullptr, Intrinsic::not_intrinsic, false, 0};
     return I->second;
   }
 
@@ -4970,8 +4969,7 @@ void LoopVectorizationCostModel::setVectorizedCallDecision(ElementCount VF) {
                              ForcedScalar->second.contains(CI)) ||
                             isUniformAfterVectorization(CI, VF))) {
         setCallWideningDecision(CI, VF, CM_Scalarize, nullptr,
-                                Intrinsic::not_intrinsic, std::nullopt,
-                                ScalarCost);
+                                Intrinsic::not_intrinsic, false, ScalarCost);
         continue;
       }
 
@@ -4986,8 +4984,8 @@ void LoopVectorizationCostModel::setVectorizedCallDecision(ElementCount VF) {
       if (RecurrenceDescriptor::isFMulAddIntrinsic(CI))
         if (auto RedCost = getReductionPatternCost(CI, VF, RetTy)) {
           setCallWideningDecision(CI, VF, CM_IntrinsicCall, nullptr,
-                                  getVectorIntrinsicIDForCall(CI, TLI),
-                                  std::nullopt, *RedCost);
+                                  getVectorIntrinsicIDForCall(CI, TLI), false,
+                                  *RedCost);
           continue;
         }
 
@@ -5073,7 +5071,7 @@ void LoopVectorizationCostModel::setVectorizedCallDecision(ElementCount VF) {
       }
 
       setCallWideningDecision(CI, VF, Decision, VecFunc, IID,
-                              FuncInfo.getParamIndexForOptionalMask(), Cost);
+                              FuncInfo.isMasked(), Cost);
     }
   }
 }
@@ -6464,7 +6462,7 @@ VPSingleDefRecipe *VPRecipeBuilder::tryToWidenCall(VPInstruction *VPI,
                                       VPI->getDebugLoc());
 
   Function *Variant = nullptr;
-  std::optional<unsigned> MaskPos;
+  bool RequiresMask = false;
   // Is better to call a vectorized version of the function than to to scalarize
   // the call?
   auto ShouldUseVectorCall = LoopVectorizationPlanner::getDecisionAndClampRange(
@@ -6487,7 +6485,7 @@ VPSingleDefRecipe *VPRecipeBuilder::tryToWidenCall(VPInstruction *VPI,
             CM.getCallWideningDecision(CI, VF);
         if (Decision.Kind == LoopVectorizationCostModel::CM_VectorCall) {
           Variant = Decision.Variant;
-          MaskPos = Decision.MaskPos;
+          RequiresMask = Decision.RequiresMask;
           return true;
         }
 
@@ -6495,7 +6493,7 @@ VPSingleDefRecipe *VPRecipeBuilder::tryToWidenCall(VPInstruction *VPI,
       },
       Range);
   if (ShouldUseVectorCall) {
-    if (MaskPos.has_value()) {
+    if (RequiresMask) {
       // We have 2 cases that would require a mask:
       //   1) The call needs to be predicated, either due to a conditional
       //      in the scalar loop or use of an active lane mask with
@@ -6505,7 +6503,7 @@ VPSingleDefRecipe *VPRecipeBuilder::tryToWidenCall(VPInstruction *VPI,
       //      synthesize an all-true mask.
       VPValue *Mask = VPI->isMasked() ? VPI->getMask() : Plan.getTrue();
 
-      Ops.insert(Ops.begin() + *MaskPos, Mask);
+      Ops.push_back(Mask);
     }
 
     Ops.push_back(VPI->getOperand(VPI->getNumOperandsWithoutMask() - 1));

>From 431d707f34914a7282f0adbe87c5cd8dc78e4b12 Mon Sep 17 00:00:00 2001
From: Graham Hunter <graham.hunter at arm.com>
Date: Tue, 12 May 2026 13:52:05 +0000
Subject: [PATCH 2/2] Improve assert instead of commenting

---
 llvm/include/llvm/IR/VFABIDemangler.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/include/llvm/IR/VFABIDemangler.h b/llvm/include/llvm/IR/VFABIDemangler.h
index aae1808297e00..33013484fbe43 100644
--- a/llvm/include/llvm/IR/VFABIDemangler.h
+++ b/llvm/include/llvm/IR/VFABIDemangler.h
@@ -131,13 +131,12 @@ struct VFInfo {
   /// Returns true if the last operand to the vectorized function has the
   /// kind 'GlobalPredicate'.
   bool isMasked() const {
-    // There should be at most one GlobalPredicate parameter.
 #ifndef NDEBUG
     unsigned NumMaskParams =
         llvm::count_if(Shape.Parameters, [](const VFParameter &I) {
           return I.ParamKind == VFParamKind::GlobalPredicate;
         });
-    assert(NumMaskParams <= 1 && "Unexpected number of mask parameters");
+    assert(NumMaskParams <= 1 && "Should be at most one mask parameter");
     assert((!NumMaskParams || Shape.Parameters.back().ParamKind ==
                                   VFParamKind::GlobalPredicate) &&
            "Mask parameter in unexpected position");



More information about the llvm-commits mailing list