[llvm] RuntimeLibcalls: Add bitset for available libcalls (PR #150869)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 9 20:53:38 PDT 2025
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/150869
>From ebbd2c86c86b3dd0b2c9de552f3d7d014a199519 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/7] 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 | 21 +++++-
.../RuntimeLibcallEmitter-conflict-warning.td | 61 ++++++++++++++----
llvm/test/TableGen/RuntimeLibcallEmitter.td | 36 ++++++++---
.../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 30 ++++++++-
5 files changed, 188 insertions(+), 24 deletions(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 93183bc6b4aa9..8e912eb989304 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -54,8 +54,64 @@ static inline auto libcall_impls() {
static_cast<RTLIB::LibcallImpl>(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,
@@ -129,6 +185,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 98a376bc5c524..2904474f6110b 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: static const LibcallImplPair LibraryCalls[] = {
// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::impl_malloc}, // malloc
// CHECK-NEXT: };
@@ -70,9 +75,14 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: if (TT.getArch() == Triple::avr) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
-// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::impl_malloc}, // malloc
-// CHECK-NEXT: };
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT: 0x0000000000001a
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::impl_malloc}, // malloc
+// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
@@ -92,6 +102,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: static const LibcallImplPair LibraryCalls[] = {
// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::impl_malloc}, // malloc
// CHECK-NEXT: };
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td b/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
index 136c81b967d47..f9a148a183806 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td
@@ -25,9 +25,22 @@ def dup1 : RuntimeLibcallImpl<ANOTHER_DUP>;
// func_a and func_b both provide SOME_FUNC.
// CHECK: if (isTargetArchA()) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
-// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::impl_func_b}, // func_b
-// CHECK-NEXT: };
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT: 0x00000000000018
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
+
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::impl_func_b}, // func_b
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: setLibcallImpl(Func, Impl);
+// CHECK-NEXT: }
+// CHECK-EMPTY:
+// CHECK-NEXT: return;
+// CHECK-NEXT: }
// ERR: :[[@LINE+1]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_b, func_a
def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
@@ -35,10 +48,22 @@ def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
>;
// CHECK: if (isTargetArchB()) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
-// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::impl_other_func}, // other_func
-// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::impl_func_a}, // func_a
-// CHECK-NEXT: };
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT: 0x00000000000058
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::impl_other_func}, // other_func
+// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::impl_func_a}, // func_a
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: setLibcallImpl(Func, Impl);
+// CHECK-NEXT: }
+// CHECK-EMPTY:
+// CHECK-NEXT: return;
+// CHECK-NEXT: }
// ERR: :[[@LINE+1]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_a, func_b
def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
@@ -46,11 +71,23 @@ def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
>;
// CHECK: if (isTargetArchC()) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
-// CHECK-NEXT: {RTLIB::ANOTHER_DUP, RTLIB::impl_dup1}, // dup1
-// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::impl_other_func}, // other_func
-// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::impl_func_a}, // func_a
-// CHECK-NEXT: };
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT: 0x0000000000007e
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
+// CHECK-EMPTY:
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: {RTLIB::ANOTHER_DUP, RTLIB::impl_dup1}, // dup1
+// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::impl_other_func}, // other_func
+// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::impl_func_a}, // func_a
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: setLibcallImpl(Func, Impl);
+// CHECK-NEXT: }
+// CHECK-EMPTY:
+// CHECK-NEXT: return;
+// CHECK-NEXT: }
// ERR: :[[@LINE+3]]:5: warning: conflicting implementations for libcall ANOTHER_DUP: dup1, dup0
// ERR: :[[@LINE+2]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_a, func_b
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index c336fee956ce1..0c23e3bac195e 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -196,15 +196,20 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: if (TT.getArch() == Triple::blah) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
-// CHECK-NEXT: {RTLIB::BZERO, RTLIB::impl_bzero}, // bzero
-// CHECK-NEXT: {RTLIB::CALLOC, RTLIB::impl_calloc}, // calloc
-// CHECK-NEXT: {RTLIB::SQRT_F128, RTLIB::impl_sqrtl_f128}, // sqrtl
-// CHECK-NEXT: };
+// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
+// CHECK-NEXT: 0x000000000000e0
+// CHECK-NEXT: });
+// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
// CHECK-EMPTY:
-// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
-// CHECK-NEXT: setLibcallImpl(Func, Impl);
-// CHECK-NEXT: }
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: {RTLIB::BZERO, RTLIB::impl_bzero}, // bzero
+// CHECK-NEXT: {RTLIB::CALLOC, RTLIB::impl_calloc}, // calloc
+// CHECK-NEXT: {RTLIB::SQRT_F128, RTLIB::impl_sqrtl_f128}, // sqrtl
+// CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: setLibcallImpl(Func, Impl);
+// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: if (TT.hasCompilerRT()) {
// CHECK-NEXT: static const LibcallImplPair LibraryCalls_hasCompilerRT[] = {
@@ -233,6 +238,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: static const LibcallImplPair LibraryCalls[] = {
// CHECK-NEXT: {RTLIB::SHL_I32, RTLIB::impl___ashlsi3}, // __ashlsi3
// CHECK-NEXT: {RTLIB::SQRT_F80, RTLIB::impl_sqrtl_f80}, // sqrtl
@@ -247,6 +257,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: static const LibcallImplPair LibraryCalls[] = {
// CHECK-NEXT: {RTLIB::BZERO, RTLIB::impl_bzero}, // bzero
// CHECK-NEXT: {RTLIB::SQRT_F128, RTLIB::impl_sqrtl_f128}, // sqrtl
@@ -271,6 +286,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: static const LibcallImplPair LibraryCalls[] = {
// CHECK-NEXT: {RTLIB::CALLOC, RTLIB::impl_calloc}, // calloc
// CHECK-NEXT: {RTLIB::SHL_I32, RTLIB::impl___ashlsi3}, // __ashlsi3
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 10f02134d03b5..62c5c26105f3f 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -589,6 +589,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) {
@@ -597,16 +601,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;
@@ -614,6 +626,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();
>From 0ed7caf38b3e1430ec381da2f2dc6136e6dc678d 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/7] 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 8e912eb989304..a7992f00a9673 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"
@@ -55,54 +56,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 62c5c26105f3f..d8a9cae740626 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -588,10 +588,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);
@@ -602,8 +604,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 b4f753ae67f068d0e537236941e42b7f9c9abba1 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/7] 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 ed2bfa6df68f4..fc4494a3ec897 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 6488d6c01b5c6..87f877a043111 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 d8a9cae740626..24f548cd0460e 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -588,7 +588,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;
@@ -604,7 +605,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 d62fc749ca96734902f3e9621b3f779ad08e591d 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/7] 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 fc4494a3ec897..dfe55e596bb29 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")
>From 4a3701b4a6b321c666aa019edf2f4751e70c6fff Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 10 Oct 2025 01:45:28 +0900
Subject: [PATCH 5/7] Always use uint64_t array for special initializer
---
llvm/cmake/config-ix.cmake | 19 +------------------
.../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 4 +---
2 files changed, 2 insertions(+), 21 deletions(-)
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index dfe55e596bb29..ed2bfa6df68f4 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -579,9 +579,7 @@ 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 "loongarch32")
- set(LLVM_NATIVE_ARCH LoongArch)
-elseif (LLVM_NATIVE_ARCH MATCHES "loongarch64")
+elseif (LLVM_NATIVE_ARCH MATCHES "loongarch")
set(LLVM_NATIVE_ARCH LoongArch)
else ()
message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}")
@@ -618,21 +616,6 @@ 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")
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 24f548cd0460e..9553bd2281e0d 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -588,9 +588,7 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
PredicateSorter.insert(
PredicateWithCC()); // No predicate or CC override first.
- constexpr unsigned BitsPerStorageElt =
- LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T * CHAR_BIT;
-
+ constexpr unsigned BitsPerStorageElt = 64;
DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
SmallVector<uintptr_t, 32> BitsetValues(
>From 17f78f0a8ccaeff18097c6186cb73700a98febfd Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 10 Oct 2025 02:02:37 +0900
Subject: [PATCH 6/7] Adjust for always-uint64_t bitset constructor
---
llvm/include/llvm/IR/RuntimeLibcalls.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index a7992f00a9673..e6894cda9fee2 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -60,7 +60,7 @@ class LibcallImplBitset : public Bitset<RTLIB::NumLibcallImpls> {
public:
constexpr LibcallImplBitset() = default;
constexpr LibcallImplBitset(
- const Bitset<RTLIB::NumLibcallImpls>::StorageType &Src)
+ const std::array<uint64_t, (RTLIB::NumLibcallImpls + 63) / 64> &Src)
: Bitset(Src) {}
};
>From ff2566a194ba2ea6015933483331faecbcc28f0f Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 10 Oct 2025 12:53:09 +0900
Subject: [PATCH 7/7] Revert leftover cmake change
---
llvm/include/llvm/Config/llvm-config.h.cmake | 3 ---
1 file changed, 3 deletions(-)
diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake
index 87f877a043111..6488d6c01b5c6 100644
--- a/llvm/include/llvm/Config/llvm-config.h.cmake
+++ b/llvm/include/llvm/Config/llvm-config.h.cmake
@@ -33,9 +33,6 @@
/* 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
More information about the llvm-commits
mailing list