From 8f67c6a5669e219a6cd0ed40fd1ba9be620148d6 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 11 Jul 2024 12:57:20 -0500 Subject: [PATCH] [LLVM][LTO] Factor out RTLib calls and allow them to be dropped Summary: The LTO pass and LLD linker have logic in them that forces extraction and prevent internalization of needed runtime calls. However, these currently take all RTLibcalls into account, even if the target does not support them. The target opts-out of a libcall if it sets its name to nullptr. This patch pulls this logic out into a class in the header so that LTO / lld can use it to determine if a symbol actually needs to be kept. This is important for targets like AMDGPU that want to be able to use `lld` to perform the final link step, but cannot maintain the overhead of several unused function calls. --- lld/COFF/Driver.cpp | 7 +- lld/ELF/Driver.cpp | 6 +- lld/wasm/Driver.cpp | 6 +- llvm/include/llvm/CodeGen/TargetLowering.h | 464 +++++++++++++++++++-- llvm/include/llvm/LTO/LTO.h | 2 +- llvm/lib/CodeGen/TargetLoweringBase.cpp | 373 +---------------- llvm/lib/LTO/LTO.cpp | 15 +- llvm/lib/Object/IRSymtab.cpp | 20 +- llvm/tools/lto/lto.cpp | 2 +- 9 files changed, 478 insertions(+), 417 deletions(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index cef6271e4c8f8a..9e28b1c50be504 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2428,9 +2428,12 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // file's symbol table. If any of those library functions are defined in a // bitcode file in an archive member, we need to arrange to use LTO to // compile those archive members by adding them to the link beforehand. - if (!ctx.bitcodeFileInstances.empty()) - for (auto *s : lto::LTO::getRuntimeLibcallSymbols()) + if (!ctx.bitcodeFileInstances.empty()) { + llvm::Triple TT( + ctx.bitcodeFileInstances.front()->obj->getTargetTriple()); + for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT)) ctx.symtab.addLibcall(s); + } // Windows specific -- if __load_config_used can be resolved, resolve it. if (ctx.symtab.findUnderscore("_load_config_used")) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index abfa313bfef0e9..5c7ff8dcda9454 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2883,9 +2883,11 @@ template void LinkerDriver::link(opt::InputArgList &args) { // to, i.e. if the symbol's definition is in bitcode. Any other required // libcall symbols will be added to the link after LTO when we add the LTO // object file to the link. - if (!ctx.bitcodeFiles.empty()) - for (auto *s : lto::LTO::getRuntimeLibcallSymbols()) + if (!ctx.bitcodeFiles.empty()) { + llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple()); + for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT)) handleLibcall(s); + } // Archive members defining __wrap symbols may be extracted. std::vector wrapped = addWrappedSymbols(args); diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index d099689911fc6b..1d545420e182ce 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -1319,9 +1319,11 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // We only need to add libcall symbols to the link before LTO if the symbol's // definition is in bitcode. Any other required libcall symbols will be added // to the link after LTO when we add the LTO object file to the link. - if (!ctx.bitcodeFiles.empty()) - for (auto *s : lto::LTO::getRuntimeLibcallSymbols()) + if (!ctx.bitcodeFiles.empty()) { + llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple()); + for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT)) handleLibcall(s); + } if (errorCount()) return; diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 55b60b01e58277..bda55ab1402be8 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -189,6 +189,436 @@ struct MemOp { } }; +struct LibcallsInfo { + explicit LibcallsInfo(const Triple &TT) { + initLibcalls(TT); + initCmpLibcallCCs(); + } + + /// Rename the default libcall routine name for the specified libcall. + void setLibcallName(RTLIB::Libcall Call, const char *Name) { + LibcallRoutineNames[Call] = Name; + } + + void setLibcallName(ArrayRef Calls, const char *Name) { + for (auto Call : Calls) + setLibcallName(Call, Name); + } + + /// Get the libcall routine name for the specified libcall. + const char *getLibcallName(RTLIB::Libcall Call) const { + return LibcallRoutineNames[Call]; + } + + /// Override the default CondCode to be used to test the result of the + /// comparison libcall against zero. + void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) { + CmpLibcallCCs[Call] = CC; + } + + /// Get the CondCode that's to be used to test the result of the comparison + /// libcall against zero. + ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { + return CmpLibcallCCs[Call]; + } + + /// Set the CallingConv that should be used for the specified libcall. + void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { + LibcallCallingConvs[Call] = CC; + } + + /// Get the CallingConv that should be used for the specified libcall. + CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { + return LibcallCallingConvs[Call]; + } + + iterator_range getLibcallNames() { + return llvm::make_range(LibcallRoutineNames, + LibcallRoutineNames + RTLIB::UNKNOWN_LIBCALL); + } + +private: + /// Stores the name each libcall. + const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1]; + + /// The ISD::CondCode that should be used to test the result of each of the + /// comparison libcall against zero. + ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; + + /// Stores the CallingConv that should be used for each libcall. + CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; + + static bool darwinHasSinCos(const Triple &TT) { + assert(TT.isOSDarwin() && "should be called with darwin triple"); + // Don't bother with 32 bit x86. + if (TT.getArch() == Triple::x86) + return false; + // Macos < 10.9 has no sincos_stret. + if (TT.isMacOSX()) + return !TT.isMacOSXVersionLT(10, 9) && TT.isArch64Bit(); + // iOS < 7.0 has no sincos_stret. + if (TT.isiOS()) + return !TT.isOSVersionLT(7, 0); + // Any other darwin such as WatchOS/TvOS is new enough. + return true; + } + + /// Sets default libcall calling conventions. + void initCmpLibcallCCs() { + std::fill(CmpLibcallCCs, CmpLibcallCCs + RTLIB::UNKNOWN_LIBCALL, + ISD::SETCC_INVALID); + CmpLibcallCCs[RTLIB::OEQ_F32] = ISD::SETEQ; + CmpLibcallCCs[RTLIB::OEQ_F64] = ISD::SETEQ; + CmpLibcallCCs[RTLIB::OEQ_F128] = ISD::SETEQ; + CmpLibcallCCs[RTLIB::OEQ_PPCF128] = ISD::SETEQ; + CmpLibcallCCs[RTLIB::UNE_F32] = ISD::SETNE; + CmpLibcallCCs[RTLIB::UNE_F64] = ISD::SETNE; + CmpLibcallCCs[RTLIB::UNE_F128] = ISD::SETNE; + CmpLibcallCCs[RTLIB::UNE_PPCF128] = ISD::SETNE; + CmpLibcallCCs[RTLIB::OGE_F32] = ISD::SETGE; + CmpLibcallCCs[RTLIB::OGE_F64] = ISD::SETGE; + CmpLibcallCCs[RTLIB::OGE_F128] = ISD::SETGE; + CmpLibcallCCs[RTLIB::OGE_PPCF128] = ISD::SETGE; + CmpLibcallCCs[RTLIB::OLT_F32] = ISD::SETLT; + CmpLibcallCCs[RTLIB::OLT_F64] = ISD::SETLT; + CmpLibcallCCs[RTLIB::OLT_F128] = ISD::SETLT; + CmpLibcallCCs[RTLIB::OLT_PPCF128] = ISD::SETLT; + CmpLibcallCCs[RTLIB::OLE_F32] = ISD::SETLE; + CmpLibcallCCs[RTLIB::OLE_F64] = ISD::SETLE; + CmpLibcallCCs[RTLIB::OLE_F128] = ISD::SETLE; + CmpLibcallCCs[RTLIB::OLE_PPCF128] = ISD::SETLE; + CmpLibcallCCs[RTLIB::OGT_F32] = ISD::SETGT; + CmpLibcallCCs[RTLIB::OGT_F64] = ISD::SETGT; + CmpLibcallCCs[RTLIB::OGT_F128] = ISD::SETGT; + CmpLibcallCCs[RTLIB::OGT_PPCF128] = ISD::SETGT; + CmpLibcallCCs[RTLIB::UO_F32] = ISD::SETNE; + CmpLibcallCCs[RTLIB::UO_F64] = ISD::SETNE; + CmpLibcallCCs[RTLIB::UO_F128] = ISD::SETNE; + CmpLibcallCCs[RTLIB::UO_PPCF128] = ISD::SETNE; + } + + /// Set default libcall names. + void initLibcalls(const Triple &TT) { + std::fill(std::begin(LibcallRoutineNames), std::end(LibcallRoutineNames), + nullptr); + +#define HANDLE_LIBCALL(code, name) setLibcallName(RTLIB::code, name); +#include "llvm/IR/RuntimeLibcalls.def" +#undef HANDLE_LIBCALL + + // Initialize calling conventions to their default. + for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC) + setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C); + + // Use the f128 variants of math functions on x86_64 + if (TT.getArch() == Triple::ArchType::x86_64 && TT.isGNUEnvironment()) { + setLibcallName(RTLIB::REM_F128, "fmodf128"); + setLibcallName(RTLIB::FMA_F128, "fmaf128"); + setLibcallName(RTLIB::SQRT_F128, "sqrtf128"); + setLibcallName(RTLIB::CBRT_F128, "cbrtf128"); + setLibcallName(RTLIB::LOG_F128, "logf128"); + setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite"); + setLibcallName(RTLIB::LOG2_F128, "log2f128"); + setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite"); + setLibcallName(RTLIB::LOG10_F128, "log10f128"); + setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite"); + setLibcallName(RTLIB::EXP_F128, "expf128"); + setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite"); + setLibcallName(RTLIB::EXP2_F128, "exp2f128"); + setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite"); + setLibcallName(RTLIB::EXP10_F128, "exp10f128"); + setLibcallName(RTLIB::SIN_F128, "sinf128"); + setLibcallName(RTLIB::COS_F128, "cosf128"); + setLibcallName(RTLIB::TAN_F128, "tanf128"); + setLibcallName(RTLIB::SINCOS_F128, "sincosf128"); + setLibcallName(RTLIB::POW_F128, "powf128"); + setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite"); + setLibcallName(RTLIB::CEIL_F128, "ceilf128"); + setLibcallName(RTLIB::TRUNC_F128, "truncf128"); + setLibcallName(RTLIB::RINT_F128, "rintf128"); + setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128"); + setLibcallName(RTLIB::ROUND_F128, "roundf128"); + setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128"); + setLibcallName(RTLIB::FLOOR_F128, "floorf128"); + setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128"); + setLibcallName(RTLIB::FMIN_F128, "fminf128"); + setLibcallName(RTLIB::FMAX_F128, "fmaxf128"); + setLibcallName(RTLIB::LROUND_F128, "lroundf128"); + setLibcallName(RTLIB::LLROUND_F128, "llroundf128"); + setLibcallName(RTLIB::LRINT_F128, "lrintf128"); + setLibcallName(RTLIB::LLRINT_F128, "llrintf128"); + setLibcallName(RTLIB::LDEXP_F128, "ldexpf128"); + setLibcallName(RTLIB::FREXP_F128, "frexpf128"); + } + + // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf". + if (TT.isPPC()) { + setLibcallName(RTLIB::ADD_F128, "__addkf3"); + setLibcallName(RTLIB::SUB_F128, "__subkf3"); + setLibcallName(RTLIB::MUL_F128, "__mulkf3"); + setLibcallName(RTLIB::DIV_F128, "__divkf3"); + setLibcallName(RTLIB::POWI_F128, "__powikf2"); + setLibcallName(RTLIB::FPEXT_F32_F128, "__extendsfkf2"); + setLibcallName(RTLIB::FPEXT_F64_F128, "__extenddfkf2"); + setLibcallName(RTLIB::FPROUND_F128_F32, "__trunckfsf2"); + setLibcallName(RTLIB::FPROUND_F128_F64, "__trunckfdf2"); + setLibcallName(RTLIB::FPTOSINT_F128_I32, "__fixkfsi"); + setLibcallName(RTLIB::FPTOSINT_F128_I64, "__fixkfdi"); + setLibcallName(RTLIB::FPTOSINT_F128_I128, "__fixkfti"); + setLibcallName(RTLIB::FPTOUINT_F128_I32, "__fixunskfsi"); + setLibcallName(RTLIB::FPTOUINT_F128_I64, "__fixunskfdi"); + setLibcallName(RTLIB::FPTOUINT_F128_I128, "__fixunskfti"); + setLibcallName(RTLIB::SINTTOFP_I32_F128, "__floatsikf"); + setLibcallName(RTLIB::SINTTOFP_I64_F128, "__floatdikf"); + setLibcallName(RTLIB::SINTTOFP_I128_F128, "__floattikf"); + setLibcallName(RTLIB::UINTTOFP_I32_F128, "__floatunsikf"); + setLibcallName(RTLIB::UINTTOFP_I64_F128, "__floatundikf"); + setLibcallName(RTLIB::UINTTOFP_I128_F128, "__floatuntikf"); + setLibcallName(RTLIB::OEQ_F128, "__eqkf2"); + setLibcallName(RTLIB::UNE_F128, "__nekf2"); + setLibcallName(RTLIB::OGE_F128, "__gekf2"); + setLibcallName(RTLIB::OLT_F128, "__ltkf2"); + setLibcallName(RTLIB::OLE_F128, "__lekf2"); + setLibcallName(RTLIB::OGT_F128, "__gtkf2"); + setLibcallName(RTLIB::UO_F128, "__unordkf2"); + } + + // A few names are different on particular architectures or environments. + if (TT.isOSDarwin()) { + // For f16/f32 conversions, Darwin uses the standard naming scheme, + // instead of the gnueabi-style __gnu_*_ieee. + // FIXME: What about other targets? + setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2"); + setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2"); + + // Some darwins have an optimized __bzero/bzero function. + switch (TT.getArch()) { + case Triple::x86: + case Triple::x86_64: + if (TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6)) + setLibcallName(RTLIB::BZERO, "__bzero"); + break; + case Triple::aarch64: + case Triple::aarch64_32: + setLibcallName(RTLIB::BZERO, "bzero"); + break; + default: + break; + } + + if (darwinHasSinCos(TT)) { + setLibcallName(RTLIB::SINCOS_STRET_F32, "__sincosf_stret"); + setLibcallName(RTLIB::SINCOS_STRET_F64, "__sincos_stret"); + if (TT.isWatchABI()) { + setLibcallCallingConv(RTLIB::SINCOS_STRET_F32, + CallingConv::ARM_AAPCS_VFP); + setLibcallCallingConv(RTLIB::SINCOS_STRET_F64, + CallingConv::ARM_AAPCS_VFP); + } + } + + switch (TT.getOS()) { + case Triple::MacOSX: + if (TT.isMacOSXVersionLT(10, 9)) { + setLibcallName(RTLIB::EXP10_F32, nullptr); + setLibcallName(RTLIB::EXP10_F64, nullptr); + } else { + setLibcallName(RTLIB::EXP10_F32, "__exp10f"); + setLibcallName(RTLIB::EXP10_F64, "__exp10"); + } + break; + case Triple::IOS: + case Triple::TvOS: + case Triple::WatchOS: + case Triple::XROS: + if (!TT.isWatchOS() && (TT.isOSVersionLT(7, 0) || + (TT.isOSVersionLT(9, 0) && TT.isX86()))) { + setLibcallName(RTLIB::EXP10_F32, nullptr); + setLibcallName(RTLIB::EXP10_F64, nullptr); + } else { + setLibcallName(RTLIB::EXP10_F32, "__exp10f"); + setLibcallName(RTLIB::EXP10_F64, "__exp10"); + } + + break; + default: + break; + } + } else { + setLibcallName(RTLIB::FPEXT_F16_F32, "__gnu_h2f_ieee"); + setLibcallName(RTLIB::FPROUND_F32_F16, "__gnu_f2h_ieee"); + } + + if (TT.isGNUEnvironment() || TT.isOSFuchsia() || + (TT.isAndroid() && !TT.isAndroidVersionLT(9))) { + setLibcallName(RTLIB::SINCOS_F32, "sincosf"); + setLibcallName(RTLIB::SINCOS_F64, "sincos"); + setLibcallName(RTLIB::SINCOS_F80, "sincosl"); + setLibcallName(RTLIB::SINCOS_F128, "sincosl"); + setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl"); + } + + if (TT.isPS()) { + setLibcallName(RTLIB::SINCOS_F32, "sincosf"); + setLibcallName(RTLIB::SINCOS_F64, "sincos"); + } + + if (TT.isOSOpenBSD()) { + setLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL, nullptr); + } + + if (TT.isOSWindows() && !TT.isOSCygMing()) { + setLibcallName(RTLIB::LDEXP_F32, nullptr); + setLibcallName(RTLIB::LDEXP_F80, nullptr); + setLibcallName(RTLIB::LDEXP_F128, nullptr); + setLibcallName(RTLIB::LDEXP_PPCF128, nullptr); + + setLibcallName(RTLIB::FREXP_F32, nullptr); + setLibcallName(RTLIB::FREXP_F80, nullptr); + setLibcallName(RTLIB::FREXP_F128, nullptr); + setLibcallName(RTLIB::FREXP_PPCF128, nullptr); + } + + if (TT.isAArch64()) { + if (TT.isOSMSVCRT()) { + // MSVCRT doesn't have powi; fall back to pow + setLibcallName(RTLIB::POWI_F32, nullptr); + setLibcallName(RTLIB::POWI_F64, nullptr); + } + } + + // Disable most libcalls on AMDGPU. + if (TT.isAMDGPU()) { + for (int I = 0; I < RTLIB::UNKNOWN_LIBCALL; ++I) { + if (I < RTLIB::ATOMIC_LOAD || I > RTLIB::ATOMIC_FETCH_NAND_16) + setLibcallName(static_cast(I), nullptr); + } + } + + if (TT.isARM() || TT.isThumb()) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + setLibcallName(RTLIB::MUL_I128, nullptr); + setLibcallName(RTLIB::MULO_I64, nullptr); + setLibcallName(RTLIB::MULO_I128, nullptr); + + if (TT.isOSMSVCRT()) { + // MSVCRT doesn't have powi; fall back to pow + setLibcallName(RTLIB::POWI_F32, nullptr); + setLibcallName(RTLIB::POWI_F64, nullptr); + } + } + + if (TT.getArch() == Triple::ArchType::avr) { + // Division rtlib functions (not supported), use divmod functions instead + setLibcallName(RTLIB::SDIV_I8, nullptr); + setLibcallName(RTLIB::SDIV_I16, nullptr); + setLibcallName(RTLIB::SDIV_I32, nullptr); + setLibcallName(RTLIB::UDIV_I8, nullptr); + setLibcallName(RTLIB::UDIV_I16, nullptr); + setLibcallName(RTLIB::UDIV_I32, nullptr); + + // Modulus rtlib functions (not supported), use divmod functions instead + setLibcallName(RTLIB::SREM_I8, nullptr); + setLibcallName(RTLIB::SREM_I16, nullptr); + setLibcallName(RTLIB::SREM_I32, nullptr); + setLibcallName(RTLIB::UREM_I8, nullptr); + setLibcallName(RTLIB::UREM_I16, nullptr); + setLibcallName(RTLIB::UREM_I32, nullptr); + } + + if (TT.getArch() == Triple::ArchType::hexagon) { + // These cause problems when the shift amount is non-constant. + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + } + + if (TT.isLoongArch()) { + if (!TT.isLoongArch64()) { + // Set libcalls. + setLibcallName(RTLIB::MUL_I128, nullptr); + // The MULO libcall is not part of libgcc, only compiler-rt. + setLibcallName(RTLIB::MULO_I64, nullptr); + } + // The MULO libcall is not part of libgcc, only compiler-rt. + setLibcallName(RTLIB::MULO_I128, nullptr); + } + + if (TT.isMIPS32()) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + setLibcallName(RTLIB::MUL_I128, nullptr); + setLibcallName(RTLIB::MULO_I64, nullptr); + setLibcallName(RTLIB::MULO_I128, nullptr); + } + + if (TT.isPPC()) { + if (!TT.isPPC64()) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + setLibcallName(RTLIB::MUL_I128, nullptr); + setLibcallName(RTLIB::MULO_I64, nullptr); + } + setLibcallName(RTLIB::MULO_I128, nullptr); + } + + if (TT.isRISCV32()) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + setLibcallName(RTLIB::MUL_I128, nullptr); + setLibcallName(RTLIB::MULO_I64, nullptr); + } + + if (TT.isSPARC()) { + if (!TT.isSPARC64()) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::MULO_I64, nullptr); + setLibcallName(RTLIB::MUL_I128, nullptr); + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + } + setLibcallName(RTLIB::MULO_I128, nullptr); + } + + if (TT.isSystemZ()) { + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + } + + if (TT.isX86()) { + if (TT.getArch() == Triple::ArchType::x86) { + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, nullptr); + setLibcallName(RTLIB::SRL_I128, nullptr); + setLibcallName(RTLIB::SRA_I128, nullptr); + setLibcallName(RTLIB::MUL_I128, nullptr); + // The MULO libcall is not part of libgcc, only compiler-rt. + setLibcallName(RTLIB::MULO_I64, nullptr); + } + + // The MULO libcall is not part of libgcc, only compiler-rt. + setLibcallName(RTLIB::MULO_I128, nullptr); + + if (TT.isOSMSVCRT()) { + // MSVCRT doesn't have powi; fall back to pow + setLibcallName(RTLIB::POWI_F32, nullptr); + setLibcallName(RTLIB::POWI_F64, nullptr); + } + } + } +}; + /// This base class for TargetLowering contains the SelectionDAG-independent /// parts that can be used from the rest of CodeGen. class TargetLoweringBase { @@ -3410,44 +3840,40 @@ class TargetLoweringBase { return nullptr; } - //===--------------------------------------------------------------------===// - // Runtime Library hooks - // - /// Rename the default libcall routine name for the specified libcall. void setLibcallName(RTLIB::Libcall Call, const char *Name) { - LibcallRoutineNames[Call] = Name; + Libcalls.setLibcallName(Call, Name); } + void setLibcallName(ArrayRef Calls, const char *Name) { - for (auto Call : Calls) - setLibcallName(Call, Name); + Libcalls.setLibcallName(Calls, Name); } /// Get the libcall routine name for the specified libcall. const char *getLibcallName(RTLIB::Libcall Call) const { - return LibcallRoutineNames[Call]; + return Libcalls.getLibcallName(Call); } /// Override the default CondCode to be used to test the result of the /// comparison libcall against zero. void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) { - CmpLibcallCCs[Call] = CC; + Libcalls.setCmpLibcallCC(Call, CC); } /// Get the CondCode that's to be used to test the result of the comparison /// libcall against zero. ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { - return CmpLibcallCCs[Call]; + return Libcalls.getCmpLibcallCC(Call); } /// Set the CallingConv that should be used for the specified libcall. void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { - LibcallCallingConvs[Call] = CC; + Libcalls.setLibcallCallingConv(Call, CC); } /// Get the CallingConv that should be used for the specified libcall. CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { - return LibcallCallingConvs[Call]; + return Libcalls.getLibcallCallingConv(Call); } /// Execute target specific actions to finalize target lowering. @@ -3626,18 +4052,8 @@ class TargetLoweringBase { std::map, MVT::SimpleValueType> PromoteToType; - /// Stores the name each libcall. - const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1]; - - /// The ISD::CondCode that should be used to test the result of each of the - /// comparison libcall against zero. - ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; - - /// Stores the CallingConv that should be used for each libcall. - CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; - - /// Set default libcall names and calling conventions. - void InitLibcalls(const Triple &TT); + /// The list of libcalls that the target will use. + LibcallsInfo Libcalls; /// The bits of IndexedModeActions used to store the legalisation actions /// We store the data as | ML | MS | L | S | each taking 4 bits. diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 94996ae89e35d0..30eda34cd7ba54 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -301,7 +301,7 @@ class LTO { /// Static method that returns a list of libcall symbols that can be generated /// by LTO but might not be visible from bitcode symbol table. - static ArrayRef getRuntimeLibcallSymbols(); + static SmallVector getRuntimeLibcallSymbols(const Triple &TT); private: Config Conf; diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 4a2db272defd11..f2aba006cc0dca 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -98,338 +98,6 @@ static cl::opt DisableStrictNodeMutation("disable-strictnode-mutation", cl::desc("Don't mutate strict-float node to a legalize node"), cl::init(false), cl::Hidden); -static bool darwinHasSinCos(const Triple &TT) { - assert(TT.isOSDarwin() && "should be called with darwin triple"); - // Don't bother with 32 bit x86. - if (TT.getArch() == Triple::x86) - return false; - // Macos < 10.9 has no sincos_stret. - if (TT.isMacOSX()) - return !TT.isMacOSXVersionLT(10, 9) && TT.isArch64Bit(); - // iOS < 7.0 has no sincos_stret. - if (TT.isiOS()) - return !TT.isOSVersionLT(7, 0); - // Any other darwin such as WatchOS/TvOS is new enough. - return true; -} - -void TargetLoweringBase::InitLibcalls(const Triple &TT) { -#define HANDLE_LIBCALL(code, name) \ - setLibcallName(RTLIB::code, name); -#include "llvm/IR/RuntimeLibcalls.def" -#undef HANDLE_LIBCALL - // Initialize calling conventions to their default. - for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC) - setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C); - - // Use the f128 variants of math functions on x86_64 - if (TT.getArch() == Triple::ArchType::x86_64 && TT.isGNUEnvironment()) { - setLibcallName(RTLIB::REM_F128, "fmodf128"); - setLibcallName(RTLIB::FMA_F128, "fmaf128"); - setLibcallName(RTLIB::SQRT_F128, "sqrtf128"); - setLibcallName(RTLIB::CBRT_F128, "cbrtf128"); - setLibcallName(RTLIB::LOG_F128, "logf128"); - setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite"); - setLibcallName(RTLIB::LOG2_F128, "log2f128"); - setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite"); - setLibcallName(RTLIB::LOG10_F128, "log10f128"); - setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite"); - setLibcallName(RTLIB::EXP_F128, "expf128"); - setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite"); - setLibcallName(RTLIB::EXP2_F128, "exp2f128"); - setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite"); - setLibcallName(RTLIB::EXP10_F128, "exp10f128"); - setLibcallName(RTLIB::SIN_F128, "sinf128"); - setLibcallName(RTLIB::COS_F128, "cosf128"); - setLibcallName(RTLIB::TAN_F128, "tanf128"); - setLibcallName(RTLIB::SINCOS_F128, "sincosf128"); - setLibcallName(RTLIB::POW_F128, "powf128"); - setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite"); - setLibcallName(RTLIB::CEIL_F128, "ceilf128"); - setLibcallName(RTLIB::TRUNC_F128, "truncf128"); - setLibcallName(RTLIB::RINT_F128, "rintf128"); - setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128"); - setLibcallName(RTLIB::ROUND_F128, "roundf128"); - setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128"); - setLibcallName(RTLIB::FLOOR_F128, "floorf128"); - setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128"); - setLibcallName(RTLIB::FMIN_F128, "fminf128"); - setLibcallName(RTLIB::FMAX_F128, "fmaxf128"); - setLibcallName(RTLIB::LROUND_F128, "lroundf128"); - setLibcallName(RTLIB::LLROUND_F128, "llroundf128"); - setLibcallName(RTLIB::LRINT_F128, "lrintf128"); - setLibcallName(RTLIB::LLRINT_F128, "llrintf128"); - setLibcallName(RTLIB::LDEXP_F128, "ldexpf128"); - setLibcallName(RTLIB::FREXP_F128, "frexpf128"); - } - - // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf". - if (TT.isPPC()) { - setLibcallName(RTLIB::ADD_F128, "__addkf3"); - setLibcallName(RTLIB::SUB_F128, "__subkf3"); - setLibcallName(RTLIB::MUL_F128, "__mulkf3"); - setLibcallName(RTLIB::DIV_F128, "__divkf3"); - setLibcallName(RTLIB::POWI_F128, "__powikf2"); - setLibcallName(RTLIB::FPEXT_F32_F128, "__extendsfkf2"); - setLibcallName(RTLIB::FPEXT_F64_F128, "__extenddfkf2"); - setLibcallName(RTLIB::FPROUND_F128_F32, "__trunckfsf2"); - setLibcallName(RTLIB::FPROUND_F128_F64, "__trunckfdf2"); - setLibcallName(RTLIB::FPTOSINT_F128_I32, "__fixkfsi"); - setLibcallName(RTLIB::FPTOSINT_F128_I64, "__fixkfdi"); - setLibcallName(RTLIB::FPTOSINT_F128_I128, "__fixkfti"); - setLibcallName(RTLIB::FPTOUINT_F128_I32, "__fixunskfsi"); - setLibcallName(RTLIB::FPTOUINT_F128_I64, "__fixunskfdi"); - setLibcallName(RTLIB::FPTOUINT_F128_I128, "__fixunskfti"); - setLibcallName(RTLIB::SINTTOFP_I32_F128, "__floatsikf"); - setLibcallName(RTLIB::SINTTOFP_I64_F128, "__floatdikf"); - setLibcallName(RTLIB::SINTTOFP_I128_F128, "__floattikf"); - setLibcallName(RTLIB::UINTTOFP_I32_F128, "__floatunsikf"); - setLibcallName(RTLIB::UINTTOFP_I64_F128, "__floatundikf"); - setLibcallName(RTLIB::UINTTOFP_I128_F128, "__floatuntikf"); - setLibcallName(RTLIB::OEQ_F128, "__eqkf2"); - setLibcallName(RTLIB::UNE_F128, "__nekf2"); - setLibcallName(RTLIB::OGE_F128, "__gekf2"); - setLibcallName(RTLIB::OLT_F128, "__ltkf2"); - setLibcallName(RTLIB::OLE_F128, "__lekf2"); - setLibcallName(RTLIB::OGT_F128, "__gtkf2"); - setLibcallName(RTLIB::UO_F128, "__unordkf2"); - } - - // A few names are different on particular architectures or environments. - if (TT.isOSDarwin()) { - // For f16/f32 conversions, Darwin uses the standard naming scheme, instead - // of the gnueabi-style __gnu_*_ieee. - // FIXME: What about other targets? - setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2"); - setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2"); - - // Some darwins have an optimized __bzero/bzero function. - switch (TT.getArch()) { - case Triple::x86: - case Triple::x86_64: - if (TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6)) - setLibcallName(RTLIB::BZERO, "__bzero"); - break; - case Triple::aarch64: - case Triple::aarch64_32: - setLibcallName(RTLIB::BZERO, "bzero"); - break; - default: - break; - } - - if (darwinHasSinCos(TT)) { - setLibcallName(RTLIB::SINCOS_STRET_F32, "__sincosf_stret"); - setLibcallName(RTLIB::SINCOS_STRET_F64, "__sincos_stret"); - if (TT.isWatchABI()) { - setLibcallCallingConv(RTLIB::SINCOS_STRET_F32, - CallingConv::ARM_AAPCS_VFP); - setLibcallCallingConv(RTLIB::SINCOS_STRET_F64, - CallingConv::ARM_AAPCS_VFP); - } - } - - switch (TT.getOS()) { - case Triple::MacOSX: - if (TT.isMacOSXVersionLT(10, 9)) { - setLibcallName(RTLIB::EXP10_F32, nullptr); - setLibcallName(RTLIB::EXP10_F64, nullptr); - } else { - setLibcallName(RTLIB::EXP10_F32, "__exp10f"); - setLibcallName(RTLIB::EXP10_F64, "__exp10"); - } - break; - case Triple::IOS: - case Triple::TvOS: - case Triple::WatchOS: - case Triple::XROS: - if (!TT.isWatchOS() && - (TT.isOSVersionLT(7, 0) || (TT.isOSVersionLT(9, 0) && TT.isX86()))) { - setLibcallName(RTLIB::EXP10_F32, nullptr); - setLibcallName(RTLIB::EXP10_F64, nullptr); - } else { - setLibcallName(RTLIB::EXP10_F32, "__exp10f"); - setLibcallName(RTLIB::EXP10_F64, "__exp10"); - } - - break; - default: - break; - } - } else { - setLibcallName(RTLIB::FPEXT_F16_F32, "__gnu_h2f_ieee"); - setLibcallName(RTLIB::FPROUND_F32_F16, "__gnu_f2h_ieee"); - } - - if (TT.isGNUEnvironment() || TT.isOSFuchsia() || - (TT.isAndroid() && !TT.isAndroidVersionLT(9))) { - setLibcallName(RTLIB::SINCOS_F32, "sincosf"); - setLibcallName(RTLIB::SINCOS_F64, "sincos"); - setLibcallName(RTLIB::SINCOS_F80, "sincosl"); - setLibcallName(RTLIB::SINCOS_F128, "sincosl"); - setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl"); - } - - if (TT.isPS()) { - setLibcallName(RTLIB::SINCOS_F32, "sincosf"); - setLibcallName(RTLIB::SINCOS_F64, "sincos"); - } - - if (TT.isOSOpenBSD()) { - setLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL, nullptr); - } - - if (TT.isOSWindows() && !TT.isOSCygMing()) { - setLibcallName(RTLIB::LDEXP_F32, nullptr); - setLibcallName(RTLIB::LDEXP_F80, nullptr); - setLibcallName(RTLIB::LDEXP_F128, nullptr); - setLibcallName(RTLIB::LDEXP_PPCF128, nullptr); - - setLibcallName(RTLIB::FREXP_F32, nullptr); - setLibcallName(RTLIB::FREXP_F80, nullptr); - setLibcallName(RTLIB::FREXP_F128, nullptr); - setLibcallName(RTLIB::FREXP_PPCF128, nullptr); - } - - if (TT.isAArch64()) { - if (TT.isOSMSVCRT()) { - // MSVCRT doesn't have powi; fall back to pow - setLibcallName(RTLIB::POWI_F32, nullptr); - setLibcallName(RTLIB::POWI_F64, nullptr); - } - } - - // Disable most libcalls on AMDGPU. - if (TT.isAMDGPU()) { - for (int I = 0; I < RTLIB::UNKNOWN_LIBCALL; ++I) { - if (I < RTLIB::ATOMIC_LOAD || I > RTLIB::ATOMIC_FETCH_NAND_16) - setLibcallName(static_cast(I), nullptr); - } - } - - if (TT.isARM() || TT.isThumb()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - setLibcallName(RTLIB::MUL_I128, nullptr); - setLibcallName(RTLIB::MULO_I64, nullptr); - setLibcallName(RTLIB::MULO_I128, nullptr); - - if (TT.isOSMSVCRT()) { - // MSVCRT doesn't have powi; fall back to pow - setLibcallName(RTLIB::POWI_F32, nullptr); - setLibcallName(RTLIB::POWI_F64, nullptr); - } - } - - if (TT.getArch() == Triple::ArchType::avr) { - // Division rtlib functions (not supported), use divmod functions instead - setLibcallName(RTLIB::SDIV_I8, nullptr); - setLibcallName(RTLIB::SDIV_I16, nullptr); - setLibcallName(RTLIB::SDIV_I32, nullptr); - setLibcallName(RTLIB::UDIV_I8, nullptr); - setLibcallName(RTLIB::UDIV_I16, nullptr); - setLibcallName(RTLIB::UDIV_I32, nullptr); - - // Modulus rtlib functions (not supported), use divmod functions instead - setLibcallName(RTLIB::SREM_I8, nullptr); - setLibcallName(RTLIB::SREM_I16, nullptr); - setLibcallName(RTLIB::SREM_I32, nullptr); - setLibcallName(RTLIB::UREM_I8, nullptr); - setLibcallName(RTLIB::UREM_I16, nullptr); - setLibcallName(RTLIB::UREM_I32, nullptr); - } - - if (TT.getArch() == Triple::ArchType::hexagon) { - // These cause problems when the shift amount is non-constant. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - } - - if (TT.isLoongArch()) { - if (!TT.isLoongArch64()) { - // Set libcalls. - setLibcallName(RTLIB::MUL_I128, nullptr); - // The MULO libcall is not part of libgcc, only compiler-rt. - setLibcallName(RTLIB::MULO_I64, nullptr); - } - // The MULO libcall is not part of libgcc, only compiler-rt. - setLibcallName(RTLIB::MULO_I128, nullptr); - } - - if (TT.isMIPS32()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - setLibcallName(RTLIB::MUL_I128, nullptr); - setLibcallName(RTLIB::MULO_I64, nullptr); - setLibcallName(RTLIB::MULO_I128, nullptr); - } - - if (TT.isPPC()) { - if (!TT.isPPC64()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - setLibcallName(RTLIB::MUL_I128, nullptr); - setLibcallName(RTLIB::MULO_I64, nullptr); - } - setLibcallName(RTLIB::MULO_I128, nullptr); - } - - if (TT.isRISCV32()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - setLibcallName(RTLIB::MUL_I128, nullptr); - setLibcallName(RTLIB::MULO_I64, nullptr); - } - - if (TT.isSPARC()) { - if (!TT.isSPARC64()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::MULO_I64, nullptr); - setLibcallName(RTLIB::MUL_I128, nullptr); - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - } - setLibcallName(RTLIB::MULO_I128, nullptr); - } - - if (TT.isSystemZ()) { - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - } - - if (TT.isX86()) { - if (TT.getArch() == Triple::ArchType::x86) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - setLibcallName(RTLIB::MUL_I128, nullptr); - // The MULO libcall is not part of libgcc, only compiler-rt. - setLibcallName(RTLIB::MULO_I64, nullptr); - } - - // The MULO libcall is not part of libgcc, only compiler-rt. - setLibcallName(RTLIB::MULO_I128, nullptr); - - if (TT.isOSMSVCRT()) { - // MSVCRT doesn't have powi; fall back to pow - setLibcallName(RTLIB::POWI_F32, nullptr); - setLibcallName(RTLIB::POWI_F64, nullptr); - } - } -} - /// GetFPLibCall - Helper to return the right libcall for the given floating /// point type, or UNKNOWN_LIBCALL if there is none. RTLIB::Libcall RTLIB::getFPLibCall(EVT VT, @@ -906,41 +574,9 @@ RTLIB::Libcall RTLIB::getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize) { } } -/// InitCmpLibcallCCs - Set default comparison libcall CC. -static void InitCmpLibcallCCs(ISD::CondCode *CCs) { - std::fill(CCs, CCs + RTLIB::UNKNOWN_LIBCALL, ISD::SETCC_INVALID); - CCs[RTLIB::OEQ_F32] = ISD::SETEQ; - CCs[RTLIB::OEQ_F64] = ISD::SETEQ; - CCs[RTLIB::OEQ_F128] = ISD::SETEQ; - CCs[RTLIB::OEQ_PPCF128] = ISD::SETEQ; - CCs[RTLIB::UNE_F32] = ISD::SETNE; - CCs[RTLIB::UNE_F64] = ISD::SETNE; - CCs[RTLIB::UNE_F128] = ISD::SETNE; - CCs[RTLIB::UNE_PPCF128] = ISD::SETNE; - CCs[RTLIB::OGE_F32] = ISD::SETGE; - CCs[RTLIB::OGE_F64] = ISD::SETGE; - CCs[RTLIB::OGE_F128] = ISD::SETGE; - CCs[RTLIB::OGE_PPCF128] = ISD::SETGE; - CCs[RTLIB::OLT_F32] = ISD::SETLT; - CCs[RTLIB::OLT_F64] = ISD::SETLT; - CCs[RTLIB::OLT_F128] = ISD::SETLT; - CCs[RTLIB::OLT_PPCF128] = ISD::SETLT; - CCs[RTLIB::OLE_F32] = ISD::SETLE; - CCs[RTLIB::OLE_F64] = ISD::SETLE; - CCs[RTLIB::OLE_F128] = ISD::SETLE; - CCs[RTLIB::OLE_PPCF128] = ISD::SETLE; - CCs[RTLIB::OGT_F32] = ISD::SETGT; - CCs[RTLIB::OGT_F64] = ISD::SETGT; - CCs[RTLIB::OGT_F128] = ISD::SETGT; - CCs[RTLIB::OGT_PPCF128] = ISD::SETGT; - CCs[RTLIB::UO_F32] = ISD::SETNE; - CCs[RTLIB::UO_F64] = ISD::SETNE; - CCs[RTLIB::UO_F128] = ISD::SETNE; - CCs[RTLIB::UO_PPCF128] = ISD::SETNE; -} - /// NOTE: The TargetMachine owns TLOF. -TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) { +TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) + : TM(tm), Libcalls(TM.getTargetTriple()) { initActions(); // Perform these initializations only once. @@ -972,11 +608,6 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) { MinCmpXchgSizeInBits = 0; SupportsUnalignedAtomics = false; - - std::fill(std::begin(LibcallRoutineNames), std::end(LibcallRoutineNames), nullptr); - - InitLibcalls(TM.getTargetTriple()); - InitCmpLibcallCCs(CmpLibcallCCs); } void TargetLoweringBase::initActions() { diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 4ffacbb9f0ffd7..eff511e0e552a8 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -22,6 +22,7 @@ #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/TargetLowering.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/DiagnosticPrinter.h" @@ -665,6 +666,7 @@ void LTO::addModuleToGlobalRes(ArrayRef Syms, if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() || (GlobalRes.Partition != GlobalResolution::Unknown && GlobalRes.Partition != Partition)) { + llvm::errs() << Sym.getName() << "\n"; GlobalRes.Partition = GlobalResolution::External; } else // First recorded reference, save the current partition. @@ -1357,14 +1359,13 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) { return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); } -static const char *libcallRoutineNames[] = { -#define HANDLE_LIBCALL(code, name) name, -#include "llvm/IR/RuntimeLibcalls.def" -#undef HANDLE_LIBCALL -}; +SmallVector LTO::getRuntimeLibcallSymbols(const Triple &TT) { + LibcallsInfo Libcalls(TT); -ArrayRef LTO::getRuntimeLibcallSymbols() { - return ArrayRef(libcallRoutineNames); + SmallVector LibcallSymbols; + copy_if(Libcalls.getLibcallNames(), std::back_inserter(LibcallSymbols), + [](const char *Name) { return Name; }); + return LibcallSymbols; } /// This class defines the interface to the ThinLTO backend. diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp index 7e29da4d5e948f..4783a90b00d673 100644 --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/CodeGen/TargetLowering.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Comdat.h" #include "llvm/IR/DataLayout.h" @@ -46,9 +47,6 @@ static cl::opt DisableBitcodeVersionUpgrade( cl::desc("Disable automatic bitcode upgrade for version mismatch")); static const char *PreservedSymbols[] = { -#define HANDLE_LIBCALL(code, name) name, -#include "llvm/IR/RuntimeLibcalls.def" -#undef HANDLE_LIBCALL // There are global variables, so put it here instead of in // RuntimeLibcalls.def. // TODO: Are there similar such variables? @@ -215,9 +213,16 @@ Expected Builder::getComdatIndex(const Comdat *C, const Module *M) { return P.first->second; } -static DenseSet buildPreservedSymbolsSet() { - return DenseSet(std::begin(PreservedSymbols), - std::end(PreservedSymbols)); +static DenseSet buildPreservedSymbolsSet(const Triple &TT) { + DenseSet PreservedSymbolSet(std::begin(PreservedSymbols), + std::end(PreservedSymbols)); + + LibcallsInfo Libcalls(TT); + for (const char *Name : Libcalls.getLibcallNames()) { + if (Name) + PreservedSymbolSet.insert(Name); + } + return PreservedSymbolSet; } Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, @@ -276,7 +281,8 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, setStr(Sym.IRName, GV->getName()); static const DenseSet PreservedSymbolsSet = - buildPreservedSymbolsSet(); + buildPreservedSymbolsSet( + llvm::Triple(GV->getParent()->getTargetTriple())); bool IsPreservedSymbol = PreservedSymbolsSet.contains(GV->getName()); if (Used.count(GV) || IsPreservedSymbol) diff --git a/llvm/tools/lto/lto.cpp b/llvm/tools/lto/lto.cpp index ece6dd0f108301..d68cff839604f6 100644 --- a/llvm/tools/lto/lto.cpp +++ b/llvm/tools/lto/lto.cpp @@ -691,7 +691,7 @@ extern const char *lto_input_get_dependent_library(lto_input_t input, } extern const char *const *lto_runtime_lib_symbols_list(size_t *size) { - auto symbols = lto::LTO::getRuntimeLibcallSymbols(); + auto symbols = lto::LTO::getRuntimeLibcallSymbols(Triple()); *size = symbols.size(); return symbols.data(); }