diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index a8e4e5a63244d..f321ab0bdebe5 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -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 \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/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/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index f39e2e3c26900..04bda69c40280 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" @@ -53,8 +54,22 @@ static inline auto libcall_impls() { return enum_seq(static_cast(1), RTLIB::NumLibcallImpls); } +/// Manage a bitset representing the list of available libcalls for a module. +class LibcallImplBitset : public Bitset { +public: + constexpr LibcallImplBitset() = default; + constexpr LibcallImplBitset( + const Bitset::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, @@ -132,6 +147,14 @@ struct RuntimeLibcallsInfo { return ImplToLibcall[Impl]; } + bool isAvailable(RTLIB::LibcallImpl Impl) const { + return AvailableLibcallImpls.test(Impl); + } + + void setAvailable(RTLIB::LibcallImpl Impl) { + AvailableLibcallImpls.set(Impl); + } + /// Check if this is valid libcall for the current module, otherwise /// RTLIB::Unsupported. LLVM_ABI RTLIB::LibcallImpl getSupportedLibcallImpl(StringRef FuncName) const; diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index a8e6c7938cf54..21a8d03c3a552 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -96,12 +96,8 @@ RuntimeLibcallsInfo::getSupportedLibcallImpl(StringRef FuncName) const { for (auto I = Range.begin(); I != Range.end(); ++I) { RTLIB::LibcallImpl Impl = static_cast(I - RuntimeLibcallNameOffsets.begin()); - - // FIXME: This should not depend on looking up ImplToLibcall, only the list - // of libcalls for the module. - RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]]; - if (Recognized != RTLIB::Unsupported) - return Recognized; + if (isAvailable(Impl)) + return Impl; } return RTLIB::Unsupported; diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td index feef07502eedb..210946e58c6d7 100644 --- a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td +++ b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td @@ -48,6 +48,11 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary; // 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; // 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; // 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 59ccd2341c54c..a6009b1fc6ce2 100644 --- a/llvm/test/TableGen/RuntimeLibcallEmitter.td +++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td @@ -157,16 +157,21 @@ def BlahLibrary : SystemRuntimeLibrary Libcalls, -// CHECK-NEXT: std::optional CC = {}) -// CHECK-NEXT: { +// CHECK-NEXT: std::optional 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 @@ -192,6 +197,11 @@ def BlahLibrary : SystemRuntimeLibrary Libcalls,\n" - " std::optional CC = {})\n" - " {\n" + " std::optional CC = {}) {\n" " for (const auto [Func, Impl] : Libcalls) {\n" " setLibcallImpl(Func, Impl);\n" + " setAvailable(Impl);\n" " if (CC)\n" " setLibcallImplCallingConv(Impl, *CC);\n" " }\n" @@ -411,7 +412,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 Pred2Funcs; + + SmallVector BitsetValues( + divideCeil(RuntimeLibcallImplDefList.size(), BitsPerStorageElt)); + for (const Record *Elt : *Elements) { const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt); if (!LibCallImpl) { @@ -420,16 +428,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; @@ -437,6 +453,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 SortedPredicates = PredicateSorter.takeVector(); @@ -500,7 +532,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");