diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h --- a/llvm/include/llvm/Analysis/VectorUtils.h +++ b/llvm/include/llvm/Analysis/VectorUtils.h @@ -164,8 +164,20 @@ /// name. At the moment, this parameter is needed only to retrieve the /// Vectorization Factor of scalable vector functions from their /// respective IR declarations. +/// \param AllowEmptyParameter -> If true, this function will try to demangle +/// even when the list is empty. The x86 VFABI doc explicitly +/// allows an empty parameter list. std::optional tryDemangleForVFABI(StringRef MangledName, - const Module &M); + const Module &M, + bool AllowEmptyParameter = false); +/// \param M -> The pointer to module used to retrieve informations about the +/// vector function. If nullptr is passed, we don't check the existence of +/// the demangled vector function. +std::optional tryDemangleForVFABI(StringRef MangledName, + const Module *M = nullptr, + bool AllowEmptyParameter = false); +VFInfo demangleForVFABI(StringRef MangledName, + bool AllowEmptyParameter = false); /// This routine mangles the given VectorName according to the LangRef /// specification for vector-function-abi-variant attribute and is specific to diff --git a/llvm/lib/Analysis/VFABIDemangling.cpp b/llvm/lib/Analysis/VFABIDemangling.cpp --- a/llvm/lib/Analysis/VFABIDemangling.cpp +++ b/llvm/lib/Analysis/VFABIDemangling.cpp @@ -312,10 +312,25 @@ } } // namespace +VFInfo VFABI::demangleForVFABI(StringRef MangledName, + bool AllowEmptyParameter) { + auto VI = VFABI::tryDemangleForVFABI(MangledName, /*M = */ nullptr, + AllowEmptyParameter); + assert(VI && "Invalid name for a VFABI variant."); + return VI.value(); +} + +std::optional VFABI::tryDemangleForVFABI(StringRef MangledName, + const Module &M, + bool AllowEmptyParameter) { + return VFABI::tryDemangleForVFABI(MangledName, &M, AllowEmptyParameter); +} + // Format of the ABI name: // _ZGV_[()] std::optional VFABI::tryDemangleForVFABI(StringRef MangledName, - const Module &M) { + const Module *M, + bool AllowEmptyParameter) { const StringRef OriginalName = MangledName; // Assume there is no custom name , and therefore the // vector name consists of @@ -369,9 +384,7 @@ } } while (ParamFound == ParseRet::OK); - // A valid MangledName must have at least one valid entry in the - // . - if (Parameters.empty()) + if (!AllowEmptyParameter && Parameters.empty()) return std::nullopt; // Check for the and the optional , which @@ -434,7 +447,8 @@ // 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); + assert(M && "Can't demangle scalable variant name without a valid module!"); + 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) @@ -444,11 +458,11 @@ } // 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. + // 2. If M is not nullptr, 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)) + if (M && !M->getFunction(VectorName)) return std::nullopt; const VFShape Shape({ElementCount::get(VF, IsScalable), Parameters}); diff --git a/llvm/unittests/Analysis/VectorFunctionABITest.cpp b/llvm/unittests/Analysis/VectorFunctionABITest.cpp --- a/llvm/unittests/Analysis/VectorFunctionABITest.cpp +++ b/llvm/unittests/Analysis/VectorFunctionABITest.cpp @@ -66,7 +66,9 @@ // bool invokeParser(const StringRef MangledName, const StringRef VectorName = "", - const StringRef IRType = "void()") { + const StringRef IRType = "void()", + bool CheckVectorNameExistence = true, + bool AllowEmptyParameter = false) { StringRef Name = MangledName; if (!VectorName.empty()) Name = VectorName; @@ -74,7 +76,11 @@ // `invokeParser` multiple times in the same test. reset(Name, IRType); - const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, *(M.get())); + const auto OptInfo = CheckVectorNameExistence + ? VFABI::tryDemangleForVFABI( + MangledName, *(M.get()), AllowEmptyParameter) + : VFABI::tryDemangleForVFABI(MangledName, nullptr, + AllowEmptyParameter); if (OptInfo) { Info = *OptInfo; return true; @@ -144,6 +150,21 @@ EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar", "fakename")); } +TEST_F(VFABIParserTest, EmptyParamList) { + EXPECT_TRUE(invokeParser( + "_ZGVnN2_foo", /*VectorName = */ "", /*IRType = */ "void()", + /*CheckVectorNameExistence = */ true, /*AllowEmptyParameter = */ true)); +} + +TEST_F(VFABIParserTest, DontCheckVectorNameExistence) { + // Demangling succeeds even if `UserFunc` doesn't exist in the module. + EXPECT_TRUE(invokeParser("_ZGVnM2v_sin(UserFunc)", /*VectorName = */ "", + /*IRType = */ "void()", + /*CheckVectorNameExistence = */ false)); + EXPECT_EQ(ScalarName, "sin"); + EXPECT_EQ(VectorName, "UserFunc"); +} + TEST_F(VFABIParserTest, ParamListParsing) { EXPECT_TRUE(invokeParser("_ZGVnN2vl16Ls32R3l_foo")); EXPECT_EQ(Parameters.size(), (unsigned)5);