From cbd3a30cd235cdbd912861e7f437c151f8d0ff96 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 16 Jul 2024 06:22:09 -0500 Subject: [PATCH] [LLVM][LTO] Factor out RTLib calls and allow them to be dropped (#98512) 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 does not want the overhead of uncalled functions. (This adds like a second to the link time trivially) Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251770 --- lld/COFF/Driver.cpp | 7 +- lld/ELF/Driver.cpp | 6 +- lld/wasm/Driver.cpp | 6 +- .../llvm/CodeGen/GlobalISel/LegalizerHelper.h | 2 +- .../include/llvm/CodeGen/RuntimeLibcallUtil.h | 96 +++++ llvm/include/llvm/CodeGen/RuntimeLibcalls.h | 113 ----- llvm/include/llvm/CodeGen/TargetLowering.h | 37 +- llvm/include/llvm/IR/RuntimeLibcalls.h | 126 ++++++ llvm/include/llvm/LTO/LTO.h | 2 +- llvm/lib/CodeGen/AtomicExpandPass.cpp | 2 +- llvm/lib/CodeGen/DwarfEHPrepare.cpp | 2 +- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 2 +- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 2 +- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2 +- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 2 +- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 +- .../SelectionDAG/SelectionDAGBuilder.cpp | 2 +- .../SelectionDAG/StatepointLowering.cpp | 2 +- llvm/lib/CodeGen/TargetLoweringBase.cpp | 387 +----------------- llvm/lib/IR/CMakeLists.txt | 1 + llvm/lib/IR/RuntimeLibcalls.cpp | 379 +++++++++++++++++ llvm/lib/LTO/LTO.cpp | 14 +- llvm/lib/Object/IRSymtab.cpp | 20 +- llvm/lib/Target/AArch64/AArch64FastISel.cpp | 2 +- .../Target/AArch64/AArch64ISelLowering.cpp | 2 +- llvm/lib/Target/ARM/ARMFastISel.cpp | 2 +- llvm/lib/Target/ARM/ARMISelLowering.cpp | 2 +- llvm/lib/Target/ARM/ARMLegalizerInfo.h | 2 +- llvm/lib/Target/ARM/ARMSelectionDAGInfo.h | 2 +- .../Target/Hexagon/HexagonISelLowering.cpp | 4 +- llvm/lib/Target/Lanai/LanaiISelLowering.cpp | 2 +- .../LoongArch/LoongArchISelLowering.cpp | 2 +- llvm/lib/Target/Mips/MipsISelLowering.cpp | 2 +- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 2 +- .../WebAssemblyRuntimeLibcallSignatures.cpp | 2 +- .../WebAssemblyRuntimeLibcallSignatures.h | 2 +- llvm/tools/lto/lto.cpp | 2 +- 37 files changed, 676 insertions(+), 568 deletions(-) create mode 100644 llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h delete mode 100644 llvm/include/llvm/CodeGen/RuntimeLibcalls.h create mode 100644 llvm/include/llvm/IR/RuntimeLibcalls.h create mode 100644 llvm/lib/IR/RuntimeLibcalls.cpp 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 a94cb3a7cfef73..710f5a642a2272 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 b66b988005d58d..8c83d17db02f54 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -1320,9 +1320,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/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index ede8af13b9e757..6e2ab8ce403387 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -22,7 +22,7 @@ #include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/TargetOpcodes.h" namespace llvm { diff --git a/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h b/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h new file mode 100644 index 00000000000000..ce63dcc405fd5e --- /dev/null +++ b/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h @@ -0,0 +1,96 @@ +//===-- CodeGen/RuntimeLibcallUtil.h - Runtime Library Calls ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines some helper functions for runtime library calls. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_RUNTIMELIBCALLS_H +#define LLVM_CODEGEN_RUNTIMELIBCALLS_H + +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/RuntimeLibcalls.h" +#include "llvm/Support/AtomicOrdering.h" + +namespace llvm { +namespace RTLIB { + +/// GetFPLibCall - Helper to return the right libcall for the given floating +/// point type, or UNKNOWN_LIBCALL if there is none. +Libcall getFPLibCall(EVT VT, Libcall Call_F32, Libcall Call_F64, + Libcall Call_F80, Libcall Call_F128, Libcall Call_PPCF128); + +/// getFPEXT - Return the FPEXT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getFPEXT(EVT OpVT, EVT RetVT); + +/// getFPROUND - Return the FPROUND_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getFPROUND(EVT OpVT, EVT RetVT); + +/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getFPTOSINT(EVT OpVT, EVT RetVT); + +/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getFPTOUINT(EVT OpVT, EVT RetVT); + +/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getSINTTOFP(EVT OpVT, EVT RetVT); + +/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getUINTTOFP(EVT OpVT, EVT RetVT); + +/// getPOWI - Return the POWI_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getPOWI(EVT RetVT); + +/// getLDEXP - Return the LDEXP_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getLDEXP(EVT RetVT); + +/// getFREXP - Return the FREXP_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getFREXP(EVT RetVT); + +/// Return the SYNC_FETCH_AND_* value for the given opcode and type, or +/// UNKNOWN_LIBCALL if there is none. +Libcall getSYNC(unsigned Opc, MVT VT); + +/// Return the outline atomics value for the given atomic ordering, access +/// size and set of libcalls for a given atomic, or UNKNOWN_LIBCALL if there +/// is none. +Libcall getOutlineAtomicHelper(const Libcall (&LC)[5][4], AtomicOrdering Order, + uint64_t MemSize); + +/// Return the outline atomics value for the given opcode, atomic ordering +/// and type, or UNKNOWN_LIBCALL if there is none. +Libcall getOUTLINE_ATOMIC(unsigned Opc, AtomicOrdering Order, MVT VT); + +/// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return +/// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or +/// UNKNOW_LIBCALL if there is none. +Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); + +/// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return +/// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or +/// UNKNOW_LIBCALL if there is none. +Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); + +/// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return +/// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or +/// UNKNOW_LIBCALL if there is none. +Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); + +} // namespace RTLIB +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/llvm/include/llvm/CodeGen/RuntimeLibcalls.h deleted file mode 100644 index 3a407c4a4d9406..00000000000000 --- a/llvm/include/llvm/CodeGen/RuntimeLibcalls.h +++ /dev/null @@ -1,113 +0,0 @@ -//===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the enum representing the list of runtime library calls -// the backend may emit during code generation, and also some helper functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_RUNTIMELIBCALLS_H -#define LLVM_CODEGEN_RUNTIMELIBCALLS_H - -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/AtomicOrdering.h" - -namespace llvm { -namespace RTLIB { - /// RTLIB::Libcall enum - This enum defines all of the runtime library calls - /// the backend can emit. The various long double types cannot be merged, - /// because 80-bit library functions use "xf" and 128-bit use "tf". - /// - /// When adding PPCF128 functions here, note that their names generally need - /// to be overridden for Darwin with the xxx$LDBL128 form. See - /// PPCISelLowering.cpp. - /// - enum Libcall { -#define HANDLE_LIBCALL(code, name) code, - #include "llvm/IR/RuntimeLibcalls.def" -#undef HANDLE_LIBCALL - }; - - /// GetFPLibCall - Helper to return the right libcall for the given floating - /// point type, or UNKNOWN_LIBCALL if there is none. - Libcall getFPLibCall(EVT VT, - Libcall Call_F32, - Libcall Call_F64, - Libcall Call_F80, - Libcall Call_F128, - Libcall Call_PPCF128); - - /// getFPEXT - Return the FPEXT_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPEXT(EVT OpVT, EVT RetVT); - - /// getFPROUND - Return the FPROUND_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPROUND(EVT OpVT, EVT RetVT); - - /// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPTOSINT(EVT OpVT, EVT RetVT); - - /// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFPTOUINT(EVT OpVT, EVT RetVT); - - /// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getSINTTOFP(EVT OpVT, EVT RetVT); - - /// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getUINTTOFP(EVT OpVT, EVT RetVT); - - /// getPOWI - Return the POWI_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getPOWI(EVT RetVT); - - /// getLDEXP - Return the LDEXP_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getLDEXP(EVT RetVT); - - /// getFREXP - Return the FREXP_* value for the given types, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getFREXP(EVT RetVT); - - /// Return the SYNC_FETCH_AND_* value for the given opcode and type, or - /// UNKNOWN_LIBCALL if there is none. - Libcall getSYNC(unsigned Opc, MVT VT); - - /// Return the outline atomics value for the given atomic ordering, access - /// size and set of libcalls for a given atomic, or UNKNOWN_LIBCALL if there - /// is none. - Libcall getOutlineAtomicHelper(const Libcall (&LC)[5][4], - AtomicOrdering Order, uint64_t MemSize); - - /// Return the outline atomics value for the given opcode, atomic ordering - /// and type, or UNKNOWN_LIBCALL if there is none. - Libcall getOUTLINE_ATOMIC(unsigned Opc, AtomicOrdering Order, MVT VT); - - /// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return - /// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or - /// UNKNOW_LIBCALL if there is none. - Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); - - /// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return - /// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or - /// UNKNOW_LIBCALL if there is none. - Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); - - /// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return - /// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or - /// UNKNOW_LIBCALL if there is none. - Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); - -} -} - -#endif diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 55b60b01e58277..06e802314d97cc 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -31,7 +31,7 @@ #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/LowLevelTypeUtils.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetCallingConv.h" @@ -45,6 +45,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/RuntimeLibcalls.h" #include "llvm/IR/Type.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/AtomicOrdering.h" @@ -3410,44 +3411,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 +3623,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. + RTLIB::RuntimeLibcallsInfo 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/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h new file mode 100644 index 00000000000000..3057bff397b2fb --- /dev/null +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -0,0 +1,126 @@ +//===- RuntimeLibcalls.h - Interface for runtime libcalls -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a common interface to work with library calls into a +// runtime that may be emitted by a given backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_RUNTIME_LIBCALLS_H +#define LLVM_IR_RUNTIME_LIBCALLS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/Support/AtomicOrdering.h" +#include "llvm/TargetParser/Triple.h" + +namespace llvm { +namespace RTLIB { + +/// RTLIB::Libcall enum - This enum defines all of the runtime library calls +/// the backend can emit. The various long double types cannot be merged, +/// because 80-bit library functions use "xf" and 128-bit use "tf". +/// +/// When adding PPCF128 functions here, note that their names generally need +/// to be overridden for Darwin with the xxx$LDBL128 form. See +/// PPCISelLowering.cpp. +/// +enum Libcall { +#define HANDLE_LIBCALL(code, name) code, +#include "llvm/IR/RuntimeLibcalls.def" +#undef HANDLE_LIBCALL +}; + +/// A simple container for information about the supported runtime calls. +struct RuntimeLibcallsInfo { + explicit RuntimeLibcallsInfo(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(); + + /// Set default libcall names. If a target wants to opt-out of a libcall it + /// should be placed here. + void initLibcalls(const Triple &TT); +}; + +} // namespace RTLIB +} // namespace llvm + +#endif // LLVM_IR_RUNTIME_LIBCALLS_H 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/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index cea09bcb453863..ebcf76175a36ba 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -21,7 +21,7 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/CodeGen/AtomicExpand.h" #include "llvm/CodeGen/AtomicExpandUtils.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp index 09e7cfb12bdbad..324329ce989e71 100644 --- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -18,7 +18,7 @@ #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 7ba0ae6255c3bc..97be19825fcf35 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -38,7 +38,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/SwitchLoweringUtils.h" #include "llvm/CodeGen/TargetFrameLowering.h" diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 83df106a7fdc80..b58c96a8668836 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -25,7 +25,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 765f1e1f5f68c2..302ad128f4f532 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -37,7 +37,7 @@ #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SDPatternMatch.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 9f515739ee0481..7f5b46af01c62f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -25,7 +25,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetFrameLowering.h" diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 897bdc71818f8a..9bd0d1c51fbc27 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -36,7 +36,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SDPatternMatch.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGNodes.h" diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 403cd9c8b9fb5a..51cbdd9b3ad310 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -44,7 +44,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/StackMaps.h" diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index 671ec84fb94163..4268da8670d500 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -26,7 +26,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/StackMaps.h" diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index eccac0e218c58e..bf031c00a24491 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -28,7 +28,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetOpcodes.h" @@ -98,350 +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::ASIN_F128, "asinf128"); - setLibcallName(RTLIB::ACOS_F128, "acosf128"); - setLibcallName(RTLIB::ATAN_F128, "atanf128"); - setLibcallName(RTLIB::SINH_F128, "sinhf128"); - setLibcallName(RTLIB::COSH_F128, "coshf128"); - setLibcallName(RTLIB::TANH_F128, "tanhf128"); - 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: - if (TT.isOSVersionLT(7, 0)) { - setLibcallName(RTLIB::EXP10_F32, nullptr); - setLibcallName(RTLIB::EXP10_F64, nullptr); - break; - } - [[fallthrough]]; - case Triple::TvOS: - case Triple::WatchOS: - case Triple::XROS: - 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); - } - } - - // Disable most libcalls on NVPTX. - if (TT.isNVPTX()) { - 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, @@ -918,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. @@ -984,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/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index 6b3224e22ffb6f..91e0e0cc65f36b 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -73,6 +73,7 @@ add_llvm_component_library(LLVMCore VectorBuilder.cpp Verifier.cpp VFABIDemangler.cpp + RuntimeLibcalls.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/IR diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp new file mode 100644 index 00000000000000..de3db557d8b50b --- /dev/null +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -0,0 +1,379 @@ +//===- RuntimeLibcalls.cpp - Interface for runtime libcalls -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/RuntimeLibcalls.h" + +using namespace llvm; +using namespace RTLIB; + +/// 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) { + 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::ASIN_F128, "asinf128"); + setLibcallName(RTLIB::ACOS_F128, "acosf128"); + setLibcallName(RTLIB::ATAN_F128, "atanf128"); + setLibcallName(RTLIB::SINH_F128, "sinhf128"); + setLibcallName(RTLIB::COSH_F128, "coshf128"); + setLibcallName(RTLIB::TANH_F128, "tanhf128"); + 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: + if (TT.isOSVersionLT(7, 0)) { + setLibcallName(RTLIB::EXP10_F32, nullptr); + setLibcallName(RTLIB::EXP10_F64, nullptr); + break; + } + [[fallthrough]]; + case Triple::TvOS: + case Triple::WatchOS: + case Triple::XROS: + 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); + } + } + + // Disable most libcalls on NVPTX. + if (TT.isNVPTX()) { + 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); + } + } +} + +void RuntimeLibcallsInfo::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; +} diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 4ffacbb9f0ffd7..d303f228aa72c3 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/RuntimeLibcalls.h" #include "llvm/LTO/LTOBackend.h" #include "llvm/LTO/SummaryBasedOptimizations.h" #include "llvm/Linker/IRMover.h" @@ -1357,14 +1358,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) { + RTLIB::RuntimeLibcallsInfo 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..2a2b235461a550 100644 --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/IR/RuntimeLibcalls.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Object/SymbolicFile.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)); + + RTLIB::RuntimeLibcallsInfo 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/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index e3c5a143b28892..527496f1a63749 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -35,7 +35,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGenTypes/MachineValueType.h" #include "llvm/IR/Argument.h" diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 01358db5499c10..df9b0ae1a632f3 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -48,7 +48,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetCallingConv.h" diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp index 61d2928fe6d412..1cc21da51d1e67 100644 --- a/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -40,7 +40,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetOpcodes.h" diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 2683b5741d4597..75d16a42d0205a 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -53,7 +53,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGNodes.h" diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.h b/llvm/lib/Target/ARM/ARMLegalizerInfo.h index d6ce4eb1055b48..9e10638233e6d1 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.h +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.h @@ -16,7 +16,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/IR/Instructions.h" namespace llvm { diff --git a/llvm/lib/Target/ARM/ARMSelectionDAGInfo.h b/llvm/lib/Target/ARM/ARMSelectionDAGInfo.h index ffa8b50493510d..275b1c0f8dc017 100644 --- a/llvm/lib/Target/ARM/ARMSelectionDAGInfo.h +++ b/llvm/lib/Target/ARM/ARMSelectionDAGInfo.h @@ -14,7 +14,7 @@ #define LLVM_LIB_TARGET_ARM_ARMSELECTIONDAGINFO_H #include "MCTargetDesc/ARMAddressingModes.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" namespace llvm { diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 09fe5264e09553..79cffc0da7a4f2 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -27,7 +27,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/CodeGen/ValueTypes.h" @@ -39,12 +39,12 @@ #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsHexagon.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp index 8aef45e401d43b..06fd7ac807d8ab 100644 --- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp +++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp @@ -27,7 +27,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetCallingConv.h" diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 5c4fddd5116eaa..79da36c03e3046 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -22,7 +22,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicsLoongArch.h" diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 7d8adb9a003114..ef70ef27726814 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -40,7 +40,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetFrameLowering.h" diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 6aabf5cd8c5945..411114599543c9 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -48,7 +48,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetInstrInfo.h" diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp index 20e50c8c9e1ae0..e7810e18d44d42 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp @@ -21,7 +21,7 @@ #include "WebAssemblyRuntimeLibcallSignatures.h" #include "WebAssemblySubtarget.h" #include "WebAssemblyUtilities.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" using namespace llvm; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h index ff6515d5bf4e67..966b84aa4951be 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h @@ -16,7 +16,7 @@ #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/RuntimeLibcallUtil.h" namespace llvm { 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(); }