[llvm] Refactor try demangle for vfabi to use only the vector abi mangled names (PR #67430)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 6 04:42:51 PDT 2023


https://github.com/JolantaJensen updated https://github.com/llvm/llvm-project/pull/67430

>From 5edf4127c14f8c696bed4d5e2fd728de02791a16 Mon Sep 17 00:00:00 2001
From: Jolanta Jensen <Jolanta.Jensen at arm.com>
Date: Tue, 26 Sep 2023 13:13:08 +0000
Subject: [PATCH 1/3] [VFABI] Refactor tryDemangleForVFABI to use only the
 Vector ABI mangled names         and the call's argument types to construct
 the VFInfo.

Currently the tryDemangleForVFABI is incorrectly making assumptions that when
the mangled name has __LLVM__ set as ISA and _vlen_ is set to scalable/VLA
the module can be queried to identify the correct VF. This works currently only
by chance rather than by design and limits the ability to maximise the use for
the Vector ABI. This behaviour is changed by
https://github.com/llvm/llvm-project/pull/66656 and
https://github.com/llvm/llvm-project/pull/67308
and means demangling can be implemented as expected based solely on the rules
as documented within the VFABI.
---
 llvm/include/llvm/Analysis/VectorUtils.h      | 13 ++++----
 llvm/lib/Analysis/VFABIDemangling.cpp         | 33 ++++++++++++-------
 llvm/lib/Analysis/VectorUtils.cpp             |  6 ++--
 llvm/lib/Transforms/Utils/ModuleUtils.cpp     |  6 +++-
 .../LoopVectorize/AArch64/masked-call.ll      |  8 ++---
 .../LoopVectorize/AArch64/scalable-call.ll    |  6 ++--
 .../vfabi-demangler-fuzzer.cpp                | 20 ++++++-----
 .../Analysis/VectorFunctionABITest.cpp        | 21 ++++++------
 8 files changed, 66 insertions(+), 47 deletions(-)

diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index 7947648aaddd4ea..bb612ae041c138d 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -174,13 +174,9 @@ static constexpr char const *_LLVM_Scalarize_ = "_LLVM_Scalarize_";
 ///
 /// \param MangledName -> input string in the format
 /// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
-/// \param M -> Module used to retrieve informations about the vector
-/// function that are not possible to retrieve from the mangled
-/// name. At the moment, this parameter is needed only to retrieve the
-/// Vectorization Factor of scalable vector functions from their
-/// respective IR declarations.
+/// \param OpTys -> the instruction operand types.
 std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
-                                          const Module &M);
+                                          SmallVector<Type *> OpTys);
 
 /// Retrieve the `VFParamKind` from a string token.
 VFParamKind getVFParamKindFromString(const StringRef Token);
