Compare commits

...

4 Commits

Author SHA1 Message Date
Matt Arsenault
a4c65ba7ed Use try_compile tests to get sizeof(uintptr_t) 2025-08-17 10:05:33 +09:00
Matt Arsenault
49f4496de2 Add LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T 2025-08-17 10:05:33 +09:00
Matt Arsenault
985a510a8c Use Bitset 2025-08-17 10:05:33 +09:00
Matt Arsenault
d51a2488b5 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.
2025-08-17 10:05:32 +09:00
7 changed files with 131 additions and 7 deletions

View File

@ -579,7 +579,9 @@ 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")
elseif (LLVM_NATIVE_ARCH MATCHES "loongarch32")
set(LLVM_NATIVE_ARCH LoongArch)
elseif (LLVM_NATIVE_ARCH MATCHES "loongarch64")
set(LLVM_NATIVE_ARCH LoongArch)
else ()
message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}")
@ -616,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")

View File

@ -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

View File

@ -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"
@ -53,8 +54,22 @@ 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.
class LibcallImplBitset : public Bitset<RTLIB::NumLibcallImpls> {
public:
constexpr LibcallImplBitset() = default;
constexpr LibcallImplBitset(
const Bitset<RTLIB::NumLibcallImpls>::StorageType &Src)
: Bitset(Src) {}
};
/// 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 +143,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];

View File

@ -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: });

View File

@ -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

View File

@ -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

View File

@ -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"
@ -606,7 +606,14 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
PredicateSorter.insert(
PredicateWithCC()); // No predicate or CC override first.
constexpr unsigned BitsPerStorageElt =
LLVM_NATIVE_ARCH_SIZEOF_UINTPTR_T * CHAR_BIT;
DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
SmallVector<uintptr_t, 32> BitsetValues(
divideCeil(RuntimeLibcallImplDefList.size(), BitsPerStorageElt));
for (const Record *Elt : *Elements) {
const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt);
if (!LibCallImpl) {
@ -615,16 +622,24 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
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);
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 +647,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 +726,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");