[llvm-branch-commits] [llvm] RuntimeLibcalls: Dispatch to library functions from SystemRuntimeLibrary (PR #217593)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Aug 20 04:58:38 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/217593
>From 81afca9fc03474ea8640bbd99c774da6aca0d0e6 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 13 Aug 2026 16:11:18 +0200
Subject: [PATCH] RuntimeLibcalls: Dispatch to library functions from
SystemRuntimeLibrary
When a SystemRuntimeLibrary names LibcallLibrary defs, setTargetRuntimeLibcallSets
now dispatches each under an isLibraryAvailable guard, so an impl can be homed
into a library without dropping it from the target. Non-library members keep the
inline path. No target names a library yet, so output is unchanged.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
.../RuntimeLibcallEmitter-library-dispatch.td | 52 +++++++++++++++++++
.../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 41 ++++++++++++++-
2 files changed, 91 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td b/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td
new file mode 100644
index 0000000000000..7705dde4fafbb
--- /dev/null
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td
@@ -0,0 +1,52 @@
+// RUN: llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s | FileCheck %s
+
+// Check that a SystemRuntimeLibrary naming LibcallLibrary defs dispatches to
+// their setAvailableLibFuncs_<name> functions under an isLibraryAvailable guard,
+// inside the target's triple block, while bare (non-library) members are still
+// emitted inline via the flat path.
+
+include "llvm/IR/RuntimeLibcallsImpl.td"
+
+def MEMCPY : RuntimeLibcall;
+def SQRT_F64 : RuntimeLibcall;
+def EXTRA : RuntimeLibcall;
+
+def memcpy : RuntimeLibcallImpl<MEMCPY>;
+def sqrt : RuntimeLibcallImpl<SQRT_F64, "sqrt">;
+def extra : RuntimeLibcallImpl<EXTRA>;
+
+def IsX86 : LibcallPredicate<[{TT.isX86()}]>;
+def isX86 : RuntimeLibcallAvailability<(all_of IsX86)>;
+
+def Libc : LibcallLibrary<"libc", (add memcpy)>;
+def Libm : LibcallLibrary<"libm", (add sqrt)>;
+
+// Pulls two named libraries plus one bare inline member.
+def X86System : SystemRuntimeLibrary<isX86, (add Libc, Libm, extra)>;
+
+// The named libraries still get their standalone implementation functions.
+
+// CHECK: static void setAvailableLibFuncs_libc(
+// CHECK: static void setAvailableLibFuncs_libm(
+
+// The driver dispatches to each named library under its presence guard, then
+// emits the bare member (extra) inline.
+
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName, LongDoubleFormat LongDoubleFormat) {
+// CHECK: if (TT.isX86()) {
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
+// CHECK-NEXT: if (isLibraryAvailable("libc"))
+// CHECK-NEXT: setAvailableLibFuncs_libc(*this, TT, ExceptionModel, FloatABI, EABIVersion, ABIName, LongDoubleFormat);
+// CHECK-NEXT: if (isLibraryAvailable("libm"))
+// CHECK-NEXT: setAvailableLibFuncs_libm(*this, TT, ExceptionModel, FloatABI, EABIVersion, ABIName, LongDoubleFormat);
+// CHECK-EMPTY:
+// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK-NEXT: RTLIB::impl_extra, // extra
+// CHECK-NEXT: };
+// CHECK: for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
+// CHECK-NEXT: setAvailable(Impl);
+// CHECK-NEXT: }
+// CHECK: return;
+// CHECK-NEXT: }
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 2dbff92f623c0..1a90c36f2a879 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -650,6 +650,29 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
}
}
+ // Split the top-level member list into named LibcallLibrary references,
+ // which are dispatched to their own setAvailableLibFuncs_<name> function
+ // under an isLibraryAvailable guard, and the remaining (bare impl /
+ // LibcallImpls) members, which are emitted inline via the flat path below.
+ const DagInit *MemberDag =
+ R->getValueAsDef("MemberList")->getValueAsDag("MemberList");
+ SmallVector<StringRef, 4> DispatchLibs;
+ SmallVector<const Init *, 16> InlineArgs;
+ SmallVector<const StringInit *, 16> InlineArgNames;
+ for (auto [Arg, ArgName] :
+ zip_equal(MemberDag->getArgs(), MemberDag->getArgNames())) {
+ if (const auto *DI = dyn_cast<DefInit>(Arg);
+ DI && DI->getDef()->isSubClassOf("LibcallLibrary")) {
+ DispatchLibs.push_back(DI->getDef()->getValueAsString("LibraryName"));
+ continue;
+ }
+ InlineArgs.push_back(Arg);
+ InlineArgNames.push_back(ArgName);
+ }
+
+ const DagInit *InlineDag =
+ DagInit::get(MemberDag->getOperator(), InlineArgs, InlineArgNames);
+
SetTheory Sets;
DenseMap<const RuntimeLibcallImpl *,
@@ -658,8 +681,9 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>(
Libcalls, Func2Preds));
- const SetTheory::RecVec *Elements =
- Sets.expand(R->getValueAsDef("MemberList"));
+ SetTheory::RecSet ElementsSet;
+ Sets.evaluate(InlineDag, ElementsSet, R->getLoc());
+ const SetTheory::RecSet *Elements = &ElementsSet;
// Sort to get deterministic output
SetVector<PredicateWithCC> PredicateSorter;
@@ -722,6 +746,19 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
OS << "\n });\n"
" AvailableLibcallImpls = SystemAvailableImpls;\n\n";
+ // Dispatch to each named library's setup function. This must come after the
+ // SystemAvailableImpls assignment above (which overwrites the bitset); the
+ // library functions union their members in on top via setAvailable.
+ for (StringRef LibName : DispatchLibs) {
+ OS << indent(4) << "if (isLibraryAvailable(\"" << LibName << "\"))\n"
+ << indent(6) << "setAvailableLibFuncs_";
+ emitLibFuncSuffix(OS, LibName);
+ OS << "(*this, TT, ExceptionModel, FloatABI, EABIVersion, ABIName, "
+ "LongDoubleFormat);\n";
+ }
+ if (!DispatchLibs.empty())
+ OS << '\n';
+
emitPredicateGroups(OS, R, Pred2Funcs, PredicateSorter, /*BaseIndent=*/2,
/*Receiver=*/"");
More information about the llvm-branch-commits
mailing list