[llvm] RuntimeLibcalls: Add bitset for available libcalls (PR #150869)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 16 18:25:19 PDT 2025


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

>From d51a2488b5827e2112b26587de35aca083d6b085 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 27 Jul 2025 23:26:20 +0900
Subject: [PATCH 1/4] RuntimeLibcalls: Add bitset for available libcalls

This is a step towards separating the set of available libcalls
from the lowering decision of which call to use. Libcall recognition
now directly checks availability instead of indirectly checking through
the lowering table.
---
 llvm/include/llvm/IR/RuntimeLibcalls.h        | 64 +++++++++++++++++++
 .../RuntimeLibcallEmitter-calling-conv.td     | 15 +++++
 .../RuntimeLibcallEmitter-conflict-warning.td | 15 +++++
 llvm/test/TableGen/RuntimeLibcallEmitter.td   | 24 ++++++-
 .../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 36 +++++++++--
 5 files changed, 148 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 308be543de2bd..6ab77a2b5a3ec 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -53,8 +53,64 @@ static inline auto libcall_impls() {
   return enum_seq(static_cast<RTLIB::LibcallImpl>(1), RTLIB::NumLibcallImpls);
 }
 
+/// Manage a bitset representing the list of available libcalls for a module.
+///
+/// Most of this exists because std::bitset cannot be statically constructed in
+/// a size large enough before c++23
+class LibcallImplBitset {
+private:
+  using BitWord = uint64_t;
+  static constexpr unsigned BitWordSize = sizeof(BitWord) * CHAR_BIT;
+  static constexpr size_t NumArrayElts =
+      divideCeil(RTLIB::NumLibcallImpls, BitWordSize);
+  using Storage = BitWord[NumArrayElts];
+
+  Storage Bits = {};
+
+  /// Get bitmask for \p Impl in its Bits element.
+  static constexpr BitWord getBitmask(RTLIB::LibcallImpl Impl) {
+    unsigned Idx = static_cast<unsigned>(Impl);
+    return BitWord(1) << (Idx % BitWordSize);
+  }
+
+  /// Get index of array element of Bits for \p Impl
+  static constexpr unsigned getArrayIdx(RTLIB::LibcallImpl Impl) {
+    return static_cast<unsigned>(Impl) / BitWordSize;
+  }
+
+public:
+  constexpr LibcallImplBitset() = default;
+  constexpr LibcallImplBitset(const Storage &Src) {
+    for (size_t I = 0; I != NumArrayElts; ++I)
+      Bits[I] = Src[I];
+  }
+
+  /// Check if a LibcallImpl is available.
+  constexpr bool test(RTLIB::LibcallImpl Impl) const {
+    BitWord Mask = getBitmask(Impl);
+    return (Bits[getArrayIdx(Impl)] & Mask) != 0;
+  }
+
+  /// Mark a LibcallImpl as available
+  void set(RTLIB::LibcallImpl Impl) {
+    assert(Impl != RTLIB::Unsupported && "cannot enable unsupported libcall");
+    Bits[getArrayIdx(Impl)] |= getBitmask(Impl);
+  }
+
+  /// Mark a LibcallImpl as unavailable
+  void unset(RTLIB::LibcallImpl Impl) {
+    assert(Impl != RTLIB::Unsupported && "cannot enable unsupported libcall");
+    Bits[getArrayIdx(Impl)] &= ~getBitmask(Impl);
+  }
+};
+
 /// A simple container for information about the supported runtime calls.
 struct RuntimeLibcallsInfo {
+private:
+  /// Bitset of libcalls a module may emit a call to.
+  LibcallImplBitset AvailableLibcallImpls;
+
+public:
   explicit RuntimeLibcallsInfo(
       const Triple &TT,
       ExceptionHandling ExceptionModel = ExceptionHandling::None,
@@ -128,6 +184,14 @@ struct RuntimeLibcallsInfo {
     return getLibcallName(RTLIB::MEMMOVE);
   }
 
+  bool isAvailable(RTLIB::LibcallImpl Impl) const {
+    return AvailableLibcallImpls.test(Impl);
+  }
+
+  void setAvailable(RTLIB::LibcallImpl Impl) {
+    AvailableLibcallImpls.set(Impl);
+  }
+
   /// Return the libcall provided by \p Impl
   static RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl) {
     return ImplToLibcall[Impl];
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
index fcc5f7e0b6012..555be423267ee 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
@@ -48,6 +48,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
 // 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:    setLibcallsImpl({
 // CHECK-NEXT:      {RTLIB::MALLOC, RTLIB::malloc}, // malloc
 // CHECK-NEXT:    });
@@ -61,6 +66,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
 // 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-EMPTY:
 // CHECK-NEXT:   setLibcallsImpl({
 // CHECK-NEXT:       {RTLIB::MALLOC, RTLIB::malloc}, // malloc
 // CHECK-NEXT:   });
@@ -74,6 +84,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
 // 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:    setLibcallsImpl({
 // CHECK-NEXT:        {RTLIB::MALLOC, RTLIB::malloc}, // malloc
 // CHECK-NEXT:    });
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td b/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
index 2608faf2f75f0..d2343f58842c4 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
@@ -25,6 +25,11 @@ 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: setLibcallsImpl({
 // CHECK-NEXT:   {RTLIB::SOME_FUNC, RTLIB::func_b}, // func_b
 // CHECK-NEXT: });
@@ -35,6 +40,11 @@ def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
 >;
 
 // CHECK: if (isTargetArchB()) {
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT:   0x00000000000058
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
 // CHECK-NEXT: setLibcallsImpl({
 // CHECK-NEXT:   {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func
 // CHECK-NEXT:   {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a
@@ -46,6 +56,11 @@ def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
 >;
 
 // CHECK: if (isTargetArchC()) {
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT:   0x0000000000007e
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
 // CHECK-NEXT: setLibcallsImpl({
 // CHECK-NEXT:   {RTLIB::ANOTHER_DUP, RTLIB::dup1}, // dup1
 // CHECK-NEXT:   {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index 7c62402227f7d..b06582ed5ef27 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -196,16 +196,21 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // CHECK-NEXT:  };
 // CHECK-NEXT:  auto setLibcallsImpl = [this](
 // CHECK-NEXT:    ArrayRef<LibcallImplPair> Libcalls,
-// CHECK-NEXT:    std::optional<llvm::CallingConv::ID> CC = {})
-// CHECK-NEXT:  {
+// CHECK-NEXT:    std::optional<llvm::CallingConv::ID> CC = {}) {
 // CHECK-NEXT:    for (const auto [Func, Impl] : Libcalls) {
 // CHECK-NEXT:      setLibcallImpl(Func, Impl);
+// CHECK-NEXT:      setAvailable(Impl);
 // CHECK-NEXT:      if (CC)
 // CHECK-NEXT:        setLibcallImplCallingConv(Impl, *CC);
 // CHECK-NEXT:    }
 // CHECK-NEXT:  };
 // 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:     setLibcallsImpl({
 // CHECK-NEXT:         {RTLIB::BZERO, RTLIB::bzero}, // bzero
 // CHECK-NEXT:         {RTLIB::CALLOC, RTLIB::calloc}, // calloc
@@ -231,6 +236,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // 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:    setLibcallsImpl({
 // CHECK-NEXT:        {RTLIB::SHL_I32, RTLIB::__ashlsi3}, // __ashlsi3
 // CHECK-NEXT:        {RTLIB::SQRT_F80, RTLIB::sqrtl_f80}, // sqrtl
@@ -241,6 +251,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // 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:    setLibcallsImpl({
 // CHECK-NEXT:        {RTLIB::BZERO, RTLIB::bzero}, // bzero
 // CHECK-NEXT:        {RTLIB::SQRT_F128, RTLIB::sqrtl_f128}, // sqrtl
@@ -257,6 +272,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // 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:    setLibcallsImpl({
 // CHECK-NEXT:        {RTLIB::CALLOC, RTLIB::calloc}, // calloc
 // CHECK-NEXT:        {RTLIB::SHL_I32, RTLIB::__ashlsi3}, // __ashlsi3
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index c305e6323ca9d..80d687ee295e4 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -558,10 +558,10 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
         "  };\n"
         "  auto setLibcallsImpl = [this](\n"
         "    ArrayRef<LibcallImplPair> Libcalls,\n"
-        "    std::optional<llvm::CallingConv::ID> CC = {})\n"
-        "  {\n"
+        "    std::optional<llvm::CallingConv::ID> CC = {}) {\n"
         "    for (const auto [Func, Impl] : Libcalls) {\n"
         "      setLibcallImpl(Func, Impl);\n"
+        "      setAvailable(Impl);\n"
         "      if (CC)\n"
         "        setLibcallImplCallingConv(Impl, *CC);\n"
         "    }\n"
@@ -607,6 +607,10 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
         PredicateWithCC()); // No predicate or CC override first.
 
     DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
+
+    SmallVector<uint64_t, 32> BitsetValues(
+        divideCeil(RuntimeLibcallImplDefList.size(), 64));
+
     for (const Record *Elt : *Elements) {
       const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt);
       if (!LibCallImpl) {
@@ -615,16 +619,24 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
         continue;
       }
 
+      size_t BitIdx = LibCallImpl->getEnumVal();
+      uint64_t BitmaskVal = uint64_t(1) << (BitIdx % 64);
+      size_t BitsetIdx = BitIdx / 64;
+
       auto It = Func2Preds.find(LibCallImpl);
       if (It == Func2Preds.end()) {
+        BitsetValues[BitsetIdx] |= BitmaskVal;
         Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl);
         continue;
       }
 
       for (const Record *Pred : It->second.first) {
         const Record *CC = It->second.second;
-        PredicateWithCC Key(Pred, CC);
+        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;
@@ -632,6 +644,22 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
       }
     }
 
+    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";
+
     SmallVector<PredicateWithCC, 0> SortedPredicates =
         PredicateSorter.takeVector();
 
@@ -695,7 +723,7 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
         OS << indent(IndentDepth + 4);
         LibCallImpl->emitTableEntry(OS);
       }
-      OS << indent(IndentDepth + 2) << "}";
+      OS << indent(IndentDepth + 2) << '}';
       if (FuncsWithCC.CallingConv) {
         StringRef CCEnum =
             FuncsWithCC.CallingConv->getValueAsString("CallingConv");

>From 985a510a8c2c39f66f453c1c7b8cd168783d59e8 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 4 Aug 2025 21:25:49 +0900
Subject: [PATCH 2/4] Use Bitset

---
 llvm/include/llvm/IR/RuntimeLibcalls.h        | 51 ++-----------------
 .../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 10 ++--
 2 files changed, 11 insertions(+), 50 deletions(-)

diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 6ab77a2b5a3ec..fd25c12497f8a 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -15,6 +15,7 @@
 #define LLVM_IR_RUNTIME_LIBCALLS_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Bitset.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/StringTable.h"
 #include "llvm/IR/CallingConv.h"
@@ -54,54 +55,12 @@ static inline auto libcall_impls() {
 }
 
 /// Manage a bitset representing the list of available libcalls for a module.
-///
-/// Most of this exists because std::bitset cannot be statically constructed in
-/// a size large enough before c++23
-class LibcallImplBitset {
-private:
-  using BitWord = uint64_t;
-  static constexpr unsigned BitWordSize = sizeof(BitWord) * CHAR_BIT;
-  static constexpr size_t NumArrayElts =
-      divideCeil(RTLIB::NumLibcallImpls, BitWordSize);
-  using Storage = BitWord[NumArrayElts];
-
-  Storage Bits = {};
-
-  /// Get bitmask for \p Impl in its Bits element.
-  static constexpr BitWord getBitmask(RTLIB::LibcallImpl Impl) {
-    unsigned Idx = static_cast<unsigned>(Impl);
-    return BitWord(1) << (Idx % BitWordSize);
-  }
-
-  /// Get index of array element of Bits for \p Impl
-  static constexpr unsigned getArrayIdx(RTLIB::LibcallImpl Impl) {
-    return static_cast<unsigned>(Impl) / BitWordSize;
-  }
-
+class LibcallImplBitset : public Bitset<RTLIB::NumLibcallImpls> {
 public:
   constexpr LibcallImplBitset() = default;
-  constexpr LibcallImplBitset(const Storage &Src) {
-    for (size_t I = 0; I != NumArrayElts; ++I)
-      Bits[I] = Src[I];
-  }
-
-  /// Check if a LibcallImpl is available.
-  constexpr bool test(RTLIB::LibcallImpl Impl) const {
-    BitWord Mask = getBitmask(Impl);
-    return (Bits[getArrayIdx(Impl)] & Mask) != 0;
-  }
-
-  /// Mark a LibcallImpl as available
-  void set(RTLIB::LibcallImpl Impl) {
-    assert(Impl != RTLIB::Unsupported && "cannot enable unsupported libcall");
-    Bits[getArrayIdx(Impl)] |= getBitmask(Impl);
-  }
-
-  /// Mark a LibcallImpl as unavailable
-  void unset(RTLIB::LibcallImpl Impl) {
-    assert(Impl != RTLIB::Unsupported && "cannot enable unsupported libcall");
-    Bits[getArrayIdx(Impl)] &= ~getBitmask(Impl);
-  }
+  constexpr LibcallImplBitset(
+      const Bitset<RTLIB::NumLibcallImpls>::StorageType &Src)
+      : Bitset(Src) {}
 };
 
 /// A simple container for information about the supported runtime calls.
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 80d687ee295e4..6026658d5374f 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -606,10 +606,12 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
     PredicateSorter.insert(
         PredicateWithCC()); // No predicate or CC override first.
 
+    constexpr unsigned BitsPerStorageElt = sizeof(uintptr_t) * CHAR_BIT;
+
     DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
 
-    SmallVector<uint64_t, 32> BitsetValues(
-        divideCeil(RuntimeLibcallImplDefList.size(), 64));
+    SmallVector<uintptr_t, 32> BitsetValues(
+        divideCeil(RuntimeLibcallImplDefList.size(), BitsPerStorageElt));
 
     for (const Record *Elt : *Elements) {
       const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt);
@@ -620,8 +622,8 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
       }
 
       size_t BitIdx = LibCallImpl->getEnumVal();
-      uint64_t BitmaskVal = uint64_t(1) << (BitIdx % 64);
-      size_t BitsetIdx = BitIdx / 64;
+      uintptr_t BitmaskVal = uintptr_t(1) << (BitIdx % BitsPerStorageElt);
+      size_t BitsetIdx = BitIdx / BitsPerStorageElt;
 
       auto It = Func2Preds.find(LibCallImpl);
       if (It == Func2Preds.end()) {

>From 49f4496de2150ea8b3512a6528d2ff222d33e918 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 5 Aug 2025 02:13:23 +0900
Subject: [PATCH 3/4] Add LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T

---
 llvm/cmake/config-ix.cmake                    | 20 ++++++++++++++++++-
 llvm/include/llvm/Config/llvm-config.h.cmake  |  3 +++
 .../TableGen/Basic/RuntimeLibcallsEmitter.cpp |  5 +++--
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index a8e4e5a63244d..12a6d94c08131 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -537,18 +537,24 @@ if( LLVM_NATIVE_ARCH STREQUAL "host" )
   string(REGEX MATCH "^[^-]*" LLVM_NATIVE_ARCH ${LLVM_HOST_TRIPLE})
 endif ()
 
+set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 8)
+
 if (LLVM_NATIVE_ARCH MATCHES "i[2-6]86")
   set(LLVM_NATIVE_ARCH X86)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH STREQUAL "x86")
   set(LLVM_NATIVE_ARCH X86)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH STREQUAL "amd64")
   set(LLVM_NATIVE_ARCH X86)
 elseif (LLVM_NATIVE_ARCH STREQUAL "x86_64")
   set(LLVM_NATIVE_ARCH X86)
 elseif (LLVM_NATIVE_ARCH MATCHES "sparc")
   set(LLVM_NATIVE_ARCH Sparc)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "powerpc")
   set(LLVM_NATIVE_ARCH PowerPC)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "ppc64le")
   set(LLVM_NATIVE_ARCH PowerPC)
 elseif (LLVM_NATIVE_ARCH MATCHES "aarch64")