@@ -226,8 +222,11 @@ class VFDatabase {
     if (ListOfStrings.empty())
       return;
     for (const auto &MangledName : ListOfStrings) {
+      SmallVector<Type *> OpTys;
+      for (Value *Op : CI.operands())
+        OpTys.push_back(Op->getType());
       const std::optional<VFInfo> Shape =
-          VFABI::tryDemangleForVFABI(MangledName, *(CI.getModule()));
+          VFABI::tryDemangleForVFABI(MangledName, OpTys);
       // A match is found via scalar and vector names, and also by
       // ensuring that the variant described in the attribute has a
       // corresponding definition or declaration of the vector
diff --git a/llvm/lib/Analysis/VFABIDemangling.cpp b/llvm/lib/Analysis/VFABIDemangling.cpp
index 1e2d1db4e44b9d6..7a3c8c3bcc72fbe 100644
--- a/llvm/lib/Analysis/VFABIDemangling.cpp
+++ b/llvm/lib/Analysis/VFABIDemangling.cpp
@@ -315,7 +315,7 @@ ElementCount getECFromSignature(FunctionType *Signature) {
 // Format of the ABI name:
 // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
 std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
-                                                 const Module &M) {
+                                                 SmallVector<Type *> OpTys) {
   const StringRef OriginalName = MangledName;
   // Assume there is no custom name <redirection>, and therefore the
   // vector name consists of
@@ -434,22 +434,33 @@ std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
   // need to make sure that the VF field of the VFShape class is never
   // set to 0.
   if (IsScalable) {
-    const Function *F = M.getFunction(VectorName);
-    // The declaration of the function must be present in the module
-    // to be able to retrieve its signature.
-    if (!F)
+    if (ISA != VFISAKind::SVE)
       return std::nullopt;
-    const ElementCount EC = getECFromSignature(F->getFunctionType());
-    VF = EC.getKnownMinValue();
+    if (OpTys.empty())
+      return std::nullopt;
+    switch (OpTys[0]->getScalarSizeInBits()) {
+    case 64:
+      VF = 2;
+      break;
+    case 32:
+      VF = 4;
+      break;
+    case 0: {
+      if (OpTys[0]->isPointerTy())
+        VF = 2;
+      else
+        VF = 0;
+      break;
+    }
+    default:
+      VF = 0;
+      break;
+    }
   }
 
   // 1. We don't accept a zero lanes vectorization factor.
-  // 2. We don't accept the demangling if the vector function is not
-  // present in the module.
   if (VF == 0)
     return std::nullopt;
-  if (!M.getFunction(VectorName))
-    return std::nullopt;
 
   const VFShape Shape({ElementCount::get(VF, IsScalable), Parameters});
   return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA});
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 9893e23468e177d..6936dd1bd4db5f8 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1464,9 +1464,11 @@ void VFABI::getVectorVariantNames(
 
   for (const auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) {
 #ifndef NDEBUG
+    SmallVector<Type *> OpTys;
+    for (Value *Op : CI.operands())
+      OpTys.push_back(Op->getType());
     LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << S << "'\n");
-    std::optional<VFInfo> Info =
-        VFABI::tryDemangleForVFABI(S, *(CI.getModule()));
+    std::optional<VFInfo> Info = VFABI::tryDemangleForVFABI(S, OpTys);
     assert(Info && "Invalid name for a VFABI variant.");
     assert(CI.getModule()->getFunction(Info->VectorName) &&
            "Vector function is missing.");
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 1e243ef74df7fd6..6da3882875583fa 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -345,8 +345,12 @@ void VFABI::setVectorVariantNames(CallInst *CI,
   Module *M = CI->getModule();
 #ifndef NDEBUG
   for (const std::string &VariantMapping : VariantMappings) {
+    SmallVector<Type *> OpTys;
+    for (Value *Op : CI->operands())
+      OpTys.push_back(Op->getType());
     LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");
-    std::optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping, *M);
+    std::optional<VFInfo> VI =
+        VFABI::tryDemangleForVFABI(VariantMapping, OpTys);
     assert(VI && "Cannot add an invalid VFABI name.");
     assert(M->getNamedValue(VI->VectorName) &&
            "Cannot add variant to attribute: "
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll
index 904dcd4fed30e15..3a0a9a075619289 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll
@@ -862,8 +862,8 @@ declare <vscale x 2 x i64> @foo_uniform(i64, <vscale x 2 x i1>)
 declare <vscale x 2 x i64> @foo_vector(<vscale x 2 x i64>, <vscale x 2 x i1>)
 declare <vscale x 2 x i64> @foo_vector_nomask(<vscale x 2 x i64>)
 
-attributes #0 = { nounwind "vector-function-abi-variant"="_ZGV_LLVM_Mxv_foo(foo_vector),_ZGV_LLVM_Mxu_foo(foo_uniform)" }
-attributes #1 = { nounwind "vector-function-abi-variant"="_ZGV_LLVM_Mxv_foo(foo_vector)" }
-attributes #2 = { nounwind "vector-function-abi-variant"="_ZGV_LLVM_Nxv_foo(foo_vector_nomask)" }
-attributes #3 = { nounwind "vector-function-abi-variant"="_ZGV_LLVM_Nxv_foo(foo_vector_nomask),_ZGV_LLVM_Mxv_foo(foo_vector)" }
+attributes #0 = { nounwind "vector-function-abi-variant"="_ZGVsMxv_foo(foo_vector),_ZGVsMxu_foo(foo_uniform)" }
+attributes #1 = { nounwind "vector-function-abi-variant"="_ZGVsMxv_foo(foo_vector)" }
+attributes #2 = { nounwind "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vector_nomask)" }
+attributes #3 = { nounwind "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vector_nomask),_ZGVsMxv_foo(foo_vector)" }
 attributes #4 = { "target-features"="+sve" vscale_range(2,16) "no-trapping-math"="false" }
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/scalable-call.ll b/llvm/test/Transforms/LoopVectorize/AArch64/scalable-call.ll
index 69c6f84aac53dd6..84f67310021bf1d 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/scalable-call.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/scalable-call.ll
@@ -224,9 +224,9 @@ declare <vscale x 2 x i64> @bar_vec(<vscale x 2 x ptr>)
 declare <vscale x 2 x double> @sin_vec_nxv2f64(<vscale x 2 x double>)
 declare <2 x double> @sin_vec_v2f64(<2 x double>)
 
-attributes #0 = { "vector-function-abi-variant"="_ZGV_LLVM_Nxv_foo(foo_vec)" }
-attributes #1 = { "vector-function-abi-variant"="_ZGV_LLVM_Nxv_bar(bar_vec)" }
-attributes #2 = { "vector-function-abi-variant"="_ZGV_LLVM_Nxv_llvm.sin.f64(sin_vec_nxv2f64)" }
+attributes #0 = { "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vec)" }
+attributes #1 = { "vector-function-abi-variant"="_ZGVsNxv_bar(bar_vec)" }
+attributes #2 = { "vector-function-abi-variant"="_ZGVsNxv_llvm.sin.f64(sin_vec_nxv2f64)" }
 attributes #3 = { "vector-function-abi-variant"="_ZGV_LLVM_N2v_llvm.sin.f64(sin_vec_v2f64)" }
 
 !1 = distinct !{!1, !2, !3}
diff --git a/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp b/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
index b0b80131bf48f48..050f8adca278eb0 100644
--- a/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
+++ b/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
@@ -27,15 +27,17 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   // present. We need to make sure we can even invoke
   // `getOrInsertFunction` because such method asserts on strings with
   // zeroes.
-  if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos)
-    M->getOrInsertFunction(
-        MangledName,
-        FunctionType::get(Type::getVoidTy(M->getContext()), false));
-  const auto Info = VFABI::tryDemangleForVFABI(MangledName, *M);
+  if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos) {
+    SmallVector<Type *> OpTys(
+        FunctionType::get(Type::getVoidTy(M->getContext()), false)->params());
 
-  // Do not optimize away the return value. Inspired by
-  // https://github.com/google/benchmark/blob/main/include/benchmark/benchmark.h#L307-L345
-  asm volatile("" : : "r,m"(Info) : "memory");
+    const auto Info = VFABI::tryDemangleForVFABI(MangledName, OpTys);
 
-  return 0;
+    // Do not optimize away the return value. Inspired by
+    // https://github.com/google/benchmark/blob/main/include/benchmark/benchmark.h#L307-L345
+    asm volatile("" : : "r,m"(Info) : "memory");
+
+    return 0;
+  }
+  return 1;
 }
diff --git a/llvm/unittests/Analysis/VectorFunctionABITest.cpp b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
index a4c6b2143fc662c..2e0bf2bb96935ec 100644
--- a/llvm/unittests/Analysis/VectorFunctionABITest.cpp
+++ b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
@@ -25,7 +25,7 @@ class VFABIParserTest : public ::testing::Test {
     EXPECT_NE(M.get(), nullptr) << "Loading an invalid module.\n "
                                 << Err.getMessage() << "\n";
     Type *Ty = parseType(IRType, Err, *(M.get()));
-    FunctionType *FTy = dyn_cast<FunctionType>(Ty);
+    FTy = dyn_cast<FunctionType>(Ty);
     EXPECT_NE(FTy, nullptr) << "Invalid function type string: " << IRType
                             << "\n"
                             << Err.getMessage() << "\n";
@@ -40,7 +40,8 @@ class VFABIParserTest : public ::testing::Test {
   LLVMContext Ctx;
   SMDiagnostic Err;
   std::unique_ptr<Module> M;
-  //  CallInst *CI;
+  FunctionType *FTy;
+
 protected:
   // Referencies to the parser output field.
   ElementCount &VF = Info.Shape.VF;
@@ -73,8 +74,8 @@ class VFABIParserTest : public ::testing::Test {
     // Reset the VFInfo and the Module to be able to invoke
     // `invokeParser` multiple times in the same test.
     reset(Name, IRType);
-
-    const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, *(M.get()));
+    SmallVector<Type *> OpTys(FTy->params());
+    const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, OpTys);
     if (OptInfo) {
       Info = *OptInfo;
       return true;
@@ -206,7 +207,7 @@ TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
 TEST_F(VFABIParserTest, ParseScalableSVE) {
   EXPECT_TRUE(invokeParser(
       "_ZGVsMxv_sin(custom_vg)", "custom_vg",
-      "<vscale x 2 x i32>(<vscale x 2 x i32>, <vscale x 2 x i1>)"));
+      "<vscale x 2 x i64>(<vscale x 2 x i64>, <vscale x 2 x i1>)"));
   EXPECT_EQ(VF, ElementCount::getScalable(2));
   EXPECT_TRUE(IsMasked());
   EXPECT_EQ(ISA, VFISAKind::SVE);
@@ -496,11 +497,11 @@ TEST_F(VFABIParserTest, ParseMaskingLLVM) {
 
 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
   EXPECT_TRUE(invokeParser(
-      "_ZGV_LLVM_Mxv_sin(custom_vector_sin)", "custom_vector_sin",
-      "<vscale x 2 x i32> (<vscale x 2 x i32>, <vscale x 2 x i1>)"));
+      "_ZGVsMxv_sin(custom_vector_sin)", "custom_vector_sin",
+      "<vscale x 2 x i64> (<vscale x 2 x i64>, <vscale x 2 x i1>)"));
   EXPECT_TRUE(IsMasked());
   EXPECT_EQ(VF, ElementCount::getScalable(2));
-  EXPECT_EQ(ISA, VFISAKind::LLVM);
+  EXPECT_EQ(ISA, VFISAKind::SVE);
   EXPECT_EQ(Parameters.size(), (unsigned)2);
   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
@@ -509,12 +510,12 @@ TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
 }
 
 TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) {
-  EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)",
+  EXPECT_TRUE(invokeParser("_ZGVsMxvl8l8_sincos(custom_vector_sincos)",
                            "custom_vector_sincos",
                            "void(<vscale x 2 x double>, double *, double *)"));
   EXPECT_EQ(VF, ElementCount::getScalable(2));
   EXPECT_TRUE(IsMasked());
