Skip to content

Commit

Permalink
[LLVM][LTO] Factor out RTLib calls and allow them to be dropped (llvm…
Browse files Browse the repository at this point in the history
…#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/D59822415
  • Loading branch information
jhuber6 authored and sayhaan committed Jul 16, 2024
1 parent 87eab27 commit 4a71ab2
Show file tree
Hide file tree
Showing 37 changed files with 676 additions and 568 deletions.
7 changes: 5 additions & 2 deletions lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2428,9 +2428,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> 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"))
Expand Down
6 changes: 4 additions & 2 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2883,9 +2883,11 @@ template <class ELFT> 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<WrappedSymbol> wrapped = addWrappedSymbols(args);
Expand Down
6 changes: 4 additions & 2 deletions lld/wasm/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1320,9 +1320,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> 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;

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
96 changes: 96 additions & 0 deletions llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
Original file line number Diff line number Diff line change
@@ -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
113 changes: 0 additions & 113 deletions llvm/include/llvm/CodeGen/RuntimeLibcalls.h

This file was deleted.

37 changes: 12 additions & 25 deletions llvm/include/llvm/CodeGen/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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<RTLIB::Libcall> 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.
Expand Down Expand Up @@ -3626,18 +3623,8 @@ class TargetLoweringBase {
std::map<std::pair<unsigned, MVT::SimpleValueType>, 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.
Expand Down
Loading

0 comments on commit 4a71ab2

Please sign in to comment.