@@ -557,29 +563,41 @@ elseif (LLVM_NATIVE_ARCH MATCHES "arm64")
   set(LLVM_NATIVE_ARCH AArch64)
 elseif (LLVM_NATIVE_ARCH MATCHES "arm")
   set(LLVM_NATIVE_ARCH ARM)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "avr")
   set(LLVM_NATIVE_ARCH AVR)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 2)
 elseif (LLVM_NATIVE_ARCH MATCHES "mips")
   set(LLVM_NATIVE_ARCH Mips)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "xcore")
   set(LLVM_NATIVE_ARCH XCore)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "msp430")
   set(LLVM_NATIVE_ARCH MSP430)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 2)
 elseif (LLVM_NATIVE_ARCH MATCHES "hexagon")
   set(LLVM_NATIVE_ARCH Hexagon)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "s390x")
   set(LLVM_NATIVE_ARCH SystemZ)
 elseif (LLVM_NATIVE_ARCH MATCHES "wasm32")
   set(LLVM_NATIVE_ARCH WebAssembly)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "wasm64")
   set(LLVM_NATIVE_ARCH WebAssembly)
 elseif (LLVM_NATIVE_ARCH MATCHES "riscv32")
   set(LLVM_NATIVE_ARCH RISCV)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "riscv64")
   set(LLVM_NATIVE_ARCH RISCV)
 elseif (LLVM_NATIVE_ARCH STREQUAL "m68k")
   set(LLVM_NATIVE_ARCH M68k)