-  EXPECT_EQ(ISA, VFISAKind::LLVM);
+  EXPECT_EQ(ISA, VFISAKind::SVE);
   EXPECT_EQ(Parameters.size(), (unsigned)4);
   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8}));

>From 4ab245ff3e076e1e721be484775d7c923dfebd75 Mon Sep 17 00:00:00 2001
From: Jolanta Jensen <Jolanta.Jensen at arm.com>
Date: Fri, 29 Sep 2023 14:34:29 +0000
Subject: [PATCH 2/3] Addressed review comments.

---
 llvm/include/llvm/Analysis/VectorUtils.h      |   9 +-
 llvm/lib/Analysis/VFABIDemangling.cpp         | 151 ++++++++----------
 llvm/lib/Analysis/VectorUtils.cpp             |   5 +-
 llvm/lib/Transforms/Utils/ModuleUtils.cpp     |   6 +-
 .../vfabi-demangler-fuzzer.cpp                |  15 +-
 .../Analysis/VectorFunctionABITest.cpp        |  13 +-
 6 files changed, 88 insertions(+), 111 deletions(-)

diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index bb612ae041c138d..183cada23f56ab5 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -174,9 +174,9 @@ static constexpr char const *_LLVM_Scalarize_ = "_LLVM_Scalarize_";
 ///
 /// \param MangledName -> input string in the format
 /// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
