[llvm-branch-commits] [llvm] RuntimeLibcalls: Require system library members to be libraries (PR #230306)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 9 01:02:18 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/230306

>From a357cd0bfa3006ed9124eebb99ed851ae20d86ac Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 9 Oct 2026 00:33:51 +0200
Subject: [PATCH] RuntimeLibcalls: Require system library members to be
 libraries

Every SystemRuntimeLibrary now lists only LibcallLibrary and LibraryRef
members, so the inline path that expanded unhomed RuntimeLibcallImpl members
directly into the system's block, including its SystemAvailableImpls
bitset, is dead. Remove it, and error on any member that is not a
library. The generated RuntimeLibcalls.inc is unchanged.

Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
 llvm/include/llvm/IR/RuntimeLibcallsImpl.td   |   9 +-
 ...lEmitter-bad-system-library-entry-error.td |  21 +-
 .../RuntimeLibcallEmitter-calling-conv.td     | 179 +++++++-------
 .../RuntimeLibcallEmitter-library-dispatch.td |  24 +-
 .../RuntimeLibcallEmitter-library-ref.td      |   2 -
 .../RuntimeLibcallEmitter-multiple-impls.td   |  62 +----
 ...eLibcallEmitter-nested-predicates-error.td |   4 +-
 ...RuntimeLibcallEmitter-predicate-cc-sort.td |   5 +-
 ...timeLibcallEmitter-predicate-dag-errors.td |   4 +-
 .../RuntimeLibcallEmitter-predicate-dag.td    |   5 +-
 llvm/test/TableGen/RuntimeLibcallEmitter.td   | 226 +++++++++---------
 .../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 135 ++---------
 12 files changed, 269 insertions(+), 407 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td
index f6a10a9ba59379..8eda649dc6c816 100644
--- a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td
+++ b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td
@@ -152,8 +152,8 @@ class LibcallsWithCC<dag funcList, LibcallCallingConv CC,
   LibcallCallingConv CallingConv = CC;
 }
 