-elseif (LLVM_NATIVE_ARCH MATCHES "loongarch")
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
+elseif (LLVM_NATIVE_ARCH MATCHES "loongarch32")
+  set(LLVM_NATIVE_ARCH LoongArch)
+  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
+elseif (LLVM_NATIVE_ARCH MATCHES "loongarch64")
   set(LLVM_NATIVE_ARCH LoongArch)
 else ()
   message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}")
diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake
index 39136bc45c292..13767a2e80325 100644
--- a/llvm/include/llvm/Config/llvm-config.h.cmake
+++ b/llvm/include/llvm/Config/llvm-config.h.cmake
@@ -33,6 +33,9 @@
 /* LLVM architecture name for the native architecture, if available */
 #cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH}
 
+/* sizeof(uintptr_t) name for the native architecture, if available */
+#cmakedefine LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T ${LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T}
+
 /* LLVM name for the native AsmParser init function, if available */
 #cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser
 
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 6026658d5374f..436b5b359f406 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -606,7 +606,8 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
     PredicateSorter.insert(
         PredicateWithCC()); // No predicate or CC override first.
 
-    constexpr unsigned BitsPerStorageElt = sizeof(uintptr_t) * CHAR_BIT;
+    constexpr unsigned BitsPerStorageElt =
+        LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T * CHAR_BIT;
 
     DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
 