-/// \param OpTys -> the instruction operand types.
+/// \param CI -> the call instruction.
 std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
-                                          SmallVector<Type *> OpTys);
+                                          const CallInst &CI);
 
 /// Retrieve the `VFParamKind` from a string token.
 VFParamKind getVFParamKindFromString(const StringRef Token);
@@ -222,11 +222,8 @@ class VFDatabase {
     if (ListOfStrings.empty())
       return;
     for (const auto &MangledName : ListOfStrings) {
-      SmallVector<Type *> OpTys;
-      for (Value *Op : CI.operands())
-        OpTys.push_back(Op->getType());
       const std::optional<VFInfo> Shape =
-          VFABI::tryDemangleForVFABI(MangledName, OpTys);
+          VFABI::tryDemangleForVFABI(MangledName, CI);
       // A match is found via scalar and vector names, and also by
       // ensuring that the variant described in the attribute has a
       // corresponding definition or declaration of the vector
diff --git a/llvm/lib/Analysis/VFABIDemangling.cpp b/llvm/lib/Analysis/VFABIDemangling.cpp
index 7a3c8c3bcc72fbe..a28ac29c543e6b1 100644
--- a/llvm/lib/Analysis/VFABIDemangling.cpp
+++ b/llvm/lib/Analysis/VFABIDemangling.cpp
@@ -61,29 +61,77 @@ ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
   return ParseRet::Error;
 }
 
+#ifndef NDEBUG
+// Verify the assumtion that all vectors in the signature of a vector
+// function have the same number of elements.
+bool verifyAllVectorsHaveSameWidth(FunctionType *Signature) {
+  SmallVector<VectorType *, 2> VecTys;
+  if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
+    VecTys.push_back(RetTy);
+  for (auto *Ty : Signature->params())
+    if (auto *VTy = dyn_cast<VectorType>(Ty))
+      VecTys.push_back(VTy);
+
+  if (VecTys.size() <= 1)
+    return true;
+
+  assert(VecTys.size() > 1 && "Invalid number of elements.");
+  const ElementCount EC = VecTys[0]->getElementCount();
+  return llvm::all_of(llvm::drop_begin(VecTys), [&EC](VectorType *VTy) {
+    return (EC == VTy->getElementCount());
+  });
+}
+#endif // NDEBUG
+
 /// Extract the `<vlen>` information from the mangled string, and
 /// sets `VF` accordingly. A `<vlen> == "x"` token is interpreted as a scalable
 /// vector length. On success, the `<vlen>` token is removed from
 /// the input string `ParseString`.
 ///
-ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
+ParseRet tryParseVLEN(StringRef &ParseString, ElementCount &EC,
+                      const CallInst &CI, VFISAKind ISA) {
+  unsigned VF = 0;
   if (ParseString.consume_front("x")) {
-    // Set VF to 0, to be later adjusted to a value grater than zero
-    // by looking at the signature of the vector function with
-    // `getECFromSignature`.
-    VF = 0;
-    IsScalable = true;
+    if (ISA != VFISAKind::SVE)
+      return ParseRet::Error;
+    FunctionType *Signature = CI.getFunctionType();
+    assert(verifyAllVectorsHaveSameWidth(Signature) &&
+           "Invalid vector signature.");
+
+    ArrayRef<Type *> ParamTys = Signature->params();
+    if (ParamTys.empty()) {
+      return ParseRet::Error;
+    }
+    switch (ParamTys[0]->getScalarSizeInBits()) {
+    case 64:
+      VF = 2;
+      break;
+    case 32:
+      VF = 4;
+      break;
+    case 0: {
+      if (ParamTys[0]->isPointerTy())
+        VF = 2;
+      else
+        VF = 0;
+      break;
+    }
+    default:
+      VF = 0;
+      break;
+    }
+    if (VF == 0)
+      return ParseRet::Error;
+    EC = ElementCount::get(VF, true);
     return ParseRet::OK;
   }
-
   if (ParseString.consumeInteger(10, VF))
     return ParseRet::Error;
 
   // The token `0` is invalid for VLEN.
   if (VF == 0)
     return ParseRet::Error;
-
-  IsScalable = false;
+  EC = ElementCount::get(VF, false);
   return ParseRet::OK;
 }
 
@@ -272,50 +320,12 @@ ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {
 
   return ParseRet::None;
 }
-
-#ifndef NDEBUG
-// Verify the assumtion that all vectors in the signature of a vector
-// function have the same number of elements.
-bool verifyAllVectorsHaveSameWidth(FunctionType *Signature) {
-  SmallVector<VectorType *, 2> VecTys;
-  if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
-    VecTys.push_back(RetTy);
-  for (auto *Ty : Signature->params())
-    if (auto *VTy = dyn_cast<VectorType>(Ty))
-      VecTys.push_back(VTy);
-
-  if (VecTys.size() <= 1)
-    return true;
-
-  assert(VecTys.size() > 1 && "Invalid number of elements.");
-  const ElementCount EC = VecTys[0]->getElementCount();
-  return llvm::all_of(llvm::drop_begin(VecTys), [&EC](VectorType *VTy) {
-    return (EC == VTy->getElementCount());
-  });
-}
-#endif // NDEBUG
-
-// Extract the VectorizationFactor from a given function signature,
-// under the assumtion that all vectors have the same number of
-// elements, i.e. same ElementCount.Min.
-ElementCount getECFromSignature(FunctionType *Signature) {
-  assert(verifyAllVectorsHaveSameWidth(Signature) &&
-         "Invalid vector signature.");
-
-  if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
-    return RetTy->getElementCount();
-  for (auto *Ty : Signature->params())
-    if (auto *VTy = dyn_cast<VectorType>(Ty))
-      return VTy->getElementCount();
-
-  return ElementCount::getFixed(/*Min=*/1);
-}
 } // namespace
 
 // Format of the ABI name:
 // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
 std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