-// A named runtime library whose Impls are made available as a unit. Impls use
-// the same dag vocabulary as SystemRuntimeLibrary.
+// A named runtime library whose Impls are made available as a unit. Impls is a
+// set of RuntimeLibcallImpls, optionally grouped with LibcallImpls.
 class LibcallLibrary<string name, dag impls,
                      RuntimeLibcallAvailability pred = AlwaysAvailable> {
   string LibraryName = name;
@@ -180,9 +180,10 @@ class LibraryRef<LibcallLibrary lib, list<RuntimeLibcallImpl> exclude = []> {
   list<RuntimeLibcallImpl> Exclude = exclude;
 }
 
-/// Define a complete top level set of runtime libcalls for a target.
+/// Define a complete top level set of runtime libcalls for a target. Every
+/// member of funcList must be a LibcallLibrary or LibraryRef.
 class SystemRuntimeLibrary<RuntimeLibcallAvailability Pred, dag funcList> {
-  /// Set the default calling convention assumed for RuntimeLibcallImpl members.
+  /// Set the default calling convention assumed for library members.
   LibcallCallingConv DefaultLibcallCallingConv = DefaultCC;
   RuntimeLibcallAvailability TriplePred = Pred;
   LibcallImpls MemberList = LibcallImpls<funcList>;
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-bad-system-library-entry-error.td b/llvm/test/TableGen/RuntimeLibcallEmitter-bad-system-library-entry-error.td
index d546fefde31a09..cc15a880a65ea0 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-bad-system-library-entry-error.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-bad-system-library-entry-error.td
@@ -1,4 +1,5 @@
-// RUN: not llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s 2>&1 | FileCheck %s
+// RUN: not llvm-tblgen -gen-runtime-libcalls -I %p/../../include -DERR_SYSTEM_MEMBER %s 2>&1 | FileCheck -check-prefix=SYSTEM %s
+// RUN: not llvm-tblgen -gen-runtime-libcalls -I %p/../../include -DERR_LIBRARY_MEMBER %s 2>&1 | FileCheck -check-prefix=LIBRARY %s
 
 include "llvm/IR/RuntimeLibcallsImpl.td"
 
@@ -8,11 +9,19 @@ def func_a : RuntimeLibcallImpl<SOME_FUNC>;
 def IsTargetArchA : LibcallPredicate<[{isTargetArchA()}]>;
 def isTargetArchA : RuntimeLibcallAvailability<(all_of IsTargetArchA)>;
 
-// CHECK: [[@LINE+4]]:5: error: entry for SystemLibrary is not a RuntimeLibcallImpl
-// CHECK-NEXT: def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
-// CHECK: note: invalid entry `SOME_FUNC`
-// CHECK-NEXT: def SOME_FUNC : RuntimeLibcall;
+#ifdef ERR_SYSTEM_MEMBER
+// SYSTEM: [[@LINE+2]]:5: error: SystemRuntimeLibrary member `func_a` is not a LibcallLibrary or LibraryRef
+// SYSTEM-NEXT: def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
 def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
-  (add SOME_FUNC)
+  (add func_a)
 >;
+#endif
 
+#ifdef ERR_LIBRARY_MEMBER
+// LIBRARY: [[@LINE+4]]:5: error: entry for LibcallLibrary is not a RuntimeLibcallImpl
+// LIBRARY-NEXT: def Libc : LibcallLibrary<"libc", (add SOME_FUNC)>;
+// LIBRARY: note: invalid entry `SOME_FUNC`
+// LIBRARY-NEXT: def SOME_FUNC : RuntimeLibcall;
+def Libc : LibcallLibrary<"libc", (add SOME_FUNC)>;
+def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA, (add Libc)>;
+#endif
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
index 250ef6c9e75fc6..20a28aeac183dd 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
@@ -26,123 +26,114 @@ def isAVR : RuntimeLibcallAvailability<(all_of IsAVR)>;
 
 def isAVRHurd : RuntimeLibcallAvailability<(all_of IsAVR, IsOSHurd)>;
 
-def AVRLibrary : SystemRuntimeLibrary<isAVR,
-  (add malloc, LibcallsWithCC<(add __divmodqi4, __udivmodhi4), AVR_BUILTIN>)
->;
+def isMSP430 : RuntimeLibcallAvailability<(all_of IsMSP430)>;
+
+def Libc : LibcallLibrary<"libc", (add malloc)>;
+
+def AVRCompilerRt : LibcallLibrary<"compiler-rt",
+  (add LibcallsWithCC<(add __divmodqi4, __udivmodhi4), AVR_BUILTIN>), isAVR>;
+
+def MSP430CompilerRt : LibcallLibrary<"compiler-rt",
+  (add LibcallsWithCC<(add __divmodqi4), AVR_BUILTIN, RuntimeLibcallAvailability<(all_of IsFooLeaf)>>,
+       LibcallsWithCC<(add __udivmodhi4), MSP430_BUILTIN, RuntimeLibcallAvailability<(all_of IsBarLeaf)>>),
+  isMSP430>;
+
+def AVRLibrary : SystemRuntimeLibrary<isAVR, (add Libc, AVRCompilerRt)>;
 
 // Test with default calling convention
-def AVRHurdLibrary : SystemRuntimeLibrary<isAVRHurd,
-  (add malloc, LibcallsWithCC<(add __divmodqi4, __udivmodhi4), AVR_BUILTIN>)> {
+def AVRHurdLibrary : SystemRuntimeLibrary<isAVRHurd, (add Libc, AVRCompilerRt)> {
   let DefaultLibcallCallingConv
     = LibcallCallingConv<[{isFoo() ? CallingConv::Fast : CallingConv::GHC}]>;
 }
 
-def isMSP430 : RuntimeLibcallAvailability<(all_of IsMSP430)>;
-
 def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
-  (add malloc,
-       LibcallsWithCC<(add __divmodqi4), AVR_BUILTIN, RuntimeLibcallAvailability<(all_of IsFooLeaf)>>,
-       LibcallsWithCC<(add __udivmodhi4), MSP430_BUILTIN, RuntimeLibcallAvailability<(all_of IsBarLeaf)>>)
->;
-
+  (add Libc, MSP430CompilerRt)>;
 
-// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, StringRef ABIName, LongDoubleFormat LongDoubleFormat) {
-// CHECK: if (TT.getArch() == Triple::avr && TT.isOSHurd()) {
-// CHECK-NEXT:   const CallingConv::ID DefaultCC = isFoo() ? CallingConv::Fast : CallingConv::GHC;
-// CHECK-NEXT:   for (CallingConv::ID &Entry : LibcallImplCallingConvs) {
-// CHECK-NEXT:     Entry = DefaultCC;
-// CHECK-NEXT:   }
-// CHECK-EMPTY:
-// CHECK-NEXT:   static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:     0x0000000000001a
-// CHECK-NEXT:   });
-// CHECK-NEXT:   AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl_malloc, // malloc
-// CHECK-NEXT:    };
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_compiler_rt(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, StringRef ABIName, LongDoubleFormat LongDoubleFormat, CallingConv::ID DefaultCC) {
+// CHECK-NEXT:   if (TT.getArch() == Triple::avr) {
+// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls_AlwaysAvailable_AVR_BUILTIN[] = {
+// CHECK-NEXT:         RTLIB::impl___divmodqi4, // __divmodqi4
+// CHECK-NEXT:         RTLIB::impl___udivmodhi4, // __udivmodhi4
+// CHECK-NEXT:     };
+// CHECK-EMPTY:
+// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls_AlwaysAvailable_AVR_BUILTIN) {
+// CHECK-NEXT:       setAvailable(Impl);
+// CHECK-NEXT:       setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN);
+// CHECK-NEXT:     }
 // CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
+// CHECK-NEXT:   }
+// CHECK-NEXT:   if (TT.getArch() == Triple::msp430) {
+// CHECK-NEXT:     if ( isFoo() ) {
+// CHECK-NEXT:       static const RTLIB::LibcallImpl LibraryCalls_anonymous_1_AVR_BUILTIN[] = {
+// CHECK-NEXT:           RTLIB::impl___divmodqi4, // __divmodqi4
+// CHECK-NEXT:       };
 // CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls_AlwaysAvailable_AVR_BUILTIN[] = {
-// CHECK-NEXT:        RTLIB::impl___divmodqi4, // __divmodqi4
-// CHECK-NEXT:        RTLIB::impl___udivmodhi4, // __udivmodhi4
-// CHECK-NEXT:    };
+// CHECK-NEXT:       for (const RTLIB::LibcallImpl Impl : LibraryCalls_anonymous_1_AVR_BUILTIN) {
+// CHECK-NEXT:         setAvailable(Impl);
+// CHECK-NEXT:         setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN);
+// CHECK-NEXT:       }
 // CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls_AlwaysAvailable_AVR_BUILTIN) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:      setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN);
-// CHECK-NEXT:    }
+// CHECK-NEXT:     }
 // CHECK-EMPTY:
-// CHECK-NEXT:    return;
-// CHECK-NEXT:  }
+// CHECK-NEXT:     if ( isBar() ) {
+// CHECK-NEXT:       static const RTLIB::LibcallImpl LibraryCalls_anonymous_3_MSP430_BUILTIN[] = {
+// CHECK-NEXT:           RTLIB::impl___udivmodhi4, // __udivmodhi4
+// CHECK-NEXT:       };
 // CHECK-EMPTY:
-// CHECK-NEXT: if (TT.getArch() == Triple::avr) {
-// CHECK-NEXT:   static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:     0x0000000000001a
-// CHECK-NEXT:   });
-// CHECK-NEXT:   AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-NEXT:       for (const RTLIB::LibcallImpl Impl : LibraryCalls_anonymous_3_MSP430_BUILTIN) {
+// CHECK-NEXT:         setAvailable(Impl);
+// CHECK-NEXT:         setLibcallImplCallingConv(Impl, CallingConv::MSP430_BUILTIN);
+// CHECK-NEXT:       }
 // CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl_malloc, // malloc
-// CHECK-NEXT:    };
+// CHECK-NEXT:     }
 // CHECK-EMPTY:
-// CHECK-NEXT:   for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:     setAvailable(Impl);
 // CHECK-NEXT:   }
+// CHECK-NEXT: }
+
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libc(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, StringRef ABIName, LongDoubleFormat LongDoubleFormat, CallingConv::ID DefaultCC) {
+// CHECK-NEXT:   {
+// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK-NEXT:         RTLIB::impl_malloc, // malloc
+// CHECK-NEXT:     };
 // CHECK-EMPTY:
-// CHECK-NEXT:   static const RTLIB::LibcallImpl LibraryCalls_AlwaysAvailable_AVR_BUILTIN[] = {
-// CHECK-NEXT:       RTLIB::impl___divmodqi4, // __divmodqi4
-// CHECK-NEXT:       RTLIB::impl___udivmodhi4, // __udivmodhi4
-// CHECK-NEXT:   };
+// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
+// CHECK-NEXT:       setAvailable(Impl);
+// CHECK-NEXT:     }
 // CHECK-EMPTY:
-// CHECK-NEXT:   for (const RTLIB::LibcallImpl Impl : LibraryCalls_AlwaysAvailable_AVR_BUILTIN) {
-// CHECK-NEXT:     setAvailable(Impl);
-// CHECK-NEXT:     setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN);
 // CHECK-NEXT:   }
+// CHECK-NEXT: }
+
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, StringRef ABIName, LongDoubleFormat LongDoubleFormat) {
 // CHECK-EMPTY:
-// CHECK-NEXT:   return;
-// CHECK-NEXT:  }
-// CHECK-EMPTY:
-// CHECK-NEXT:  if (TT.getArch() == Triple::msp430) {
-// CHECK-NEXT:    static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:      0x00000000000010
-// CHECK-NEXT:    });
-// CHECK-NEXT:    AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl_malloc, // malloc
-// CHECK-NEXT:    };
-// CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:    if ( isFoo() ) {
-// CHECK-NEXT:      static const RTLIB::LibcallImpl LibraryCalls_anonymous_3_AVR_BUILTIN[] = {
-// CHECK-NEXT:          RTLIB::impl___divmodqi4, // __divmodqi4
-// CHECK-NEXT:      };
+// CHECK-NEXT:   if (TT.getArch() == Triple::avr && TT.isOSHurd()) {
+// CHECK-NEXT:     const CallingConv::ID DefaultCC = isFoo() ? CallingConv::Fast : CallingConv::GHC;
+// CHECK-NEXT:     for (CallingConv::ID &Entry : LibcallImplCallingConvs) {
+// CHECK-NEXT:       Entry = DefaultCC;
+// CHECK-NEXT:     }
 // CHECK-EMPTY:
-// CHECK-NEXT:      for (const RTLIB::LibcallImpl Impl : LibraryCalls_anonymous_3_AVR_BUILTIN) {
-// CHECK-NEXT:        setAvailable(Impl);
-// CHECK-NEXT:        setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN);
-// CHECK-NEXT:      }
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, DefaultCC);
+// CHECK-NEXT:     if (isLibraryAvailable("compiler-rt"))
+// CHECK-NEXT:       setAvailableLibFuncs_compiler_rt(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, DefaultCC);
 // CHECK-EMPTY:
-// CHECK-NEXT:    }
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
 // CHECK-EMPTY:
-// CHECK-NEXT:    if ( isBar() ) {
-// CHECK-NEXT:      static const RTLIB::LibcallImpl LibraryCalls_anonymous_5_MSP430_BUILTIN[] = {
-// CHECK-NEXT:          RTLIB::impl___udivmodhi4, // __udivmodhi4
-// CHECK-NEXT:      };
+// CHECK-NEXT:   if (TT.getArch() == Triple::avr) {
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
+// CHECK-NEXT:     if (isLibraryAvailable("compiler-rt"))
+// CHECK-NEXT:       setAvailableLibFuncs_compiler_rt(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-EMPTY:
-// CHECK-NEXT:      for (const RTLIB::LibcallImpl Impl : LibraryCalls_anonymous_5_MSP430_BUILTIN) {
-// CHECK-NEXT:        setAvailable(Impl);
-// CHECK-NEXT:        setLibcallImplCallingConv(Impl, CallingConv::MSP430_BUILTIN);
-// CHECK-NEXT:      }
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
 // CHECK-EMPTY:
-// CHECK-NEXT:    }
+// CHECK-NEXT:   if (TT.getArch() == Triple::msp430) {
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
+// CHECK-NEXT:     if (isLibraryAvailable("compiler-rt"))
+// CHECK-NEXT:       setAvailableLibFuncs_compiler_rt(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-EMPTY:
-// CHECK-NEXT:    return;
-// CHECK-NEXT:  }
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
+// CHECK-NEXT:   LLVM_DEBUG(dbgs() << "no system runtime library applied to target \'" << TT.str() << "\'\n");
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td b/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td
index 0afe356f5be6cd..ae0db2f7e741ea 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-library-dispatch.td
@@ -2,18 +2,15 @@
 
 // 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.
+// inside the target's triple block.
 
 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)>;
@@ -21,32 +18,17 @@ 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.
+def X86System : SystemRuntimeLibrary<isX86, (add Libc, Libm)>;
 
 // CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libc(
 // CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::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, 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(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-NEXT:     if (isLibraryAvailable("libm"))
 // CHECK-NEXT:       setAvailableLibFuncs_libm(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // 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:     return;
 // CHECK-NEXT:   }
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-library-ref.td b/llvm/test/TableGen/RuntimeLibcallEmitter-library-ref.td
index e98517a9191c5b..9a6a42c94f6794 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-library-ref.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-library-ref.td
@@ -44,8 +44,6 @@ def X86System : SystemRuntimeLibrary<isX86,
 // The dispatcher is a plain call for both libraries; no setUnavailable here.
 // CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(
 // CHECK:   if (TT.isX86()) {
-// CHECK: AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
 // CHECK-NEXT:     if (isLibraryAvailable("compiler-rt"))
 // CHECK-NEXT:       setAvailableLibFuncs_compiler_rt(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-NEXT:     if (isLibraryAvailable("libm"))
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td b/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td
index 4fd713bd158dc4..815ebea4ec28af 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td
@@ -29,59 +29,27 @@ def dup1 : RuntimeLibcallImpl<ANOTHER_DUP>;
 
 // func_a and func_b both provide SOME_FUNC.
 
-// CHECK: if (isTargetArchA()) {
-// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:   0x00000000000018
-// CHECK-NEXT: });
-// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_liba(
+// CHECK:    static const RTLIB::LibcallImpl LibraryCalls[] = {
 // CHECK-NEXT:        RTLIB::impl_func_a, // func_a
 // CHECK-NEXT:        RTLIB::impl_func_b, // func_b
 // CHECK-NEXT:    };
-// CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:    return;
-// CHECK-NEXT:  }
 
-def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
-  (add func_b, func_a)
->;
+def LibA : LibcallLibrary<"liba", (add func_b, func_a)>;
+def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA, (add LibA)>;
 
-// CHECK: if (isTargetArchB()) {
-// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:   0x00000000000058
-// CHECK-NEXT: });
-// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libb(
+// CHECK:    static const RTLIB::LibcallImpl LibraryCalls[] = {
 // CHECK-NEXT:        RTLIB::impl_other_func, // other_func
 // CHECK-NEXT:        RTLIB::impl_func_a, // func_a
 // CHECK-NEXT:        RTLIB::impl_func_b, // func_b
 // CHECK-NEXT:    };
-// CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:    return;
-// CHECK-NEXT:  }
 
-def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
-  (add func_a, other_func, func_b)
->;
+def LibB : LibcallLibrary<"libb", (add func_a, other_func, func_b)>;
+def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB, (add LibB)>;
 
-// CHECK: if (isTargetArchC()) {
-// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:   0x0000000000007e
-// CHECK-NEXT: });
-// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libc(
+// CHECK:     static const RTLIB::LibcallImpl LibraryCalls[] = {
 // CHECK-NEXT:         RTLIB::impl_dup0, // dup0
 // CHECK-NEXT:         RTLIB::impl_dup1, // dup1
 // CHECK-NEXT:         RTLIB::impl_other_func, // other_func
@@ -89,14 +57,8 @@ def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
 // CHECK-NEXT:         RTLIB::impl_func_b, // func_b
 // CHECK-NEXT:         RTLIB::impl_func_c, // func_c
 // CHECK-NEXT:     };
-// CHECK-EMPTY:
-// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:       setAvailable(Impl);
-// CHECK-NEXT:     }
-// CHECK-EMPTY:
-// CHECK-NEXT:    return;
-// CHECK-NEXT:  }
 
-def TheSystemLibraryC : SystemRuntimeLibrary<isTargetArchC,
+def LibC : LibcallLibrary<"libc",
   (add func_a, dup1, other_func, func_b, func_c, dup0)
 >;
+def TheSystemLibraryC : SystemRuntimeLibrary<isTargetArchC, (add LibC)>;
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td b/llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td
index 63588ef89daa50..5d3c982f3d456f 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-nested-predicates-error.td
@@ -17,6 +17,8 @@ def func0 : RuntimeLibcallImpl<FUNC0>;
 def func1 : RuntimeLibcallImpl<FUNC1>;
 
 // ERR: :[[@LINE+2]]:8: error: combining nested libcall set predicates currently unhandled
-def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
+def Libc : LibcallLibrary<"libc",
   (add LibcallImpls<(add func0, LibcallImpls<(add func1), isBar>), isFoo>)
 >;
+
+def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch, (add Libc)>;
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-cc-sort.td b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-cc-sort.td
index 6596c2b62e46e2..ba370ec98730c7 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-cc-sort.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-cc-sort.td
@@ -15,13 +15,16 @@ def impl_default : RuntimeLibcallImpl<FUNC_DEFAULT>;
 def IsWin : LibcallPredicate<[{TT.isOSWindows()}]>;
 def isWin : RuntimeLibcallAvailability<(all_of IsWin)>;
 
-def WinLibrary : SystemRuntimeLibrary<isWin,
+def WinLibc : LibcallLibrary<"libc",
   (add LibcallsWithCC<(add impl_aapcs), ARM_AAPCS, isWin>,
        LibcallImpls<(add impl_default), isWin>)
 >;
 
+def WinLibrary : SystemRuntimeLibrary<isWin, (add WinLibc)>;
+
 // The ARM_AAPCS group sorts after the default-CC group (empty calling
 // convention name orders before "ARM_AAPCS").
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libc(
 // CHECK: if (TT.isOSWindows()) {
 // CHECK:   static const RTLIB::LibcallImpl LibraryCalls_isWin[] = {
 // CHECK-NEXT:       RTLIB::impl_impl_default, // impl_default
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag-errors.td b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag-errors.td
index 5df0c201365124..a901819d6d6258 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag-errors.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag-errors.td
@@ -39,5 +39,5 @@ def badpred : RuntimeLibcallAvailability<(not IsA, IsB)>;
 def badpred : RuntimeLibcallAvailability<(all_of)>;
 #endif
 
-def Sys : SystemRuntimeLibrary<isArch,
-  (add LibcallImpls<(add impl0), badpred>)>;
+def Libc : LibcallLibrary<"libc", (add LibcallImpls<(add impl0), badpred>)>;
+def Sys : SystemRuntimeLibrary<isArch, (add Libc)>;
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
index d7e8cf5c28d044..960ba602b0b144 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-predicate-dag.td
@@ -48,7 +48,7 @@ def isNotX86_32 : RuntimeLibcallAvailability<(not IsX86_32)>;
 def IsTargetArch : LibcallPredicate<[{isTargetArch()}]>;
 def isTargetArch : RuntimeLibcallAvailability<(all_of IsTargetArch)>;
 
-def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
+def Libc : LibcallLibrary<"libc",
   (add LibcallImpls<(add impl0), isAArch64_ExceptArm64EC>,
        LibcallImpls<(add impl1), isDarwinOrGNU>,
        LibcallImpls<(add impl2), isNotDarwin>,
@@ -57,8 +57,11 @@ def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
        LibcallImpls<(add impl5), isNotX86_32>)
 >;
 
+def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch, (add Libc)>;
+
 // Predicate groups emit sorted by predicate def name
 
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libc(
 // CHECK: if (TT.isAArch64() && (TT.isOSDarwin() || TT.isGNUEnvironment()) && !(TT.isWindowsArm64EC())) {
 // CHECK: RTLIB::impl_impl3
 // CHECK: if (TT.isAArch64() || !(TT.isOSDarwin() || TT.isGNUEnvironment())) {
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index 73b0fa3ab51da8..1de89119e8908b 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -58,15 +58,19 @@ def isBlahArch : RuntimeLibcallAvailability<(all_of IsBlahArch)>;
 def hasCompilerRT : RuntimeLibcallAvailability<(all_of HasCompilerRT)>;
 
 
-def SimpleLibrary : SystemRuntimeLibrary<isSimpleArch,
-  (add LibmLibcalls, calloc, CompilerRTLibcalls)>;
+def SimpleLibc : LibcallLibrary<"libc",
+  (add LibmLibcalls, calloc, CompilerRTLibcalls), isSimpleArch>;
+def SimpleLibrary : SystemRuntimeLibrary<isSimpleArch, (add SimpleLibc)>;
 
 
 def LibraryWithConditionalFunc : LibcallImpls<(add sqrtl_f128, bzero, AvailableIf<___memset, isBarOS>)>;
 
-def FooLibrary : SystemRuntimeLibrary<isFooArch, (add LibraryWithConditionalFunc)>;
+def FooLibc : LibcallLibrary<"libc", (add LibraryWithConditionalFunc), isFooArch>;
+def FooLibrary : SystemRuntimeLibrary<isFooArch, (add FooLibc)>;
 
-def BuzzLibrary : SystemRuntimeLibrary<isBuzzArch, (add sqrtl_f80, CompilerRTLibcalls)>;
+def BuzzLibc : LibcallLibrary<"libc", (add sqrtl_f80, CompilerRTLibcalls),
+                           isBuzzArch>;
+def BuzzLibrary : SystemRuntimeLibrary<isBuzzArch, (add BuzzLibc)>;
 
 
 
@@ -75,7 +79,10 @@ def LibraryWithConditionalSet : LibcallImpls<(add sqrtl_f128, bzero,
 
 
 
-def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithConditionalSet, AvailableIf<___memset, isBarOS>)>;
+def BlahLibc : LibcallLibrary<"libc",
+  (add calloc, LibraryWithConditionalSet, AvailableIf<___memset, isBarOS>),
+  isBlahArch>;
+def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add BlahLibc)>;
 
 
 
@@ -264,118 +271,121 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // CHECK-EMPTY:
 // CHECK-NEXT:#endif // GET_INIT_RUNTIME_LIBCALL_SIGNATURES
 
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libc(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, StringRef ABIName, LongDoubleFormat LongDoubleFormat, CallingConv::ID DefaultCC) {
+// CHECK-NEXT:   if (TT.getArch() == Triple::blah) {
+// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK-NEXT:         RTLIB::impl_bzero, // bzero
+// CHECK-NEXT:         RTLIB::impl_calloc, // calloc
+// CHECK-NEXT:         RTLIB::impl_sqrtl_f128, // sqrtl
+// CHECK-NEXT:     };
+// CHECK-EMPTY:
+// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
+// CHECK-NEXT:       setAvailable(Impl);
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:     if (TT.hasCompilerRT()) {
+// CHECK-NEXT:       static const RTLIB::LibcallImpl LibraryCalls_hasCompilerRT[] = {
+// CHECK-NEXT:           RTLIB::impl___ashlsi3, // __ashlsi3
+// CHECK-NEXT:           RTLIB::impl___lshrdi3, // __lshrdi3
+// CHECK-NEXT:       };
+// CHECK-EMPTY:
+// CHECK-NEXT:       for (const RTLIB::LibcallImpl Impl : LibraryCalls_hasCompilerRT) {
+// CHECK-NEXT:         setAvailable(Impl);
+// CHECK-NEXT:       }
+// CHECK-EMPTY:
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:     if (TT.getOS() == Triple::bar) {
+// CHECK-NEXT:       static const RTLIB::LibcallImpl LibraryCalls_isBarOS[] = {
+// CHECK-NEXT:           RTLIB::impl____memset, // ___memset
+// CHECK-NEXT:       };
+// CHECK-EMPTY:
+// CHECK-NEXT:       for (const RTLIB::LibcallImpl Impl : LibraryCalls_isBarOS) {
+// CHECK-NEXT:         setAvailable(Impl);
+// CHECK-NEXT:       }
+// CHECK-EMPTY:
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:   }
+// CHECK-NEXT:   if (TT.getArch() == Triple::buzz) {
+// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK-NEXT:         RTLIB::impl___ashlsi3, // __ashlsi3
+// CHECK-NEXT:         RTLIB::impl_sqrtl_f80, // sqrtl
+// CHECK-NEXT:         RTLIB::impl___lshrdi3, // __lshrdi3
+// CHECK-NEXT:     };
+// CHECK-EMPTY:
+// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
+// CHECK-NEXT:       setAvailable(Impl);
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:   }
+// CHECK-NEXT:   if (TT.getArch() == Triple::foo) {
+// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK-NEXT:         RTLIB::impl_bzero, // bzero
+// CHECK-NEXT:         RTLIB::impl_sqrtl_f128, // sqrtl
+// CHECK-NEXT:     };
+// CHECK-EMPTY:
+// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
+// CHECK-NEXT:       setAvailable(Impl);
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:     if (TT.getOS() == Triple::bar) {
+// CHECK-NEXT:       static const RTLIB::LibcallImpl LibraryCalls_isBarOS[] = {
+// CHECK-NEXT:           RTLIB::impl____memset, // ___memset
+// CHECK-NEXT:       };
+// CHECK-EMPTY:
+// CHECK-NEXT:       for (const RTLIB::LibcallImpl Impl : LibraryCalls_isBarOS) {
+// CHECK-NEXT:         setAvailable(Impl);
+// CHECK-NEXT:       }
+// CHECK-EMPTY:
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:   }
+// CHECK-NEXT:   if (TT.getArch() == Triple::simple) {
+// CHECK-NEXT:     static const RTLIB::LibcallImpl LibraryCalls[] = {
+// CHECK-NEXT:         RTLIB::impl_calloc, // calloc
+// CHECK-NEXT:         RTLIB::impl___ashlsi3, // __ashlsi3
+// CHECK-NEXT:         RTLIB::impl_sqrtl_f80, // sqrtl
+// CHECK-NEXT:         RTLIB::impl___lshrdi3, // __lshrdi3
+// CHECK-NEXT:     };
+// CHECK-EMPTY:
+// CHECK-NEXT:     for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
+// CHECK-NEXT:       setAvailable(Impl);
+// CHECK-NEXT:     }
+// CHECK-EMPTY:
+// CHECK-NEXT:   }
+// CHECK-NEXT: }
+
 // CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, StringRef ABIName, LongDoubleFormat LongDoubleFormat) {
 // CHECK-EMPTY:
-// CHECK-NEXT: if (TT.getArch() == Triple::blah) {
-// CHECK-NEXT:     static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:       0x000000000000e0
-// CHECK-NEXT:     });
-// CHECK-NEXT:     AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl_bzero, // bzero
-// CHECK-NEXT:        RTLIB::impl_calloc, // calloc
-// CHECK-NEXT:        RTLIB::impl_sqrtl_f128, // sqrtl
-// CHECK-NEXT:    };
-// CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:    if (TT.hasCompilerRT()) {
-// CHECK-NEXT:      static const RTLIB::LibcallImpl LibraryCalls_hasCompilerRT[] = {
-// CHECK-NEXT:          RTLIB::impl___ashlsi3, // __ashlsi3
-// CHECK-NEXT:          RTLIB::impl___lshrdi3, // __lshrdi3
-// CHECK-NEXT:      };
-// CHECK-EMPTY:
-// CHECK-NEXT:      for (const RTLIB::LibcallImpl Impl : LibraryCalls_hasCompilerRT) {
-// CHECK-NEXT:        setAvailable(Impl);
-// CHECK-NEXT:      }
+// CHECK-NEXT:   if (TT.getArch() == Triple::blah) {
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-EMPTY:
-// CHECK-NEXT:    }
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
 // CHECK-EMPTY:
-// CHECK-NEXT:    if (TT.getOS() == Triple::bar) {
-// CHECK-NEXT:      static const RTLIB::LibcallImpl LibraryCalls_isBarOS[] = {
-// CHECK-NEXT:          RTLIB::impl____memset, // ___memset
-// CHECK-NEXT:      };
+// CHECK-NEXT:   if (TT.getArch() == Triple::buzz) {
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-EMPTY:
-// CHECK-NEXT:      for (const RTLIB::LibcallImpl Impl : LibraryCalls_isBarOS) {
-// CHECK-NEXT:        setAvailable(Impl);
-// CHECK-NEXT:      }
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
 // CHECK-EMPTY:
-// CHECK-NEXT:    }
+// CHECK-NEXT:   if (TT.getArch() == Triple::foo) {
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-EMPTY:
-// CHECK-NEXT:   return;
-// CHECK-NEXT: }
-// CHECK-EMPTY:
-// CHECK-NEXT: if (TT.getArch() == Triple::buzz) {
-// CHECK-NEXT:    static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:      0x00000000000118
-// CHECK-NEXT:    });
-// CHECK-NEXT:    AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl___ashlsi3, // __ashlsi3
-// CHECK-NEXT:        RTLIB::impl_sqrtl_f80, // sqrtl
-// CHECK-NEXT:        RTLIB::impl___lshrdi3, // __lshrdi3
-// CHECK-NEXT:    };
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
 // CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
+// CHECK-NEXT:   if (TT.getArch() == Triple::simple) {
+// CHECK-NEXT:     if (isLibraryAvailable("libc"))
+// CHECK-NEXT:       setAvailableLibFuncs_libc(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, CallingConv::C);
 // CHECK-EMPTY:
-// CHECK-NEXT:   return;
-// CHECK-NEXT: }
-// CHECK-EMPTY:
-// CHECK-NEXT: if (TT.getArch() == Triple::foo) {
-// CHECK-NEXT:    static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:      0x000000000000a0
-// CHECK-NEXT:    });
-// CHECK-NEXT:    AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl_bzero, // bzero
-// CHECK-NEXT:        RTLIB::impl_sqrtl_f128, // sqrtl
-// CHECK-NEXT:    };
-// CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:    if (TT.getOS() == Triple::bar) {
-// CHECK-NEXT:      static const RTLIB::LibcallImpl LibraryCalls_isBarOS[] = {
-// CHECK-NEXT:          RTLIB::impl____memset, // ___memset
-// CHECK-NEXT:      };
-// CHECK-EMPTY:
-// CHECK-NEXT:      for (const RTLIB::LibcallImpl Impl : LibraryCalls_isBarOS) {
-// CHECK-NEXT:        setAvailable(Impl);
-// CHECK-NEXT:      }
-// CHECK-EMPTY:
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:    return;
-// CHECK-NEXT:  }
-// CHECK-EMPTY:
-// CHECK-NEXT: if (TT.getArch() == Triple::simple) {
-// CHECK-NEXT:    static constexpr LibcallImplBitset SystemAvailableImpls({
-// CHECK-NEXT:      0x00000000000158
-// CHECK-NEXT:    });
-// CHECK-NEXT:    AvailableLibcallImpls = SystemAvailableImpls;
-// CHECK-EMPTY:
-// CHECK-NEXT:    static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT:        RTLIB::impl_calloc, // calloc
-// CHECK-NEXT:        RTLIB::impl___ashlsi3, // __ashlsi3
-// CHECK-NEXT:        RTLIB::impl_sqrtl_f80, // sqrtl
-// CHECK-NEXT:        RTLIB::impl___lshrdi3, // __lshrdi3
-// CHECK-NEXT:    };
-// CHECK-EMPTY:
-// CHECK-NEXT:    for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
-// CHECK-NEXT:      setAvailable(Impl);
-// CHECK-NEXT:    }
-// CHECK-EMPTY:
-// CHECK-NEXT:   return;
-// CHECK-NEXT: }
-// CHECK-NEXT:  LLVM_DEBUG(dbgs() << "no system runtime library applied to target \'" << TT.str() << "\'\n");
+// CHECK-NEXT:     return;
+// CHECK-NEXT:   }
+// CHECK-NEXT:   LLVM_DEBUG(dbgs() << "no system runtime library applied to target \'" << TT.str() << "\'\n");
 // CHECK-NEXT: }
 // CHECK-EMPTY:
 // CHECK: #endif
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index df030ed33d48de..7389db859428f7 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -828,136 +828,37 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
       }
     }
 
-    // Split the member list into library references, each dispatched to
-    // setAvailableLibFuncs_<FuncSuffix> under an isLibraryAvailable(Name)
-    // guard, and the remaining members, emitted inline below. LibraryRef
-    // exclusions are applied inside the library function.
-    struct DispatchLib {
-      StringRef Name;
-      StringRef FuncSuffix;
-    };
+    // Dispatch each library to setAvailableLibFuncs_<FuncSuffix> under an
+    // isLibraryAvailable(Name) guard. LibraryRef exclusions are applied inside
+    // the library function. A library referenced more than once is dispatched
+    // once.
     const DagInit *MemberDag =
         R->getValueAsDef("MemberList")->getValueAsDag("MemberList");
-    SmallVector<DispatchLib, 4> DispatchLibs;
-    SmallVector<const Init *, 16> InlineArgs;
-    SmallVector<const StringInit *, 16> InlineArgNames;
-    // A provider referenced both as a base opt-out and a same-name re-add
-    // variant resolves to the same function; dispatch it once.
-    DenseSet<std::pair<StringRef, StringRef>> SeenDispatch;
-    auto AddDispatch = [&](StringRef Name, StringRef FuncSuffix) {
-      if (SeenDispatch.insert({Name, FuncSuffix}).second)
-        DispatchLibs.push_back({Name, FuncSuffix});
-    };
-    for (auto [Arg, ArgName] :
-         zip_equal(MemberDag->getArgs(), MemberDag->getArgNames())) {
-      if (const auto *DI = dyn_cast<DefInit>(Arg)) {
-        const Record *Def = DI->getDef();
-        if (Def->isSubClassOf("LibcallLibrary")) {
-          AddDispatch(Def->getValueAsString("LibraryName"), libFuncKey(Def));
-          continue;
-        }
-
-        if (Def->isSubClassOf("LibraryRef")) {
-          const Record *Lib = Def->getValueAsDef("Library");
-          AddDispatch(Lib->getValueAsString("LibraryName"), libFuncKey(Lib));
-          continue;
-        }
-      }
-      InlineArgs.push_back(Arg);
-      InlineArgNames.push_back(ArgName);
-    }
-
-    const DagInit *InlineDag =
-        DagInit::get(MemberDag->getOperator(), InlineArgs, InlineArgNames);
-
-    SetTheory Sets;
-
-    DenseMap<const RuntimeLibcallImpl *,
-             std::pair<std::vector<const Record *>, const Record *>>
-        Func2Preds;
-    Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>(
-                                         Libcalls, Func2Preds));
-
-    SetTheory::RecSet ElementsSet;
-    Sets.evaluate(InlineDag, ElementsSet, R->getLoc());
-    const SetTheory::RecSet *Elements = &ElementsSet;
-
-    // Sort to get deterministic output
-    SetVector<PredicateWithCC> PredicateSorter;
-    PredicateSorter.insert(
-        PredicateWithCC()); // No predicate or CC override first.
-
-    constexpr unsigned BitsPerStorageElt = 64;
-    DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
-
-    SmallVector<uint64_t, 32> BitsetValues(divideCeil(
-        Libcalls.getRuntimeLibcallImplDefList().size() + 1, BitsPerStorageElt));
-
-    for (const Record *Elt : *Elements) {
-      const RuntimeLibcallImpl *LibCallImpl =
-          Libcalls.getRuntimeLibcallImpl(Elt);
-      if (!LibCallImpl) {
-        PrintError(R, "entry for SystemLibrary is not a RuntimeLibcallImpl");
-        PrintNote(Elt->getLoc(), "invalid entry `" + Elt->getName() + "`");
-        continue;
-      }
-
-      size_t BitIdx = LibCallImpl->getEnumVal();
-      uint64_t BitmaskVal = uint64_t(1) << (BitIdx % BitsPerStorageElt);
-      size_t BitsetIdx = BitIdx / BitsPerStorageElt;
-
-      auto It = Func2Preds.find(LibCallImpl);
-      if (It == Func2Preds.end()) {
-        BitsetValues[BitsetIdx] |= BitmaskVal;
-        Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl);
+    SetVector<std::pair<StringRef, StringRef>> DispatchLibs;
+    for (const Init *Arg : MemberDag->getArgs()) {
+      const auto *DI = dyn_cast<DefInit>(Arg);
+      const Record *Lib = DI ? DI->getDef() : nullptr;
+      if (Lib && Lib->isSubClassOf("LibraryRef"))
+        Lib = Lib->getValueAsDef("Library");
+      if (!Lib || !Lib->isSubClassOf("LibcallLibrary")) {
+        PrintError(R, "SystemRuntimeLibrary member `" + Arg->getAsString() +
+                          "` is not a LibcallLibrary or LibraryRef");
         continue;
       }
-
-      for (const Record *Pred : It->second.first) {
-        const Record *CC = It->second.second;
-        AvailabilityPredicate SubsetPredicate(Pred);
-        if (SubsetPredicate.isAlwaysAvailable())
-          BitsetValues[BitsetIdx] |= BitmaskVal;
-
-        PredicateWithCC Key(Pred, CC);
-        auto &Entry = Pred2Funcs[Key];
-        Entry.LibcallImpls.push_back(LibCallImpl);
-        Entry.CallingConv = It->second.second;
-        PredicateSorter.insert(Key);
-      }
+      DispatchLibs.insert(
+          {Lib->getValueAsString("LibraryName"), libFuncKey(Lib)});
     }
 
-    OS << "    static constexpr LibcallImplBitset SystemAvailableImpls({\n"
-       << indent(6);
-
-    ListSeparator LS;
-    unsigned EntryCount = 0;
-    for (uint64_t Bits : BitsetValues) {
-      if (EntryCount++ == 4) {
-        EntryCount = 1;
-        OS << ",\n" << indent(6);
-      } else
-        OS << LS;
-      OS << format_hex(Bits, 16);
-    }
-    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 (const DispatchLib &DL : DispatchLibs) {
-      OS << indent(4) << "if (isLibraryAvailable(\"" << DL.Name << "\"))\n"
+    for (auto [Name, FuncSuffix] : DispatchLibs) {
+      OS << indent(4) << "if (isLibraryAvailable(\"" << Name << "\"))\n"
          << indent(6) << "setAvailableLibFuncs_";
-      emitLibFuncSuffix(OS, DL.FuncSuffix);
+      emitLibFuncSuffix(OS, FuncSuffix);
       OS << "(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat, "
          << DefaultCCArg << ");\n";
     }
     if (!DispatchLibs.empty())
       OS << '\n';
 
-    emitPredicateGroups(OS, R, Pred2Funcs, PredicateSorter, /*BaseIndent=*/2);
-
     OS << indent(4) << "return;\n" << indent(2);
     TopLevelPredicate.emitEndIf(OS);
   }



More information about the llvm-branch-commits mailing list