@@ -622,7 +623,7 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
       }
 
       size_t BitIdx = LibCallImpl->getEnumVal();
-      uintptr_t BitmaskVal = uintptr_t(1) << (BitIdx % BitsPerStorageElt);
+      uint64_t BitmaskVal = uint64_t(1) << (BitIdx % BitsPerStorageElt);
       size_t BitsetIdx = BitIdx / BitsPerStorageElt;
 
       auto It = Func2Preds.find(LibCallImpl);

>From a4c65ba7ed8526a92e84304aa0788896dd5de4ba Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 6 Aug 2025 10:54:06 +0900
Subject: [PATCH 4/4] Use try_compile tests to get sizeof(uintptr_t)

---
 llvm/cmake/config-ix.cmake | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index 12a6d94c08131..f321ab0bdebe5 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -537,24 +537,18 @@ if( LLVM_NATIVE_ARCH STREQUAL "host" )
   string(REGEX MATCH "^[^-]*" LLVM_NATIVE_ARCH ${LLVM_HOST_TRIPLE})
 endif ()
 
-set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 8)
-
 if (LLVM_NATIVE_ARCH MATCHES "i[2-6]86")
   set(LLVM_NATIVE_ARCH X86)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH STREQUAL "x86")
   set(LLVM_NATIVE_ARCH X86)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH STREQUAL "amd64")
   set(LLVM_NATIVE_ARCH X86)
 elseif (LLVM_NATIVE_ARCH STREQUAL "x86_64")
   set(LLVM_NATIVE_ARCH X86)
 elseif (LLVM_NATIVE_ARCH MATCHES "sparc")
   set(LLVM_NATIVE_ARCH Sparc)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "powerpc")
   set(LLVM_NATIVE_ARCH PowerPC)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "ppc64le")
   set(LLVM_NATIVE_ARCH PowerPC)
 elseif (LLVM_NATIVE_ARCH MATCHES "aarch64")
