Skip to content

Commit e74cf8b

Browse files
committed
[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.
1 parent 0b58f34 commit e74cf8b

File tree

13 files changed

+621
-513
lines changed

13 files changed

+621
-513
lines changed

lld/COFF/Driver.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,9 +2428,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
24282428
// file's symbol table. If any of those library functions are defined in a
24292429
// bitcode file in an archive member, we need to arrange to use LTO to
24302430
// compile those archive members by adding them to the link beforehand.
2431-
if (!ctx.bitcodeFileInstances.empty())
2432-
for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
2431+
if (!ctx.bitcodeFileInstances.empty()) {
2432+
llvm::Triple TT(
2433+
ctx.bitcodeFileInstances.front()->obj->getTargetTriple());
2434+
for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
24332435
ctx.symtab.addLibcall(s);
2436+
}
24342437

24352438
// Windows specific -- if __load_config_used can be resolved, resolve it.
24362439
if (ctx.symtab.findUnderscore("_load_config_used"))

lld/ELF/Driver.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,9 +2883,11 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
28832883
// to, i.e. if the symbol's definition is in bitcode. Any other required
28842884
// libcall symbols will be added to the link after LTO when we add the LTO
28852885
// object file to the link.
2886-
if (!ctx.bitcodeFiles.empty())
2887-
for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
2886+
if (!ctx.bitcodeFiles.empty()) {
2887+
llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple());
2888+
for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
28882889
handleLibcall(s);
2890+
}
28892891

28902892
// Archive members defining __wrap symbols may be extracted.
28912893
std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);

lld/wasm/Driver.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,9 +1319,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
13191319
// We only need to add libcall symbols to the link before LTO if the symbol's
13201320
// definition is in bitcode. Any other required libcall symbols will be added
13211321
// to the link after LTO when we add the LTO object file to the link.
1322-
if (!ctx.bitcodeFiles.empty())
1323-
for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
1322+
if (!ctx.bitcodeFiles.empty()) {
1323+
llvm::Triple TT(ctx.bitcodeFiles.front()->obj->getTargetTriple());
1324+
for (auto *s : lto::LTO::getRuntimeLibcallSymbols(TT))
13241325
handleLibcall(s);
1326+
}
13251327
if (errorCount())
13261328
return;
13271329

llvm/include/llvm/CodeGen/RuntimeLibcalls.h

Lines changed: 74 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -15,99 +15,83 @@
1515
#define LLVM_CODEGEN_RUNTIMELIBCALLS_H
1616

1717
#include "llvm/CodeGen/ValueTypes.h"
18+
#include "llvm/IR/RuntimeLibcalls.h"
1819
#include "llvm/Support/AtomicOrdering.h"
1920

