[llvm] [Analysis][NFC] Make VecDesc constexpr and relocation-free (PR #201145)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 08:46:06 PDT 2026
https://github.com/aengelke updated https://github.com/llvm/llvm-project/pull/201145
>From 75334ff1c37049ebc48f7beabc9fb71a7f75f5a4 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Tue, 2 Jun 2026 15:28:01 +0000
Subject: [PATCH 1/2] [spr] initial version
Created using spr 1.3.8-wip
---
.../include/llvm/Analysis/TargetLibraryInfo.h | 53 +++--
llvm/lib/Analysis/TargetLibraryInfo.cpp | 183 +++++++++++++-----
llvm/unittests/Analysis/CMakeLists.txt | 1 -
.../Analysis/ReplaceWithVecLibTest.cpp | 115 -----------
4 files changed, 169 insertions(+), 183 deletions(-)
delete mode 100644 llvm/unittests/Analysis/ReplaceWithVecLibTest.cpp
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 629b126db17c2..6450a8a05f8c0 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -43,27 +43,42 @@ template <typename T> class ArrayRef;
/// <scalarname> = the name of the scalar function.
/// <vectorname> = the name of the vector function.
class VecDesc {
- StringRef ScalarFnName;
- StringRef VectorFnName;
- ElementCount VectorizationFactor;
- bool Masked;
- StringRef VABIPrefix;
- std::optional<CallingConv::ID> CC;
+ friend struct VecDescBuilder;
+
+ // String offsets are relative to the this pointer.
+ uint16_t ScalarFnNameOff = 0;
+ uint16_t ScalarFnNameSize = 0;
+ uint16_t VectorFnNameOff = 0;
+ uint16_t VectorFnNameSize = 0;
+ ElementCount VectorizationFactor = {};
+ bool Masked = false;
+ uint16_t VABIPrefixOff = 0;
+ uint16_t VABIPrefixSize = 0;
+ std::optional<CallingConv::ID> CC = {};
+
+ constexpr VecDesc() {}
+
+ // Due to the relative string offsets, VecDesc is neither copyable nor
+ // movable. The move constructor has to exist to allow assignment to a
+ // variable.
+ VecDesc(const VecDesc &) = delete;
+ VecDesc(VecDesc &&) = default;
public:
- VecDesc() = delete;
- VecDesc(StringRef ScalarFnName, StringRef VectorFnName,
- ElementCount VectorizationFactor, bool Masked, StringRef VABIPrefix,
- std::optional<CallingConv::ID> Conv)
- : ScalarFnName(ScalarFnName), VectorFnName(VectorFnName),
- VectorizationFactor(VectorizationFactor), Masked(Masked),
- VABIPrefix(VABIPrefix), CC(Conv) {}
-
- StringRef getScalarFnName() const { return ScalarFnName; }
- StringRef getVectorFnName() const { return VectorFnName; }
+ StringRef getScalarFnName() const {
+ return StringRef(reinterpret_cast<const char *>(this) + ScalarFnNameOff,
+ ScalarFnNameSize);
+ }
+ StringRef getVectorFnName() const {
+ return StringRef(reinterpret_cast<const char *>(this) + VectorFnNameOff,
+ VectorFnNameSize);
+ }
ElementCount getVectorizationFactor() const { return VectorizationFactor; }
bool isMasked() const { return Masked; }
- StringRef getVABIPrefix() const { return VABIPrefix; }
+ StringRef getVABIPrefix() const {
+ return StringRef(reinterpret_cast<const char *>(this) + VABIPrefixOff,
+ VABIPrefixSize);
+ }
std::optional<CallingConv::ID> getCallingConv() const { return CC; }
/// Returns a vector function ABI variant string on the form:
@@ -104,10 +119,10 @@ class TargetLibraryInfoImpl {
}
/// Vectorization descriptors - sorted by ScalarFnName.
- std::vector<VecDesc> VectorDescs;
+ std::vector<const VecDesc *> VectorDescs;
/// Scalarization descriptors - same content as VectorDescs but sorted based
/// on VectorFnName rather than ScalarFnName.
- std::vector<VecDesc> ScalarDescs;
+ std::vector<const VecDesc *> ScalarDescs;
/// Return true if the function type FTy is valid for the library function
/// F, regardless of whether the function is available.
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 6b8f861392254..701c84dc99ce3 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -25,10 +25,12 @@ using namespace llvm;
#include "llvm/Analysis/TargetLibraryInfo.inc"
std::string VecDesc::getVectorFunctionABIVariantString() const {
- assert(!VectorFnName.empty() && "Vector function name must not be empty.");
+ assert(!getVectorFnName().empty() &&
+ "Vector function name must not be empty.");
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
- Out << VABIPrefix << "_" << ScalarFnName << "(" << VectorFnName << ")";
+ Out << getVABIPrefix() << "_" << getScalarFnName() << "(" << getVectorFnName()
+ << ")";
return std::string(Out.str());
}
@@ -1223,109 +1225,197 @@ void TargetLibraryInfoImpl::disableAllFunctions() {
memset(AvailableArray, 0, sizeof(AvailableArray));
}
-static bool compareByScalarFnName(const VecDesc &LHS, const VecDesc &RHS) {
- return LHS.getScalarFnName() < RHS.getScalarFnName();
+static bool compareByScalarFnName(const VecDesc *LHS, const VecDesc *RHS) {
+ return LHS->getScalarFnName() < RHS->getScalarFnName();
}
-static bool compareByVectorFnName(const VecDesc &LHS, const VecDesc &RHS) {
- return LHS.getVectorFnName() < RHS.getVectorFnName();
+static bool compareByVectorFnName(const VecDesc *LHS, const VecDesc *RHS) {
+ return LHS->getVectorFnName() < RHS->getVectorFnName();
}
-static bool compareWithScalarFnName(const VecDesc &LHS, StringRef S) {
- return LHS.getScalarFnName() < S;
+static bool compareWithScalarFnName(const VecDesc *LHS, StringRef S) {
+ return LHS->getScalarFnName() < S;
}
void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef<VecDesc> Fns) {
- llvm::append_range(VectorDescs, Fns);
+ for (const VecDesc &Desc : Fns)
+ VectorDescs.push_back(&Desc);
llvm::sort(VectorDescs, compareByScalarFnName);
- llvm::append_range(ScalarDescs, Fns);
+ for (const VecDesc &Desc : Fns)
+ ScalarDescs.push_back(&Desc);
llvm::sort(ScalarDescs, compareByVectorFnName);
}
-static const VecDesc VecFuncs_Accelerate[] = {
+struct VecDescData {
+ StringRef ScalarFnName;
+ StringRef VectorFnName;
+ ElementCount VectorizationFactor;
+ bool Masked;
+ StringRef VABIPrefix;
+ std::optional<CallingConv::ID> CC;
+};
+
+namespace llvm {
+struct VecDescBuilder {
+ template <size_t M, size_t N>
+ static constexpr auto build(const char (&StrTab)[M],
+ const VecDescData (&Data)[N]) {
+ struct {
+ VecDesc Descs[N];
+ char StringTable[M];
+
+ operator ArrayRef<VecDesc>() const { return ArrayRef(Descs, N); }
+ } Ret{};
+ for (size_t i = 0; i != M; i++)
+ Ret.StringTable[i] = StrTab[i];
+ size_t Off = offsetof(decltype(Ret), StringTable);
+ for (size_t i = 0; i != N; i++) {
+ assert(Off < UINT16_MAX);
+ Ret.Descs[i].ScalarFnNameOff = Off;
+ Off += Data[i].ScalarFnName.size();
+ Ret.Descs[i].ScalarFnNameSize = Data[i].ScalarFnName.size();
+ Ret.Descs[i].VectorFnNameOff = Off;
+ Off += Data[i].VectorFnName.size();
+ Ret.Descs[i].VectorFnNameSize = Data[i].VectorFnName.size();
+ Ret.Descs[i].VectorizationFactor = Data[i].VectorizationFactor;
+ Ret.Descs[i].Masked = Data[i].Masked;
+ Ret.Descs[i].VABIPrefixOff = Off;
+ Off += Data[i].VABIPrefix.size();
+ Ret.Descs[i].VABIPrefixSize = Data[i].VABIPrefix.size();
+ Ret.Descs[i].CC = Data[i].CC;
+ Off -= sizeof(VecDesc);
+ }
+ return Ret;
+ }
+};
+} // namespace llvm
+
#define TLI_DEFINE_ACCELERATE_VECFUNCS
+static constexpr auto VecFuncs_Accelerate = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_ACCELERATE_VECFUNCS
-};
-static const VecDesc VecFuncs_DarwinLibSystemM[] = {
#define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS
+static constexpr auto VecFuncs_DarwinLibSystemM = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS
-};
-static const VecDesc VecFuncs_LIBMVEC_X86[] = {
#define TLI_DEFINE_LIBMVEC_X86_VECFUNCS
+static constexpr auto VecFuncs_LIBMVEC_X86 = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_LIBMVEC_X86_VECFUNCS
-};
-static const VecDesc VecFuncs_LIBMVEC_AARCH64[] = {
#define TLI_DEFINE_LIBMVEC_AARCH64_VECFUNCS
+static constexpr auto VecFuncs_LIBMVEC_AARCH64 = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX, CC) \
+ SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX, CC) \
{SCAL, VEC, VF, MASK, VABI_PREFIX, CC},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_LIBMVEC_AARCH64_VECFUNCS
-};
-static const VecDesc VecFuncs_MASSV[] = {
#define TLI_DEFINE_MASSV_VECFUNCS
+static constexpr auto VecFuncs_MASSV = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_MASSV_VECFUNCS
-};
-static const VecDesc VecFuncs_SVML[] = {
#define TLI_DEFINE_SVML_VECFUNCS
+static constexpr auto VecFuncs_SVML = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_SVML_VECFUNCS
-};
-static const VecDesc VecFuncs_SLEEFGNUABI_VF2[] = {
#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS
+static constexpr auto VecFuncs_SLEEFGNUABI_VF2 = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \
{SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX, /* CC = */ std::nullopt},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS
-};
-static const VecDesc VecFuncs_SLEEFGNUABI_VF4[] = {
#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS
+static constexpr auto VecFuncs_SLEEFGNUABI_VF4 = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \
{SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX, /* CC = */ std::nullopt},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS
-};
-static const VecDesc VecFuncs_SLEEFGNUABI_VFScalable[] = {
#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS
+static constexpr auto VecFuncs_SLEEFGNUABI_VFScalable = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
+ SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
{SCAL, VEC, VF, MASK, VABI_PREFIX, /* CC = */ std::nullopt},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS
-};
-static const VecDesc VecFuncs_SLEEFGNUABI_VFScalableRISCV[] = {
#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS_RISCV
+static constexpr auto VecFuncs_SLEEFGNUABI_VFScalableRISCV =
+ VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
+ SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
{SCAL, VEC, VF, MASK, VABI_PREFIX, /* CC = */ std::nullopt},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS_RISCV
-};
-static const VecDesc VecFuncs_ArmPL[] = {
#define TLI_DEFINE_ARMPL_VECFUNCS
+static constexpr auto VecFuncs_ArmPL = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX, CC) \
+ SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX, CC) \
{SCAL, VEC, VF, MASK, VABI_PREFIX, CC},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_ARMPL_VECFUNCS
-};
-const VecDesc VecFuncs_AMDLIBM[] = {
#define TLI_DEFINE_AMDLIBM_VECFUNCS
+static constexpr auto VecFuncs_AMDLIBM = VecDescBuilder::build(
+#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
+ SCAL VEC VABI_PREFIX
+#include "llvm/Analysis/VecFuncs.def"
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
{SCAL, VEC, VF, MASK, VABI_PREFIX, /* CC = */ std::nullopt},
#include "llvm/Analysis/VecFuncs.def"
+ });
#undef TLI_DEFINE_AMDLIBM_VECFUNCS
-};
void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib(
enum VectorLibrary VecLib, const llvm::Triple &TargetTriple) {
@@ -1402,9 +1492,8 @@ bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName) const {
if (funcName.empty())
return false;
- std::vector<VecDesc>::const_iterator I =
- llvm::lower_bound(VectorDescs, funcName, compareWithScalarFnName);
- return I != VectorDescs.end() && StringRef(I->getScalarFnName()) == funcName;
+ auto I = llvm::lower_bound(VectorDescs, funcName, compareWithScalarFnName);
+ return I != VectorDescs.end() && (*I)->getScalarFnName() == funcName;
}
StringRef TargetLibraryInfoImpl::getVectorizedFunction(StringRef F,
@@ -1422,11 +1511,10 @@ TargetLibraryInfoImpl::getVectorMappingInfo(StringRef F, const ElementCount &VF,
F = sanitizeFunctionName(F);
if (F.empty())
return nullptr;
- std::vector<VecDesc>::const_iterator I =
- llvm::lower_bound(VectorDescs, F, compareWithScalarFnName);
- while (I != VectorDescs.end() && StringRef(I->getScalarFnName()) == F) {
- if ((I->getVectorizationFactor() == VF) && (I->isMasked() == Masked))
- return &(*I);
+ auto I = llvm::lower_bound(VectorDescs, F, compareWithScalarFnName);
+ while (I != VectorDescs.end() && (*I)->getScalarFnName() == F) {
+ if (((*I)->getVectorizationFactor() == VF) && ((*I)->isMasked() == Masked))
+ return *I;
++I;
}
return nullptr;
@@ -1493,13 +1581,12 @@ void TargetLibraryInfoImpl::getWidestVF(StringRef ScalarF,
if (ScalarF.empty())
return;
- std::vector<VecDesc>::const_iterator I =
- llvm::lower_bound(VectorDescs, ScalarF, compareWithScalarFnName);
- while (I != VectorDescs.end() && StringRef(I->getScalarFnName()) == ScalarF) {
+ auto I = llvm::lower_bound(VectorDescs, ScalarF, compareWithScalarFnName);
+ while (I != VectorDescs.end() && (*I)->getScalarFnName() == ScalarF) {
ElementCount *VF =
- I->getVectorizationFactor().isScalable() ? &ScalableVF : &FixedVF;
- if (ElementCount::isKnownGT(I->getVectorizationFactor(), *VF))
- *VF = I->getVectorizationFactor();
+ (*I)->getVectorizationFactor().isScalable() ? &ScalableVF : &FixedVF;
+ if (ElementCount::isKnownGT((*I)->getVectorizationFactor(), *VF))
+ *VF = (*I)->getVectorizationFactor();
++I;
}
}
diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index 50bf4539e7984..70e5f328f2e4c 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -49,7 +49,6 @@ set(ANALYSIS_TEST_SOURCES
PluginInlineAdvisorAnalysisTest.cpp
PluginInlineOrderAnalysisTest.cpp
ProfileSummaryInfoTest.cpp
- ReplaceWithVecLibTest.cpp
ScalarEvolutionTest.cpp
SparsePropagation.cpp
TargetLibraryInfoTest.cpp
diff --git a/llvm/unittests/Analysis/ReplaceWithVecLibTest.cpp b/llvm/unittests/Analysis/ReplaceWithVecLibTest.cpp
deleted file mode 100644
index 31e0263ad64d7..0000000000000
--- a/llvm/unittests/Analysis/ReplaceWithVecLibTest.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//===--- ReplaceWithVecLibTest.cpp - replace-with-veclib unit tests -------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/ReplaceWithVeclib.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/AsmParser/Parser.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Passes/PassBuilder.h"
-#include "llvm/Support/SourceMgr.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-
-/// NOTE: Assertions must be enabled for these tests to run.
-#ifndef NDEBUG
-
-namespace {
-
-static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
- SMDiagnostic Err;
- std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
- if (!Mod)
- Err.print("ReplaceWithVecLibTest", errs());
- return Mod;
-}
-
-/// Runs ReplaceWithVecLib with different TLIIs that have custom VecDescs. This
-/// allows checking that the pass won't crash when the function to replace (from
-/// the input IR) does not match the replacement function (derived from the
-/// VecDesc mapping).
-///
-class ReplaceWithVecLibTest : public ::testing::Test {
-
- std::string getLastLine(std::string Out) {
- // remove any trailing '\n'
- if (!Out.empty() && *(Out.cend() - 1) == '\n')
- Out.pop_back();
-
- size_t LastNL = Out.find_last_of('\n');
- return (LastNL == std::string::npos) ? Out : Out.substr(LastNL + 1);
- }
-
-protected:
- LLVMContext Ctx;
-
- /// Creates TLII using the given \p VD, and then runs the ReplaceWithVeclib
- /// pass. The pass should not crash even when the replacement function
- /// (derived from the \p VD mapping) does not match the function to be
- /// replaced (from the input \p IR).
- ///
- /// \returns the last line of the standard error to be compared for
- /// correctness.
- std::string run(const VecDesc &VD, const char *IR) {
- // Create TLII and register it with FAM so it's preserved when
- // ReplaceWithVeclib pass runs.
- TargetLibraryInfoImpl TLII = TargetLibraryInfoImpl(Triple());
- TLII.addVectorizableFunctions({VD});
- FunctionAnalysisManager FAM;
- FAM.registerPass([&TLII]() { return TargetLibraryAnalysis(TLII); });
-
- // Register and run the pass on the 'foo' function from the input IR.
- FunctionPassManager FPM;
- FPM.addPass(ReplaceWithVeclib());
- std::unique_ptr<Module> M = parseIR(Ctx, IR);
- PassBuilder PB;
- PB.registerFunctionAnalyses(FAM);
-
- // Enable debugging and capture std error
- bool DebugFlagPrev = llvm::DebugFlag;
- llvm::DebugFlag = true;
- testing::internal::CaptureStderr();
- FPM.run(*M->getFunction("foo"), FAM);
- llvm::DebugFlag = DebugFlagPrev;
- return getLastLine(testing::internal::GetCapturedStderr());
- }
-};
-
-} // end anonymous namespace
-
-static const char *IR = R"IR(
-define <vscale x 4 x float> @foo(<vscale x 4 x float> %in){
- %call = call <vscale x 4 x float> @llvm.powi.f32.i32(<vscale x 4 x float> %in, i32 3)
- ret <vscale x 4 x float> %call
-}
-
-declare <vscale x 4 x float> @llvm.powi.f32.i32(<vscale x 4 x float>, i32) #0
-)IR";
-
-// The VFABI prefix in TLI describes signature which is matching the powi
-// intrinsic declaration.
-TEST_F(ReplaceWithVecLibTest, TestValidMapping) {
- VecDesc CorrectVD = {"llvm.powi.f32.i32", "_ZGVsMxvu_powi",
- ElementCount::getScalable(4), /*Masked*/ true,
- "_ZGVsMxvu", /* CC = */ std::nullopt};
- EXPECT_EQ(run(CorrectVD, IR),
- "Intrinsic calls replaced with vector libraries: 1");
-}
-
-// The VFABI prefix in TLI describes signature which is not matching the powi
-// intrinsic declaration.
-TEST_F(ReplaceWithVecLibTest, TestInvalidMapping) {
- VecDesc IncorrectVD = {"llvm.powi.f32.i32", "_ZGVsMxvv_powi",
- ElementCount::getScalable(4), /*Masked*/ true,
- "_ZGVsMxvv", /* CC = */ std::nullopt};
- EXPECT_EQ(run(IncorrectVD, IR),
- "replace-with-veclib: Will not replace: llvm.powi.f32.i32. Wrong "
- "type at index 1: i32");
-}
-#endif
>From 3248c016d8c6ec9bb2abda0a614a9b20d4e98b74 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Tue, 2 Jun 2026 15:45:26 +0000
Subject: [PATCH 2/2] better/less hacky implementation
Created using spr 1.3.8-wip
---
.../include/llvm/Analysis/TargetLibraryInfo.h | 8 +-
llvm/lib/Analysis/TargetLibraryInfo.cpp | 75 ++++++++++---------
2 files changed, 41 insertions(+), 42 deletions(-)
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 6450a8a05f8c0..ff72355bb851e 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -43,7 +43,7 @@ template <typename T> class ArrayRef;
/// <scalarname> = the name of the scalar function.
/// <vectorname> = the name of the vector function.
class VecDesc {
- friend struct VecDescBuilder;
+ template <size_t, size_t> friend struct VecDescTable;
// String offsets are relative to the this pointer.
uint16_t ScalarFnNameOff = 0;
@@ -58,11 +58,9 @@ class VecDesc {
constexpr VecDesc() {}
- // Due to the relative string offsets, VecDesc is neither copyable nor
- // movable. The move constructor has to exist to allow assignment to a
- // variable.
+ // Due to the relative string offsets, VecDesc is not copyable/movable.
VecDesc(const VecDesc &) = delete;
- VecDesc(VecDesc &&) = default;
+ VecDesc(VecDesc &&) = delete;
public:
StringRef getScalarFnName() const {
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 701c84dc99ce3..bd0cd8ba1085f 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -1257,42 +1257,44 @@ struct VecDescData {
};
namespace llvm {
-struct VecDescBuilder {
- template <size_t M, size_t N>
- static constexpr auto build(const char (&StrTab)[M],
- const VecDescData (&Data)[N]) {
- struct {
- VecDesc Descs[N];
- char StringTable[M];
-
- operator ArrayRef<VecDesc>() const { return ArrayRef(Descs, N); }
- } Ret{};
+template <size_t M, size_t N> struct VecDescTable {
+ VecDesc Descs[N];
+ char StringTable[M];
+
+ constexpr VecDescTable(const char (&StrTab)[M],
+ const VecDescData (&Data)[N]) {
for (size_t i = 0; i != M; i++)
- Ret.StringTable[i] = StrTab[i];
- size_t Off = offsetof(decltype(Ret), StringTable);
+ StringTable[i] = StrTab[i];
+ size_t Off = offsetof(VecDescTable, StringTable);
for (size_t i = 0; i != N; i++) {
assert(Off < UINT16_MAX);
- Ret.Descs[i].ScalarFnNameOff = Off;
+ Descs[i].ScalarFnNameOff = Off;
Off += Data[i].ScalarFnName.size();
- Ret.Descs[i].ScalarFnNameSize = Data[i].ScalarFnName.size();
- Ret.Descs[i].VectorFnNameOff = Off;
+ Descs[i].ScalarFnNameSize = Data[i].ScalarFnName.size();
+ Descs[i].VectorFnNameOff = Off;
Off += Data[i].VectorFnName.size();
- Ret.Descs[i].VectorFnNameSize = Data[i].VectorFnName.size();
- Ret.Descs[i].VectorizationFactor = Data[i].VectorizationFactor;
- Ret.Descs[i].Masked = Data[i].Masked;
- Ret.Descs[i].VABIPrefixOff = Off;
+ Descs[i].VectorFnNameSize = Data[i].VectorFnName.size();
+ Descs[i].VectorizationFactor = Data[i].VectorizationFactor;
+ Descs[i].Masked = Data[i].Masked;
+ Descs[i].VABIPrefixOff = Off;
Off += Data[i].VABIPrefix.size();
- Ret.Descs[i].VABIPrefixSize = Data[i].VABIPrefix.size();
- Ret.Descs[i].CC = Data[i].CC;
+ Descs[i].VABIPrefixSize = Data[i].VABIPrefix.size();
+ Descs[i].CC = Data[i].CC;
Off -= sizeof(VecDesc);
}
- return Ret;
}
+
+ operator ArrayRef<VecDesc>() const { return ArrayRef(Descs, N); }
};
+
+// Silence warning on possibly unintended CTAD.
+template <size_t N, size_t M>
+VecDescTable(const char (&)[M], const VecDescData (&)[N]) -> VecDescTable<M, N>;
+
} // namespace llvm
#define TLI_DEFINE_ACCELERATE_VECFUNCS
-static constexpr auto VecFuncs_Accelerate = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_Accelerate(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1301,7 +1303,7 @@ static constexpr auto VecFuncs_Accelerate = VecDescBuilder::build(
#undef TLI_DEFINE_ACCELERATE_VECFUNCS
#define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS
-static constexpr auto VecFuncs_DarwinLibSystemM = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_DarwinLibSystemM(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1310,7 +1312,7 @@ static constexpr auto VecFuncs_DarwinLibSystemM = VecDescBuilder::build(
#undef TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS
#define TLI_DEFINE_LIBMVEC_X86_VECFUNCS
-static constexpr auto VecFuncs_LIBMVEC_X86 = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_LIBMVEC_X86(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1319,7 +1321,7 @@ static constexpr auto VecFuncs_LIBMVEC_X86 = VecDescBuilder::build(
#undef TLI_DEFINE_LIBMVEC_X86_VECFUNCS
#define TLI_DEFINE_LIBMVEC_AARCH64_VECFUNCS
-static constexpr auto VecFuncs_LIBMVEC_AARCH64 = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_LIBMVEC_AARCH64(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX, CC) \
SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
@@ -1331,7 +1333,7 @@ static constexpr auto VecFuncs_LIBMVEC_AARCH64 = VecDescBuilder::build(
#undef TLI_DEFINE_LIBMVEC_AARCH64_VECFUNCS
#define TLI_DEFINE_MASSV_VECFUNCS
-static constexpr auto VecFuncs_MASSV = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_MASSV(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1340,7 +1342,7 @@ static constexpr auto VecFuncs_MASSV = VecDescBuilder::build(
#undef TLI_DEFINE_MASSV_VECFUNCS
#define TLI_DEFINE_SVML_VECFUNCS
-static constexpr auto VecFuncs_SVML = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_SVML(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1349,7 +1351,7 @@ static constexpr auto VecFuncs_SVML = VecDescBuilder::build(
#undef TLI_DEFINE_SVML_VECFUNCS
#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS
-static constexpr auto VecFuncs_SLEEFGNUABI_VF2 = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_SLEEFGNUABI_VF2(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1359,7 +1361,7 @@ static constexpr auto VecFuncs_SLEEFGNUABI_VF2 = VecDescBuilder::build(
});
#undef TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS
#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS
-static constexpr auto VecFuncs_SLEEFGNUABI_VF4 = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_SLEEFGNUABI_VF4(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
, {
@@ -1369,7 +1371,7 @@ static constexpr auto VecFuncs_SLEEFGNUABI_VF4 = VecDescBuilder::build(
});
#undef TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS
#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS
-static constexpr auto VecFuncs_SLEEFGNUABI_VFScalable = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_SLEEFGNUABI_VFScalable(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
@@ -1381,20 +1383,19 @@ static constexpr auto VecFuncs_SLEEFGNUABI_VFScalable = VecDescBuilder::build(
#undef TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS
#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS_RISCV
-static constexpr auto VecFuncs_SLEEFGNUABI_VFScalableRISCV =
- VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_SLEEFGNUABI_VFScalableRISCV(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
- , {
+ , {
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
{SCAL, VEC, VF, MASK, VABI_PREFIX, /* CC = */ std::nullopt},
#include "llvm/Analysis/VecFuncs.def"
- });
+ });
#undef TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS_RISCV
#define TLI_DEFINE_ARMPL_VECFUNCS
-static constexpr auto VecFuncs_ArmPL = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_ArmPL(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX, CC) \
SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
@@ -1406,7 +1407,7 @@ static constexpr auto VecFuncs_ArmPL = VecDescBuilder::build(
#undef TLI_DEFINE_ARMPL_VECFUNCS
#define TLI_DEFINE_AMDLIBM_VECFUNCS
-static constexpr auto VecFuncs_AMDLIBM = VecDescBuilder::build(
+static constexpr VecDescTable VecFuncs_AMDLIBM(
#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \
SCAL VEC VABI_PREFIX
#include "llvm/Analysis/VecFuncs.def"
More information about the llvm-commits
mailing list