llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-x86 Author: Matt Arsenault (arsenm) <details> <summary>Changes</summary> Currently the set of system libraries calls is flat and disorganized. Begin organizing this per-provider library. The goal is to organize groups of functions by named sets, corresponding to the underlying library which will be linked. A LibcallLibrary is a named runtime library whose impls are made available as a unit; its members use the same dag vocabulary as LibcallImpls. The emitter emits one setAvailableLibFuncs_<name> per distinct library name, merging same-named libraries under their per-variant availability predicates. isLibraryAvailable() is added as a stub for a future dispatch driver. No target defines a LibcallLibrary, so generated output is mostly unchanged (there are some incidental enum reorderings). Reorganizing all of the library functions require a good bit more infrastructure to be practical, but this is a minimally functional piece to start the review. Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com> --- Patch is 26.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/217592.diff 7 Files Affected: - (modified) llvm/include/llvm/IR/RuntimeLibcalls.h (+4) - (modified) llvm/include/llvm/IR/RuntimeLibcallsImpl.td (+12) - (modified) llvm/lib/IR/RuntimeLibcalls.cpp (+6) - (added) llvm/test/TableGen/RuntimeLibcallEmitter-library-grouping.td (+80) - (added) llvm/test/TableGen/RuntimeLibcallEmitter-library-name-merge.td (+102) - (modified) llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td (+2-2) - (modified) llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (+253-83) ``````````diff diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index 4def7c6db3d50..e7dfec449a842 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -234,6 +234,10 @@ struct RuntimeLibcallsInfo { LLVM_READONLY static bool isAAPCS_ABI(const Triple &TT, StringRef ABIName); + /// Return whether the runtime library \p LibraryName is available for the + /// current module. + bool isLibraryAvailable(StringRef LibraryName) const; + /// Generated by tablegen. void setTargetRuntimeLibcallSets(const Triple &TT, ExceptionHandling ExceptionModel, diff --git a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td index 1c49959285f08..59616efb41c57 100644 --- a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td +++ b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td @@ -113,6 +113,18 @@ class LibcallsWithCC<dag funcList, LibcallCallingConv CC, LibcallCallingConv CallingConv = CC; } +// A named runtime library whose Impls are made available as a unit. Impls use +// the same dag vocabulary as SystemRuntimeLibrary. +class LibcallLibrary<string name, dag impls, + RuntimeLibcallAvailability pred = AlwaysAvailable> { + string LibraryName = name; + dag Impls = impls; + + // Availability guard for the library. Libraries sharing a LibraryName merge + // into one function, each variant under its own Pred. + RuntimeLibcallAvailability Pred = pred; +} + /// Define a complete top level set of runtime libcalls for a target. class SystemRuntimeLibrary<RuntimeLibcallAvailability Pred, dag funcList> { /// Set the default calling convention assumed for RuntimeLibcallImpl members. diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 1befff9d5f00e..67e1bacdb329d 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -113,6 +113,12 @@ RuntimeLibcallsInfo::RuntimeLibcallsInfo(const Module &M, : RuntimeLibcallsInfo(M.getTargetTriple(), ExceptionModel, M.getFloatABI(), EABIVersion, ABIName, VecLib) {} +bool RuntimeLibcallsInfo::isLibraryAvailable(StringRef LibraryName) const { + // TODO: Drive this from module-level state (e.g. the linked runtime). For now + // every named library is reported as available. + return true; +} + /// Set default libcall names. If a target wants to opt-out of a libcall it /// should be placed here. void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-library-grouping.td b/llvm/test/TableGen/RuntimeLibcallEmitter-library-grouping.td new file mode 100644 index 0000000000000..6937b935e7494 --- /dev/null +++ b/llvm/test/TableGen/RuntimeLibcallEmitter-library-grouping.td @@ -0,0 +1,80 @@ +// RUN: llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s | FileCheck %s + +// Check that each LibcallLibrary emits a standalone implementation function +// (suffixed by the library name) that makes the library's members available, +// with per-member triple predicates nested inside. + +include "llvm/IR/RuntimeLibcallsImpl.td" + +def MEMCPY : RuntimeLibcall; +def MEMSET : RuntimeLibcall; +def SQRT_F64 : RuntimeLibcall; +def SINCOS_F64 : RuntimeLibcall; + +def memcpy : RuntimeLibcallImpl<MEMCPY>; +def memset_pattern : RuntimeLibcallImpl<MEMSET, "memset_pattern">; +def sqrt : RuntimeLibcallImpl<SQRT_F64, "sqrt">; +def sincos : RuntimeLibcallImpl<SINCOS_F64, "sincos">; + +def IsDarwin : LibcallPredicate<[{TT.isOSDarwin()}]>; +def IsX86 : LibcallPredicate<[{TT.isX86()}]>; +def isDarwin : RuntimeLibcallAvailability<(all_of IsDarwin)>; +def isX86 : RuntimeLibcallAvailability<(all_of IsX86)>; + +// libc: memcpy is universal; memset_pattern only on Darwin. +def Libc : LibcallLibrary<"libc", (add memcpy, + LibcallImpls<(add memset_pattern), isDarwin>)>; + +// libm: sqrt is universal; sincos only on x86. +def Libm : LibcallLibrary<"libm", (add sqrt, + LibcallImpls<(add sincos), isX86>)>; + +// One standalone implementation function is emitted per LibcallLibrary. + +// CHECK: static void setAvailableLibFuncs_libc(llvm::RTLIB::RuntimeLibcallsInfo &Info, const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName, LongDoubleFormat LongDoubleFormat) { +// CHECK-NEXT: { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { +// CHECK-NEXT: RTLIB::impl_memcpy, // memcpy +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: if (TT.isOSDarwin()) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls_isDarwin[] = { +// CHECK-NEXT: RTLIB::impl_memset_pattern, // memset_pattern +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls_isDarwin) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-NEXT: } + +// CHECK: static void setAvailableLibFuncs_libm(llvm::RTLIB::RuntimeLibcallsInfo &Info, const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName, LongDoubleFormat LongDoubleFormat) { +// CHECK-NEXT: { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { +// CHECK-NEXT: RTLIB::impl_sqrt, // sqrt +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: if (TT.isX86()) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls_isX86[] = { +// CHECK-NEXT: RTLIB::impl_sincos, // sincos +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls_isX86) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-NEXT: } diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-library-name-merge.td b/llvm/test/TableGen/RuntimeLibcallEmitter-library-name-merge.td new file mode 100644 index 0000000000000..06b900025d230 --- /dev/null +++ b/llvm/test/TableGen/RuntimeLibcallEmitter-library-name-merge.td @@ -0,0 +1,102 @@ +// RUN: llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s | FileCheck %s + +// Several libraries sharing one linker name (a GNU and a Darwin "libc") merge +// into a single setAvailableLibFuncs_libc. The shared core is emitted once, +// unguarded; each variant's guarded block carries only its own extras. + +include "llvm/IR/RuntimeLibcallsImpl.td" + +def MEMCPY : RuntimeLibcall; +def MEMSET : RuntimeLibcall; +def BZERO : RuntimeLibcall; +def STPCPY : RuntimeLibcall; + +def memcpy : RuntimeLibcallImpl<MEMCPY>; +def memset : RuntimeLibcallImpl<MEMSET>; +def bzero : RuntimeLibcallImpl<BZERO>; +def stpcpy : RuntimeLibcallImpl<STPCPY>; + +def IsDarwin : LibcallPredicate<[{TT.isOSDarwin()}]>; +def IsLinux : LibcallPredicate<[{TT.isOSLinux()}]>; +def isDarwin : RuntimeLibcallAvailability<(all_of IsDarwin)>; +def isLinux : RuntimeLibcallAvailability<(all_of IsLinux)>; + +def SQRT_F64 : RuntimeLibcall; +def sqrt : RuntimeLibcallImpl<SQRT_F64, "sqrt">; + +// The core libc functions shared by every libc variant. +defvar CoreLibc = (add memcpy, memset); + +// Each system's libc = the common core + its own extras, selected by Pred. +def GnuLibc : LibcallLibrary<"libc", (add CoreLibc, stpcpy)> { let Pred = isLinux; } +def DarwinLibc : LibcallLibrary<"libc", (add CoreLibc, bzero)> { let Pred = isDarwin; } + +// sqrt appears in both variants but with a different calling convention +// (ARM_AAPCS on GNU, default on Darwin), so it must not be hoisted into the +// shared core (that would drop the per-target CC). +def GnuLibm : LibcallLibrary<"libm", (add LibcallsWithCC<(add sqrt), ARM_AAPCS>)> { + let Pred = isLinux; +} +def DarwinLibm : LibcallLibrary<"libm", (add sqrt)> { let Pred = isDarwin; } + +// The shared core (memcpy, memset) is emitted once and unguarded; each variant's +// guarded block carries only its own extras (bzero for Darwin, stpcpy for GNU). + +// CHECK: static void setAvailableLibFuncs_libc(llvm::RTLIB::RuntimeLibcallsInfo &Info, const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName, LongDoubleFormat LongDoubleFormat) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { +// CHECK-NEXT: RTLIB::impl_memcpy, // memcpy +// CHECK-NEXT: RTLIB::impl_memset, // memset +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: if (TT.isOSDarwin()) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { +// CHECK-NEXT: RTLIB::impl_bzero, // bzero +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-NEXT: if (TT.isOSLinux()) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { +// CHECK-NEXT: RTLIB::impl_stpcpy, // stpcpy +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-NEXT: } + +// sqrt differs in calling convention between the two libm variants, so it stays +// per-variant: no shared-core hoist, and the GNU variant keeps its ARM_AAPCS. + +// CHECK: static void setAvailableLibFuncs_libm(llvm::RTLIB::RuntimeLibcallsInfo &Info, const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName, LongDoubleFormat LongDoubleFormat) { +// CHECK-NEXT: if (TT.isOSDarwin()) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { +// CHECK-NEXT: RTLIB::impl_sqrt, // sqrt +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-NEXT: if (TT.isOSLinux()) { +// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls_AlwaysAvailable_ARM_AAPCS[] = { +// CHECK-NEXT: RTLIB::impl_sqrt, // sqrt +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls_AlwaysAvailable_ARM_AAPCS) { +// CHECK-NEXT: Info.setAvailable(Impl); +// CHECK-NEXT: Info.setLibcallImplCallingConv(Impl, CallingConv::ARM_AAPCS); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: } +// CHECK-NEXT: } diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td b/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td index 640b3ba7e5435..4fd713bd158dc 100644 --- a/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td +++ b/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td @@ -37,8 +37,8 @@ def dup1 : RuntimeLibcallImpl<ANOTHER_DUP>; // CHECK-EMPTY: // CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { -// CHECK-NEXT: RTLIB::impl_func_b, // func_b // CHECK-NEXT: RTLIB::impl_func_a, // func_a +// CHECK-NEXT: RTLIB::impl_func_b, // func_b // CHECK-NEXT: }; // CHECK-EMPTY: // CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) { @@ -82,8 +82,8 @@ def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB, // CHECK-NEXT: AvailableLibcallImpls = SystemAvailableImpls; // CHECK-EMPTY: // CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = { -// CHECK-NEXT: RTLIB::impl_dup1, // dup1 // CHECK-NEXT: RTLIB::impl_dup0, // dup0 +// CHECK-NEXT: RTLIB::impl_dup1, // dup1 // CHECK-NEXT: RTLIB::impl_other_func, // other_func // CHECK-NEXT: RTLIB::impl_func_a, // func_a // CHECK-NEXT: RTLIB::impl_func_b, // func_b diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp index 7a76c1740b53b..2dbff92f623c0 100644 --- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp +++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -87,6 +88,21 @@ class RuntimeLibcallEmitter { void emitGetInitRuntimeLibcallNames(raw_ostream &OS) const; + // Emit the sorted per-predicate `setAvailable` tables/loops. The + // always-available bucket emits at \p BaseIndent; each predicated bucket is + // wrapped in `if (pred)`. \p Receiver prefixes the calls ("Info." for the + // standalone library functions, empty otherwise). + void + emitPredicateGroups(raw_ostream &OS, const Record *R, + DenseMap<PredicateWithCC, LibcallsWithCC> &Pred2Funcs, + SetVector<PredicateWithCC> &PredicateSorter, + unsigned BaseIndent, StringRef Receiver) const; + + // Emit a file-local `setAvailableLibFuncs_<name>` for all LibcallLibrary defs + // sharing \p Name, each gated by its own availability predicate. + void emitLibraryFunction(raw_ostream &OS, StringRef Name, + ArrayRef<const Record *> Libs) const; + void emitSystemRuntimeLibrarySetCalls(raw_ostream &OS) const; DenseSet<StringRef> collectLibcallNames() const; @@ -371,16 +387,248 @@ const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = { emitNameMatchHashTable(OS, Table); } +void RuntimeLibcallEmitter::emitPredicateGroups( + raw_ostream &OS, const Record *R, + DenseMap<PredicateWithCC, LibcallsWithCC> &Pred2Funcs, + SetVector<PredicateWithCC> &PredicateSorter, unsigned BaseIndent, + StringRef Receiver) const { + SmallVector<PredicateWithCC, 0> SortedPredicates = + PredicateSorter.takeVector(); + + llvm::sort(SortedPredicates, [](PredicateWithCC A, PredicateWithCC B) { + StringRef AName = A.Availability ? A.Availability->getName() : ""; + StringRef BName = B.Availability ? B.Availability->getName() : ""; + if (AName != BName) + return AName < BName; + // Break name ties on the calling convention for a deterministic order. + StringRef ACC = A.CallingConv ? A.CallingConv->getName() : ""; + StringRef BCC = B.CallingConv ? B.CallingConv->getName() : ""; + return ACC < BCC; + }); + + for (PredicateWithCC Entry : SortedPredicates) { + AvailabilityPredicate SubsetPredicate(Entry.Availability); + unsigned IndentDepth = BaseIndent; + + auto It = Pred2Funcs.find(Entry); + if (It == Pred2Funcs.end()) + continue; + + // Shared-core deduplication can empty a bucket. + if (It->second.LibcallImpls.empty()) + continue; + + if (!SubsetPredicate.isAlwaysAvailable()) { + IndentDepth = BaseIndent + 2; + + OS << indent(IndentDepth); + SubsetPredicate.emitIf(OS); + } + + LibcallsWithCC &FuncsWithCC = It->second; + + std::vector<const RuntimeLibcallImpl *> &Funcs = FuncsWithCC.LibcallImpls; + + // Records which impls are available, not which is selected, so a libcall + // may have more than one. Order is irrelevant (each entry is a setAvailable + // call); sort by the provided libcall, breaking ties on the impl enum for a + // deterministic total order. + sort(Funcs, [](const RuntimeLibcallImpl *A, const RuntimeLibcallImpl *B) { + return std::make_pair(A->getProvides()->getEnumVal(), A->getEnumVal()) < + std::make_pair(B->getProvides()->getEnumVal(), B->getEnumVal()); + }); + + OS << indent(IndentDepth + 2) + << "static const RTLIB::LibcallImpl LibraryCalls"; + SubsetPredicate.emitTableVariableNameSuffix(OS); + if (FuncsWithCC.CallingConv) + OS << '_' << FuncsWithCC.CallingConv->getName(); + + OS << "[] = {\n"; + for (const RuntimeLibcallImpl *LibCallImpl : Funcs) { + OS << indent(IndentDepth + 6); + LibCallImpl->emitEnumEntry(OS); + OS << ", // " << LibCallImpl->getLibcallFuncName() << '\n'; + } + + OS << indent(IndentDepth + 2) << "};\n\n" + << indent(IndentDepth + 2) + << "for (const RTLIB::LibcallImpl Impl : LibraryCalls"; + SubsetPredicate.emitTableVariableNameSuffix(OS); + if (FuncsWithCC.CallingConv) + OS << '_' << FuncsWithCC.CallingConv->getName(); + + OS << ") {\n" + << indent(IndentDepth + 4) << Receiver << "setAvailable(Impl);\n"; + + if (FuncsWithCC.CallingConv) { + StringRef CCEnum = + FuncsWithCC.CallingConv->getValueAsString("CallingConv"); + OS << indent(IndentDepth + 4) << Receiver + << "setLibcallImplCallingConv(Impl, " << CCEnum << ");\n"; + } + + OS << indent(IndentDepth + 2) << "}\n"; + OS << '\n'; + + if (!SubsetPredicate.isAlwaysAvailable()) { + OS << indent(IndentDepth); + SubsetPredicate.emitEndIf(OS); + OS << '\n'; + } + } +} + +// Emit the linker name \p Name as a C++ identifier suffix, replacing characters +// invalid in an identifier (e.g. the '-' in "compiler-rt") with '_'. +static void emitLibFuncSuffix(raw_ostream &OS, StringRef Name) { + for (char C : Name) + OS << (isAlnum(C) || C == '_' ? C : '_'); +} + +void RuntimeLibcallEmitter::emitLibraryFunction( + raw_ostream &OS, StringRef Name, ArrayRef<const Record *> Libs) const { + // File-local; referenced only from the driver in the same fragment. + OS << "static void setAvailableLibFuncs_"; + emitLibFuncSuffix(OS, Name); + OS << "(llvm::RTLIB::RuntimeLibcallsInfo &Info, const llvm::Triple &TT, " + "ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, " + "EABI EABIVersion, StringRef ABIName, " + "LongDoubleFormat LongDoubleFormat) {\n"; + + // Per-variant expansion. Unconditional impls are tracked separately for + // cross-variant deduplication. + struct ExpandedLibrary { + const Record *Lib; + DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs; + SetVector<PredicateWithCC> PredicateSorter; + SetVector<const RuntimeLibcallImpl *> Unconditional; + }; + + SmallVector<ExpandedLibrary, 2> Expanded; + for (const Record *Lib : Libs) { + ExpandedLibrary EL; + EL.Lib = Lib; + + // Expand this library's members with a library-local Func2Preds. + SetTheory Sets; + DenseMap<const RuntimeLibcallImpl *, + std::pair<std::vector<const Record *>, const Record *>> + Func2Preds; + Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>( + Libcalls, Func2Preds)); + + SetTheory::RecSet Elements; + Sets.evaluate(Lib->getValueInit("Impls"), Elements, Lib->getLoc()); + + EL.PredicateSorter.insert( + PredicateWithCC()); // No predicate or CC override first. + + for (const Record *Elt : Elements) { + const RuntimeLibcallImpl *LibCallImpl = + Libcalls.getRuntimeLibcallImpl(Elt); + if (!LibCallImpl) { + PrintError(Lib, "entry for LibcallLibrary is not a RuntimeLibcallImpl"); + PrintNote(Elt->getLoc(), "invalid entry `" + Elt->getName() + "`"); + continue; + } + + auto It = Func2Preds.find(LibCallImpl); + if (It == Func2Preds.end()) { + EL.Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl); + EL.Unconditional.insert(LibCallImpl); + continue; + } + + for (const Record *Pred : It->second.first) { + const Record *CC = It->second.second; + PredicateWithCC Key(Pred, CC); + auto &Entry = EL.Pred2Funcs[Key]; + Entry.LibcallImpls.push_back(LibCallImpl); + Entry.CallingConv = CC; + EL.PredicateSorter.insert(Key); + } + } + + Expanded.pus... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/217592 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
