Skip to content

Commit 61b2148

Browse files
committed
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.
1 parent 5843fba commit 61b2148

File tree

6 files changed

+136
-6
lines changed

6 files changed

+136
-6
lines changed

llvm/include/llvm/IR/RuntimeLibcalls.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,64 @@ static inline auto libcall_impls() {
5353
return enum_seq(static_cast<RTLIB::LibcallImpl>(1), RTLIB::NumLibcallImpls);
5454
}
5555

56+
/// Manage a bitset representing the list of available libcalls for a module.
57+
///
58+
/// Most of this exists because std::bitset cannot be statically constructed in
59+
/// a size large enough before c++23
60+
class LibcallImplBitset {
61+
private:
62+
using BitWord = uint64_t;
63+
static constexpr unsigned BitWordSize = sizeof(BitWord) * CHAR_BIT;
64+
static constexpr size_t NumArrayElts =
65+
divideCeil(RTLIB::NumLibcallImpls, BitWordSize);
66+
using Storage = BitWord[NumArrayElts];
67+
68+
Storage Bits = {};
69+
70+
/// Get bitmask for \p Impl in its Bits element.
71+
static constexpr BitWord getBitmask(RTLIB::LibcallImpl Impl) {
72+
unsigned Idx = static_cast<unsigned>(Impl);
73+
return BitWord(1) << (Idx % BitWordSize);
74+
}
75+
76+
/// Get index of array element of Bits for \p Impl
77+
static constexpr unsigned getArrayIdx(RTLIB::LibcallImpl Impl) {
78+
return static_cast<unsigned>(Impl) / BitWordSize;
79+
}
80+
81+
public:
82+
constexpr LibcallImplBitset() = default;
83+
constexpr LibcallImplBitset(const Storage &Src) {
84+
for (size_t I = 0; I != NumArrayElts; ++I)
85+
Bits[I] = Src[I];
86+
}
87+
88+
/// Check if a LibcallImpl is available.
89+
constexpr bool test(RTLIB::LibcallImpl Impl) const {
90+
BitWord Mask = getBitmask(Impl);
91+
return (Bits[getArrayIdx(Impl)] & Mask) != 0;
92+
}
93+
94+
/// Mark a LibcallImpl as available
95+
void set(RTLIB::LibcallImpl Impl) {
96+
assert(Impl != RTLIB::Unsupported && "cannot enable unsupported libcall");
97+
Bits[getArrayIdx(Impl)] |= getBitmask(Impl);
98+
}
99+
100+
/// Mark a LibcallImpl as unavailable
101+
void unset(RTLIB::LibcallImpl Impl) {
102+
assert(Impl != RTLIB::Unsupported && "cannot enable unsupported libcall");
103+
Bits[getArrayIdx(Impl)] &= ~getBitmask(Impl);
104+
}
105+
};
106+
56107
/// A simple container for information about the supported runtime calls.
57108
struct RuntimeLibcallsInfo {
109+
private:
110+
/// Bitset of libcalls a module may emit a call to.
111+
LibcallImplBitset AvailableLibcallImpls;
112+
113+
public:
58114
explicit RuntimeLibcallsInfo(
59115
const Triple &TT,
60116
ExceptionHandling ExceptionModel = ExceptionHandling::None,
@@ -132,6 +188,10 @@ struct RuntimeLibcallsInfo {
132188
return ImplToLibcall[Impl];
133189
}
134190

191+
bool isAvailable(RTLIB::LibcallImpl Impl) const {
192+
return AvailableLibcallImpls.test(Impl);
193+
}
194+
135195
/// Check if this is valid libcall for the current module, otherwise
136196
/// RTLIB::Unsupported.
137197
RTLIB::LibcallImpl getSupportedLibcallImpl(StringRef FuncName) const;

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,8 @@ RuntimeLibcallsInfo::getSupportedLibcallImpl(StringRef FuncName) const {
114114
for (auto I = Range.begin(); I != Range.end(); ++I) {
115115
RTLIB::LibcallImpl Impl =
116116
static_cast<RTLIB::LibcallImpl>(I - RuntimeLibcallNameOffsets.begin());
117-
118-
// FIXME: This should not depend on looking up ImplToLibcall, only the list
119-
// of libcalls for the module.
120-
RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]];
121-
if (Recognized != RTLIB::Unsupported)
122-
return Recognized;
117+
if (isAvailable(Impl))
118+
return Impl;
123119
}
124120

125121
return RTLIB::Unsupported;

llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
4848
// CHECK-NEXT: Entry = DefaultCC;
4949
// CHECK-NEXT: }
5050
// CHECK-EMPTY:
51+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
52+
// CHECK-NEXT: 0x0000000000001a
53+
// CHECK-NEXT: });
54+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
55+
// CHECK-EMPTY:
5156
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
5257
// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::malloc}, // malloc
5358
// CHECK-NEXT: };
@@ -70,6 +75,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
7075
// CHECK-NEXT: }
7176
// CHECK-EMPTY:
7277
// CHECK-NEXT: if (TT.getArch() == Triple::avr) {
78+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
79+
// CHECK-NEXT: 0x0000000000001a
80+
// CHECK-NEXT: });
81+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
82+
// CHECK-EMPTY:
7383
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
7484
// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::malloc}, // malloc
7585
// CHECK-NEXT: };
@@ -92,6 +102,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
92102
// CHECK-NEXT: }
93103
// CHECK-EMPTY:
94104
// CHECK-NEXT: if (TT.getArch() == Triple::msp430) {
105+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
106+
// CHECK-NEXT: 0x0000000000001a
107+
// CHECK-NEXT: });
108+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
109+
// CHECK-EMPTY:
95110
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
96111
// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::malloc}, // malloc
97112
// CHECK-NEXT: };

llvm/test/TableGen/RuntimeLibcallEmitter-conflict-warning.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ def dup1 : RuntimeLibcallImpl<ANOTHER_DUP>;
2525
// func_a and func_b both provide SOME_FUNC.
2626

2727
// CHECK: if (isTargetArchA()) {
28+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
29+
// CHECK-NEXT: 0x00000000000018
30+
// CHECK-NEXT: });
31+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
32+
// CHECK-EMPTY:
2833
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
2934
// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::func_b}, // func_b
3035
// CHECK-NEXT: };
@@ -35,6 +40,11 @@ def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
3540
>;
3641

3742
// CHECK: if (isTargetArchB()) {
43+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
44+
// CHECK-NEXT: 0x00000000000058
45+
// CHECK-NEXT: });
46+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
47+
// CHECK-EMPTY:
3848
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
3949
// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func
4050
// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a
@@ -46,6 +56,11 @@ def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
4656
>;
4757

4858
// CHECK: if (isTargetArchC()) {
59+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
60+
// CHECK-NEXT: 0x0000000000007e
61+
// CHECK-NEXT: });
62+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
63+
// CHECK-EMPTY:
4964
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
5065
// CHECK-NEXT: {RTLIB::ANOTHER_DUP, RTLIB::dup1}, // dup1
5166
// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func

llvm/test/TableGen/RuntimeLibcallEmitter.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
157157
// CHECK-NEXT: };
158158
// CHECK-EMPTY:
159159
// CHECK-NEXT: if (TT.getArch() == Triple::blah) {
160+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
161+
// CHECK-NEXT: 0x000000000000fc
162+
// CHECK-NEXT: });
163+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
164+
// CHECK-EMPTY:
160165
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
161166
// CHECK-NEXT: {RTLIB::BZERO, RTLIB::bzero}, // bzero
162167
// CHECK-NEXT: {RTLIB::CALLOC, RTLIB::calloc}, // calloc
@@ -194,6 +199,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
194199
// CHECK-NEXT: }
195200
// CHECK-EMPTY:
196201
// CHECK-NEXT: if (TT.getArch() == Triple::buzz) {
202+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
203+
// CHECK-NEXT: 0x00000000000118
204+
// CHECK-NEXT: });
205+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
206+
// CHECK-EMPTY:
197207
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
198208
// CHECK-NEXT: {RTLIB::SHL_I32, RTLIB::__ashlsi3}, // __ashlsi3
199209
// CHECK-NEXT: {RTLIB::SQRT_F80, RTLIB::sqrtl_f80}, // sqrtl
@@ -208,6 +218,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
208218
// CHECK-NEXT: }
209219
// CHECK-EMPTY:
210220
// CHECK-NEXT: if (TT.getArch() == Triple::foo) {
221+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
222+
// CHECK-NEXT: 0x000000000000a4
223+
// CHECK-NEXT: });
224+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
225+
// CHECK-EMPTY:
211226
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
212227
// CHECK-NEXT: {RTLIB::BZERO, RTLIB::bzero}, // bzero
213228
// CHECK-NEXT: {RTLIB::SQRT_F128, RTLIB::sqrtl_f128}, // sqrtl
@@ -232,6 +247,11 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
232247
// CHECK-NEXT: }
233248
// CHECK-EMPTY:
234249
// CHECK-NEXT: if (TT.getArch() == Triple::simple) {
250+
// CHECK-NEXT: static constexpr LibcallImplBitset SystemAvailableImpls({
251+
// CHECK-NEXT: 0x00000000000158
252+
// CHECK-NEXT: });
253+
// CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls;
254+
// CHECK-EMPTY:
235255
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
236256
// CHECK-NEXT: {RTLIB::CALLOC, RTLIB::calloc}, // calloc
237257
// CHECK-NEXT: {RTLIB::SHL_I32, RTLIB::__ashlsi3}, // __ashlsi3

llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "llvm/ADT/StringRef.h"
1010
#include "llvm/Support/Debug.h"
11+
#include "llvm/Support/Format.h"
1112
#include "llvm/Support/FormatVariadic.h"
1213
#include "llvm/Support/raw_ostream.h"
1314
#include "llvm/TableGen/Error.h"
@@ -402,6 +403,10 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
402403
PredicateWithCC()); // No predicate or CC override first.
403404