@@ -563,40 +557,30 @@ elseif (LLVM_NATIVE_ARCH MATCHES "arm64")
   set(LLVM_NATIVE_ARCH AArch64)
 elseif (LLVM_NATIVE_ARCH MATCHES "arm")
   set(LLVM_NATIVE_ARCH ARM)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "avr")
   set(LLVM_NATIVE_ARCH AVR)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 2)
 elseif (LLVM_NATIVE_ARCH MATCHES "mips")
   set(LLVM_NATIVE_ARCH Mips)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "xcore")
   set(LLVM_NATIVE_ARCH XCore)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "msp430")
   set(LLVM_NATIVE_ARCH MSP430)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 2)
 elseif (LLVM_NATIVE_ARCH MATCHES "hexagon")
   set(LLVM_NATIVE_ARCH Hexagon)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "s390x")
   set(LLVM_NATIVE_ARCH SystemZ)
 elseif (LLVM_NATIVE_ARCH MATCHES "wasm32")
   set(LLVM_NATIVE_ARCH WebAssembly)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "wasm64")
   set(LLVM_NATIVE_ARCH WebAssembly)
 elseif (LLVM_NATIVE_ARCH MATCHES "riscv32")
   set(LLVM_NATIVE_ARCH RISCV)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "riscv64")
   set(LLVM_NATIVE_ARCH RISCV)
 elseif (LLVM_NATIVE_ARCH STREQUAL "m68k")
   set(LLVM_NATIVE_ARCH M68k)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "loongarch32")
   set(LLVM_NATIVE_ARCH LoongArch)
-  set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 4)
 elseif (LLVM_NATIVE_ARCH MATCHES "loongarch64")
   set(LLVM_NATIVE_ARCH LoongArch)
 else ()
@@ -634,6 +618,21 @@ else ()
   endif ()
 endif ()
 
+foreach(i IN ITEMS 8 4)
+  try_compile(SIZEOF_UINTPTR_T_IS_${i}
+    SOURCE_FROM_CONTENT
+    "test-sizeof-uintptr_t.cpp"
+    "#include <cstdint>\n
+     static_assert(sizeof(uintptr_t) == ${i}); int main(){}"
+    CXX_STANDARD 17
+    LOG_DESCRIPTION "testing sizeof(uintptr_t)")
+
+  if(SIZEOF_UINTPTR_T_IS_${i})
+    set(LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T ${i})
+    break()
+  endif()
+endforeach()
+
 if( MSVC )
   set(SHLIBEXT ".lib")
   set(stricmp "_stricmp")



More information about the llvm-commits mailing list