[llvm] [TLI] Make VecDesc statically initializable (PR #211307)
Valery Chernov via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 6 01:54:21 PDT 2026
https://github.com/vvchernov updated https://github.com/llvm/llvm-project/pull/211307
>From 0c317ca48530451b269cd12c3ea96d52bc3bdbbe Mon Sep 17 00:00:00 2001
From: Valery Chernov <vchernov at nvidia.com>
Date: Mon, 8 Jun 2026 13:20:51 +0400
Subject: [PATCH 1/2] [TLI] Make VecDesc trivially constructible for static
VecFuncs tables
After #135790, std::optional in VecDesc made the large static VecFuncs_*
tables require dynamic static initialization at DLL load time. In MSVC Debug
builds with LLVM embedded in a DLL, CRT init can run on threads with limited
stack, causing stack overflow and load failure.
Store CallingConv::ID directly and encode std::nullopt as CallingConv::C.
Mark the constructor constexpr so the tables are initialized at compile time
into .rdata. The public API is unchanged.
Add unit tests for getCallingConv() semantics, triviality static_asserts, and
constexpr static table initialization.
---
.../include/llvm/Analysis/TargetLibraryInfo.h | 19 +++++---
.../Analysis/TargetLibraryInfoTest.cpp | 48 +++++++++++++++++++
2 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 629b126db17c2..4c1d6b8ac0de6 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -48,23 +48,30 @@ class VecDesc {
ElementCount VectorizationFactor;
bool Masked;
StringRef VABIPrefix;
- std::optional<CallingConv::ID> CC;
+ /// Encoded calling convention: 0 means absent (std::nullopt), otherwise
+ /// stores CallingConv::ID + 1 so an explicit C (0) remains representable.
+ unsigned CC;
public:
VecDesc() = delete;
- VecDesc(StringRef ScalarFnName, StringRef VectorFnName,
- ElementCount VectorizationFactor, bool Masked, StringRef VABIPrefix,
- std::optional<CallingConv::ID> Conv)
+ constexpr 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) {}
+ VABIPrefix(VABIPrefix),
+ CC(Conv ? static_cast<unsigned>(*Conv) + 1u : 0u) {}
StringRef getScalarFnName() const { return ScalarFnName; }
StringRef getVectorFnName() const { return VectorFnName; }
ElementCount getVectorizationFactor() const { return VectorizationFactor; }
bool isMasked() const { return Masked; }
StringRef getVABIPrefix() const { return VABIPrefix; }
- std::optional<CallingConv::ID> getCallingConv() const { return CC; }
+ std::optional<CallingConv::ID> getCallingConv() const {
+ if (CC == 0)
+ return std::nullopt;
+ return static_cast<CallingConv::ID>(CC - 1);
+ }
/// Returns a vector function ABI variant string on the form:
/// _ZGV<isa><mask><vlen><vparams>_<scalarname>(<vectorname>)
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index afeefd36a11e7..21f4d08f79e49 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -8,12 +8,15 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
+#include <type_traits>
+
using namespace llvm;
namespace {
@@ -733,3 +736,48 @@ TEST_F(TLITestAarch64, TestFrem) {
EXPECT_EQ(getScalarName(Instruction::FRem, Type::getDoubleTy(Ctx)), "fmod");
EXPECT_EQ(getScalarName(Instruction::FRem, Type::getFloatTy(Ctx)), "fmodf");
}
+
+namespace {
+
+TEST(VecDescTest, GetCallingConvAbsent) {
+ VecDesc VD("sin", "__svml_sin2", ElementCount::getFixed(2), false,
+ "_ZGV_LLVM_N2v", std::nullopt);
+ EXPECT_FALSE(VD.getCallingConv().has_value());
+}
+
+TEST(VecDescTest, GetCallingConvC) {
+ VecDesc VD("sin", "__svml_sin2", ElementCount::getFixed(2), false,
+ "_ZGV_LLVM_N2v", CallingConv::C);
+ ASSERT_TRUE(VD.getCallingConv().has_value());
+ EXPECT_EQ(VD.getCallingConv().value(), CallingConv::C);
+}
+
+TEST(VecDescTest, GetCallingConvAArch64VectorCall) {
+ VecDesc VD("acos", "armpl_vacosq_f64", ElementCount::getFixed(2), false,
+ "_ZGV_LLVM_N2v", CallingConv::AArch64_VectorCall);
+ ASSERT_TRUE(VD.getCallingConv().has_value());
+ EXPECT_EQ(VD.getCallingConv().value(), CallingConv::AArch64_VectorCall);
+}
+
+static_assert(std::is_trivially_destructible_v<VecDesc>,
+ "VecDesc must not require dynamic static initialization");
+static_assert(std::is_trivially_copyable_v<VecDesc>,
+ "VecDesc static tables must be constexpr-friendly");
+
+TEST(VecDescTest, ConstexprStaticTable) {
+ static constexpr VecDesc Table[] = {
+ {"ceilf", "vceilf", ElementCount::getFixed(4), false, "_ZGV_LLVM_N4v",
+ std::nullopt},
+ {"sin", "__svml_sin2", ElementCount::getFixed(2), false, "_ZGV_LLVM_N2v",
+ CallingConv::C},
+ {"acos", "armpl_vacosq_f64", ElementCount::getFixed(2), false,
+ "_ZGV_LLVM_N2v", CallingConv::AArch64_VectorCall},
+ };
+ EXPECT_FALSE(Table[0].getCallingConv().has_value());
+ ASSERT_TRUE(Table[1].getCallingConv().has_value());
+ EXPECT_EQ(Table[1].getCallingConv().value(), CallingConv::C);
+ ASSERT_TRUE(Table[2].getCallingConv().has_value());
+ EXPECT_EQ(Table[2].getCallingConv().value(), CallingConv::AArch64_VectorCall);
+}
+
+} // namespace
>From 9092655cc0d3f6420cb4cfe9f25fc2ca31a76d8c Mon Sep 17 00:00:00 2001
From: Valery Chernov <vchernov at nvidia.com>
Date: Thu, 6 Aug 2026 12:53:29 +0400
Subject: [PATCH 2/2] update comment
---
llvm/include/llvm/Analysis/TargetLibraryInfo.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 4c1d6b8ac0de6..aaab22a253027 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -50,6 +50,9 @@ class VecDesc {
StringRef VABIPrefix;
/// Encoded calling convention: 0 means absent (std::nullopt), otherwise
/// stores CallingConv::ID + 1 so an explicit C (0) remains representable.
+ /// TODO: Since C++20 standard becomes default in LLVM we can return back to
+ /// use std::optional<CallingConv::ID> instead of unsigned and value_or()
+ /// in default constructor.
unsigned CC;
public:
More information about the llvm-commits
mailing list