2021
namespace llvm {
2122
namespace RTLIB {
22-
/// RTLIB::Libcall enum - This enum defines all of the runtime library calls
23-
/// the backend can emit. The various long double types cannot be merged,
24-
/// because 80-bit library functions use "xf" and 128-bit use "tf".
25-
///
26-
/// When adding PPCF128 functions here, note that their names generally need
27-
/// to be overridden for Darwin with the xxx$LDBL128 form. See
28-
/// PPCISelLowering.cpp.
29-
///
30-
enum Libcall {
31-
#define HANDLE_LIBCALL(code, name) code,
32-
#include "llvm/IR/RuntimeLibcalls.def"
33-
#undef HANDLE_LIBCALL
34-
};
35-
36-
/// GetFPLibCall - Helper to return the right libcall for the given floating
37-
/// point type, or UNKNOWN_LIBCALL if there is none.
38-
Libcall getFPLibCall(EVT VT,
39-
Libcall Call_F32,
40-
Libcall Call_F64,
41-
Libcall Call_F80,
42-
Libcall Call_F128,
43-
Libcall Call_PPCF128);
44-
45-
/// getFPEXT - Return the FPEXT_*_* value for the given types, or
46-
/// UNKNOWN_LIBCALL if there is none.
47-
Libcall getFPEXT(EVT OpVT, EVT RetVT);
48-
49-
/// getFPROUND - Return the FPROUND_*_* value for the given types, or
50-
/// UNKNOWN_LIBCALL if there is none.
51-
Libcall getFPROUND(EVT OpVT, EVT RetVT);
52-
53-
/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or
54-
/// UNKNOWN_LIBCALL if there is none.
55-
Libcall getFPTOSINT(EVT OpVT, EVT RetVT);
56-
57-
/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or
58-
/// UNKNOWN_LIBCALL if there is none.
59-
Libcall getFPTOUINT(EVT OpVT, EVT RetVT);
60-
61-
/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or
62-
/// UNKNOWN_LIBCALL if there is none.
63-
Libcall getSINTTOFP(EVT OpVT, EVT RetVT);
64-
65-
/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or
66-
/// UNKNOWN_LIBCALL if there is none.
67-
Libcall getUINTTOFP(EVT OpVT, EVT RetVT);
68-
69-
/// getPOWI - Return the POWI_* value for the given types, or
70-
/// UNKNOWN_LIBCALL if there is none.
71-
Libcall getPOWI(EVT RetVT);
72-
73-
/// getLDEXP - Return the LDEXP_* value for the given types, or
74-
/// UNKNOWN_LIBCALL if there is none.
75-
Libcall getLDEXP(EVT RetVT);
76-
77-
/// getFREXP - Return the FREXP_* value for the given types, or
78-
/// UNKNOWN_LIBCALL if there is none.
79-
Libcall getFREXP(EVT RetVT);
80-
81-
/// Return the SYNC_FETCH_AND_* value for the given opcode and type, or
82-
/// UNKNOWN_LIBCALL if there is none.
83-
Libcall getSYNC(unsigned Opc, MVT VT);
84-
85-
/// Return the outline atomics value for the given atomic ordering, access
86-
/// size and set of libcalls for a given atomic, or UNKNOWN_LIBCALL if there
87-
/// is none.
88-
Libcall getOutlineAtomicHelper(const Libcall (&LC)[5][4],
89-
AtomicOrdering Order, uint64_t MemSize);
90-
91-
/// Return the outline atomics value for the given opcode, atomic ordering
92-
/// and type, or UNKNOWN_LIBCALL if there is none.
93-
Libcall getOUTLINE_ATOMIC(unsigned Opc, AtomicOrdering Order, MVT VT);
94-
95-
/// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return
96-
/// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
97-
/// UNKNOW_LIBCALL if there is none.
98-
Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
99-
100-
/// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return
101-
/// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
102-
/// UNKNOW_LIBCALL if there is none.
103-
Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
104-
105-
/// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return
106-
/// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
107-
/// UNKNOW_LIBCALL if there is none.
108-
Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
109-
110-
}
111-
}
23+
24+
/// GetFPLibCall - Helper to return the right libcall for the given floating
25+
/// point type, or UNKNOWN_LIBCALL if there is none.
26+
Libcall getFPLibCall(EVT VT, Libcall Call_F32, Libcall Call_F64,
27+
Libcall Call_F80, Libcall Call_F128, Libcall Call_PPCF128);
28+
29+
/// getFPEXT - Return the FPEXT_*_* value for the given types, or
30+
/// UNKNOWN_LIBCALL if there is none.
31+
Libcall getFPEXT(EVT OpVT, EVT RetVT);
32+
33+
/// getFPROUND - Return the FPROUND_*_* value for the given types, or
34+
/// UNKNOWN_LIBCALL if there is none.
35+
Libcall getFPROUND(EVT OpVT, EVT RetVT);
36+
37+
/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or
38+
/// UNKNOWN_LIBCALL if there is none.
39+
Libcall getFPTOSINT(EVT OpVT, EVT RetVT);
40+
41+
/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or
42+
/// UNKNOWN_LIBCALL if there is none.
43+
Libcall getFPTOUINT(EVT OpVT, EVT RetVT);
44+
45+
/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or
46+
/// UNKNOWN_LIBCALL if there is none.
47+
Libcall getSINTTOFP(EVT OpVT, EVT RetVT);
48+
49+
/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or
50+
/// UNKNOWN_LIBCALL if there is none.
51+
Libcall getUINTTOFP(EVT OpVT, EVT RetVT);
52+
53+
/// getPOWI - Return the POWI_* value for the given types, or
54+
/// UNKNOWN_LIBCALL if there is none.
55+
Libcall getPOWI(EVT RetVT);
56+
57+
/// getLDEXP - Return the LDEXP_* value for the given types, or
58+
/// UNKNOWN_LIBCALL if there is none.
59+
Libcall getLDEXP(EVT RetVT);
60+
61+
/// getFREXP - Return the FREXP_* value for the given types, or
62+
/// UNKNOWN_LIBCALL if there is none.
63+
Libcall getFREXP(EVT RetVT);
64+
65+
/// Return the SYNC_FETCH_AND_* value for the given opcode and type, or
66+
/// UNKNOWN_LIBCALL if there is none.
67+
Libcall getSYNC(unsigned Opc, MVT VT);
68+
69+
/// Return the outline atomics value for the given atomic ordering, access
70+
/// size and set of libcalls for a given atomic, or UNKNOWN_LIBCALL if there
71+
/// is none.
72+
Libcall getOutlineAtomicHelper(const Libcall (&LC)[5][4], AtomicOrdering Order,
73+
uint64_t MemSize);
74+
75+
/// Return the outline atomics value for the given opcode, atomic ordering
76+
/// and type, or UNKNOWN_LIBCALL if there is none.
77+
Libcall getOUTLINE_ATOMIC(unsigned Opc, AtomicOrdering Order, MVT VT);
78+
79+
/// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return
80+
/// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
81+
/// UNKNOW_LIBCALL if there is none.
82+
Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
83+
84+
/// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return
85+
/// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
86+
/// UNKNOW_LIBCALL if there is none.
87+
Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
88+
89+
/// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return
90+
/// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
91+
/// UNKNOW_LIBCALL if there is none.
92+
Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
93+
94+
} // namespace RTLIB
95+
} // namespace llvm
11296