404405
DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
406+
407+
SmallVector<uint64_t, 32> BitsetValues(
408+
divideCeil(RuntimeLibcallImplDefList.size(), 64));
409+
405410
for (const Record *Elt : *Elements) {
406411
const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt);
407412
if (!LibCallImpl) {
@@ -410,6 +415,9 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
410415
continue;
411416
}
412417

418+
size_t Idx = LibCallImpl->getEnumVal();
419+
BitsetValues[Idx / 64] |= uint64_t(1) << (Idx % 64);
420+
413421
auto It = Func2Preds.find(LibCallImpl);
414422
if (It == Func2Preds.end()) {
415423
Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl);
@@ -427,6 +435,22 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
427435
}
428436
}
429437

438+
OS << " static constexpr LibcallImplBitset SystemAvailableImpls({\n"
439+
<< indent(6);
440+
441+
ListSeparator LS;
442+
unsigned EntryCount = 0;
443+
for (uint64_t Bits : BitsetValues) {
444+
if (EntryCount++ == 4) {
445+
EntryCount = 1;
446+
OS << ",\n" << indent(6);
447+
} else
448+
OS << LS;
449+
OS << format_hex(Bits, 16);
450+
}
451+
OS << "\n });\n"
452+
" AvailableLibcallImpls = SystemAvailableImpls;\n\n";
453+
430454
SmallVector<PredicateWithCC, 0> SortedPredicates =
431455
PredicateSorter.takeVector();
432456

0 commit comments

Comments
 (0)