-                                                 SmallVector<Type *> OpTys) {
+                                                 const CallInst &CI) {
   const StringRef OriginalName = MangledName;
   // Assume there is no custom name <redirection>, and therefore the
   // vector name consists of
@@ -338,9 +348,8 @@ std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
     return std::nullopt;
 
   // Parse the variable size, starting from <vlen>.
-  unsigned VF;
-  bool IsScalable;
-  if (tryParseVLEN(MangledName, VF, IsScalable) != ParseRet::OK)
+  ElementCount EC;
+  if (tryParseVLEN(MangledName, EC, CI, ISA) != ParseRet::OK)
     return std::nullopt;
 
   // Parse the <parameters>.
@@ -426,43 +435,9 @@ std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
     assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate &&
            "The global predicate must be the last parameter");
 
-  // Adjust the VF for scalable signatures. The EC.Min is not encoded
-  // in the name of the function, but it is encoded in the IR
-  // signature of the function. We need to extract this information
-  // because it is needed by the loop vectorizer, which reasons in
-  // terms of VectorizationFactor or ElementCount. In particular, we
-  // need to make sure that the VF field of the VFShape class is never
-  // set to 0.
-  if (IsScalable) {
-    if (ISA != VFISAKind::SVE)
-      return std::nullopt;
-    if (OpTys.empty())
-      return std::nullopt;
-    switch (OpTys[0]->getScalarSizeInBits()) {
-    case 64:
-      VF = 2;
-      break;
-    case 32:
-      VF = 4;
-      break;
-    case 0: {
-      if (OpTys[0]->isPointerTy())
-        VF = 2;
-      else
-        VF = 0;
-      break;
-    }
-    default:
-      VF = 0;
-      break;
-    }
-  }
-
-  // 1. We don't accept a zero lanes vectorization factor.
-  if (VF == 0)
-    return std::nullopt;
-
-  const VFShape Shape({ElementCount::get(VF, IsScalable), Parameters});
+  assert(EC.getKnownMinValue() != 0 &&
+         "We don't accept a zero lanes vectorization factor.");
+  const VFShape Shape({EC, Parameters});
   return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA});
 }
 
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 6936dd1bd4db5f8..16e4359abef5646 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1464,11 +1464,8 @@ void VFABI::getVectorVariantNames(
 
   for (const auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) {
 #ifndef NDEBUG
-    SmallVector<Type *> OpTys;
-    for (Value *Op : CI.operands())
-      OpTys.push_back(Op->getType());
     LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << S << "'\n");
-    std::optional<VFInfo> Info = VFABI::tryDemangleForVFABI(S, OpTys);
+    std::optional<VFInfo> Info = VFABI::tryDemangleForVFABI(S, CI);
     assert(Info && "Invalid name for a VFABI variant.");
     assert(CI.getModule()->getFunction(Info->VectorName) &&
            "Vector function is missing.");
diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 6da3882875583fa..c03d27e5dc0613a 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -345,12 +345,8 @@ void VFABI::setVectorVariantNames(CallInst *CI,
   Module *M = CI->getModule();
 #ifndef NDEBUG
   for (const std::string &VariantMapping : VariantMappings) {
-    SmallVector<Type *> OpTys;
-    for (Value *Op : CI->operands())
-      OpTys.push_back(Op->getType());
     LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");
-    std::optional<VFInfo> VI =
-        VFABI::tryDemangleForVFABI(VariantMapping, OpTys);
+    std::optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping, *CI);
     assert(VI && "Cannot add an invalid VFABI name.");
     assert(M->getNamedValue(VI->VectorName) &&
            "Cannot add variant to attribute: "
diff --git a/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp b/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
index 050f8adca278eb0..d0574cf260e5a71 100644
--- a/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
+++ b/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
@@ -28,10 +28,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   // `getOrInsertFunction` because such method asserts on strings with
   // zeroes.
   if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos) {
-    SmallVector<Type *> OpTys(
-        FunctionType::get(Type::getVoidTy(M->getContext()), false)->params());
-
-    const auto Info = VFABI::tryDemangleForVFABI(MangledName, OpTys);
+    FunctionType *FTy =
+        FunctionType::get(Type::getVoidTy(M->getContext()), false);
+    FunctionCallee F = M->getOrInsertFunction(MangledName, FTy);
+    // Fake the arguments to the CallInst.
+    SmallVector<Value *> Args;
+    for (Type *ParamTy : FTy->params()) {
+      Args.push_back(Constant::getNullValue(ParamTy));
+    }
+    std::unique_ptr<CallInst> CI(CallInst::Create(F, Args));
+    const auto Info = VFABI::tryDemangleForVFABI(MangledName, *(CI.get()));
 
     // Do not optimize away the return value. Inspired by
     // https://github.com/google/benchmark/blob/main/include/benchmark/benchmark.h#L307-L345
@@ -39,5 +45,4 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
 
     return 0;
   }
-  return 1;
 }
diff --git a/llvm/unittests/Analysis/VectorFunctionABITest.cpp b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
index 2e0bf2bb96935ec..ea47138c4963a71 100644
--- a/llvm/unittests/Analysis/VectorFunctionABITest.cpp
+++ b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
@@ -29,7 +29,7 @@ class VFABIParserTest : public ::testing::Test {
     EXPECT_NE(FTy, nullptr) << "Invalid function type string: " << IRType
                             << "\n"
                             << Err.getMessage() << "\n";
-    FunctionCallee F = M->getOrInsertFunction(Name, FTy);
+    F = M->getOrInsertFunction(Name, FTy);
     EXPECT_NE(F.getCallee(), nullptr)
         << "The function must be present in the module\n";
     // Reset the VFInfo
@@ -41,6 +41,7 @@ class VFABIParserTest : public ::testing::Test {
   SMDiagnostic Err;
   std::unique_ptr<Module> M;
   FunctionType *FTy;
+  FunctionCallee F;
 
 protected:
   // Referencies to the parser output field.
@@ -74,8 +75,14 @@ class VFABIParserTest : public ::testing::Test {
     // Reset the VFInfo and the Module to be able to invoke
     // `invokeParser` multiple times in the same test.
     reset(Name, IRType);
-    SmallVector<Type *> OpTys(FTy->params());
-    const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, OpTys);
+
+    // Fake the arguments to the CallInst.
+    SmallVector<Value *> Args;
+    for (Type *ParamTy : FTy->params()) {
+      Args.push_back(Constant::getNullValue(ParamTy));
+    }
+    std::unique_ptr<CallInst> CI(CallInst::Create(F, Args));
+    const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, *(CI.get()));
     if (OptInfo) {
       Info = *OptInfo;
       return true;

>From f2c3c9c1aa559c069f7ce5f0112d9ab28a2a8f10 Mon Sep 17 00:00:00 2001
From: Jolanta Jensen <Jolanta.Jensen at arm.com>
Date: Fri, 6 Oct 2023 11:29:38 +0000
Subject: [PATCH 3/3] Correcting the fuzzer test

---
 .../vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp  | 11 +++--------
 llvm/unittests/Analysis/VectorFunctionABITest.cpp     |  5 +----
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp b/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
index d0574cf260e5a71..87c44021d6aa16e 100644
--- a/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
+++ b/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
@@ -21,12 +21,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   const std::unique_ptr<Module> M =
       parseAssemblyString("declare i32 @foo(i32 )\n", Err, Ctx);
   const StringRef MangledName((const char *)Data, Size);
-  // Make sure that whatever symbol the demangler is operating on is
-  // present in the module (the signature is not important). This is
-  // because `tryDemangleForVFABI` fails if the function is not
-  // present. We need to make sure we can even invoke
-  // `getOrInsertFunction` because such method asserts on strings with
-  // zeroes.
+  // Make sure we can invoke `getOrInsertFunction` because such method asserts
+  // on strings with zeroes.
   if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos) {
     FunctionType *FTy =
         FunctionType::get(Type::getVoidTy(M->getContext()), false);
@@ -42,7 +38,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
     // Do not optimize away the return value. Inspired by
     // https://github.com/google/benchmark/blob/main/include/benchmark/benchmark.h#L307-L345
     asm volatile("" : : "r,m"(Info) : "memory");
-
-    return 0;
   }
+  return 0;
 }
diff --git a/llvm/unittests/Analysis/VectorFunctionABITest.cpp b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
index ea47138c4963a71..f3b26316e921d93 100644
--- a/llvm/unittests/Analysis/VectorFunctionABITest.cpp
+++ b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
@@ -50,10 +50,7 @@ class VFABIParserTest : public ::testing::Test {
   SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;
   std::string &ScalarName = Info.ScalarName;
   std::string &VectorName = Info.VectorName;
-  // Invoke the parser. We need to make sure that a function exist in
-  // the module because the parser fails if such function don't
-  // exists. Every time this method is invoked the state of the test
-  // is reset.
+  // Invoke the parser.
   //
   // \p MangledName -> the string the parser has to demangle.
   //



More information about the llvm-commits mailing list