11397
#endif

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3410,44 +3410,40 @@ class TargetLoweringBase {
34103410
return nullptr;
34113411
}
34123412

3413-
//===--------------------------------------------------------------------===//
3414-
// Runtime Library hooks
3415-
//
3416-
34173413
/// Rename the default libcall routine name for the specified libcall.
34183414
void setLibcallName(RTLIB::Libcall Call, const char *Name) {
3419-
LibcallRoutineNames[Call] = Name;
3415+
Libcalls.setLibcallName(Call, Name);
34203416
}
3417+
34213418
void setLibcallName(ArrayRef<RTLIB::Libcall> Calls, const char *Name) {
3422-
for (auto Call : Calls)
3423-
setLibcallName(Call, Name);
3419+
Libcalls.setLibcallName(Calls, Name);
34243420
}
34253421

34263422
/// Get the libcall routine name for the specified libcall.
34273423
const char *getLibcallName(RTLIB::Libcall Call) const {
3428-
return LibcallRoutineNames[Call];
3424+
return Libcalls.getLibcallName(Call);
34293425
}
34303426

34313427
/// Override the default CondCode to be used to test the result of the
34323428
/// comparison libcall against zero.
34333429
void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) {
3434-
CmpLibcallCCs[Call] = CC;
3430+
Libcalls.setCmpLibcallCC(Call, CC);
34353431
}
34363432

34373433
/// Get the CondCode that's to be used to test the result of the comparison
34383434
/// libcall against zero.
34393435
ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const {
3440-
return CmpLibcallCCs[Call];
3436+
return Libcalls.getCmpLibcallCC(Call);
34413437
}
34423438

34433439
/// Set the CallingConv that should be used for the specified libcall.
34443440
void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) {
3445-
LibcallCallingConvs[Call] = CC;
3441+
Libcalls.setLibcallCallingConv(Call, CC);
34463442
}
34473443

34483444
/// Get the CallingConv that should be used for the specified libcall.
34493445
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
3450-
return LibcallCallingConvs[Call];
3446+
return Libcalls.getLibcallCallingConv(Call);
34513447
}
34523448

34533449
/// Execute target specific actions to finalize target lowering.
@@ -3626,18 +3622,8 @@ class TargetLoweringBase {
36263622
std::map<std::pair<unsigned, MVT::SimpleValueType>, MVT::SimpleValueType>
36273623
PromoteToType;
36283624

3629-
/// Stores the name each libcall.
3630-
const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1];
3631-
3632-
/// The ISD::CondCode that should be used to test the result of each of the
3633-
/// comparison libcall against zero.
3634-
ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL];
3635-
3636-
/// Stores the CallingConv that should be used for each libcall.
3637-
CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL];
3638-
3639-
/// Set default libcall names and calling conventions.
3640-
void InitLibcalls(const Triple &TT);
3625+
/// The list of libcalls that the target will use.
3626+
RTLIB::RuntimeLibcallsInfo Libcalls;
36413627

36423628
/// The bits of IndexedModeActions used to store the legalisation actions
36433629
/// We store the data as | ML | MS | L | S | each taking 4 bits.

0 commit comments

Comments
 (0)