Skip to content

Commit 056d2c1

Browse files
authored
RuntimeLibcalls: Split lowering decisions into LibcallLoweringInfo (llvm#164987)
Introduce a new class for the TargetLowering usage. This tracks the subtarget specific lowering decisions for which libcall to use. RuntimeLibcallsInfo is a module level property, which may have multiple implementations of a particular libcall available. This attempts to be a minimum boilerplate patch to introduce the new concept. In the future we should have a tablegen way of selecting which implementations should be used for a subtarget. Currently we do have some conflicting implementations added, it just happens to work out that the default cases to prefer is alphabetically first (plus some of these still are using manual overrides in TargetLowering constructors).
1 parent 9b1719e commit 056d2c1

File tree

16 files changed

+238
-176
lines changed

16 files changed

+238
-176
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===- LibcallLoweringInfo.h ------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/IR/RuntimeLibcalls.h"
10+
11+
namespace llvm {
12+
13+
class LibcallLoweringInfo {
14+
private:
15+
LLVM_ABI const RTLIB::RuntimeLibcallsInfo &RTLCI;
16+
/// Stores the implementation choice for each each libcall.
17+
LLVM_ABI RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
18+
RTLIB::Unsupported};
19+
20+
public:
21+
LLVM_ABI LibcallLoweringInfo(const RTLIB::RuntimeLibcallsInfo &RTLCI);
22+
23+
/// Get the libcall routine name for the specified libcall.
24+
// FIXME: This should be removed. Only LibcallImpl should have a name.
25+
LLVM_ABI const char *getLibcallName(RTLIB::Libcall Call) const {
26+
// FIXME: Return StringRef
27+
return RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LibcallImpls[Call])
28+
.data();
29+
}
30+
31+
/// Return the lowering's selection of implementation call for \p Call
32+
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const {
33+
return LibcallImpls[Call];
34+
}
35+
36+
/// Rename the default libcall routine name for the specified libcall.
37+
LLVM_ABI void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
38+
LibcallImpls[Call] = Impl;
39+
}
40+
41+
// FIXME: Remove this wrapper in favor of directly using
42+
// getLibcallImplCallingConv
43+
LLVM_ABI CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
44+
return RTLCI.LibcallImplCallingConvs[LibcallImpls[Call]];
45+
}
46+
47+
/// Get the CallingConv that should be used for the specified libcall.
48+
LLVM_ABI CallingConv::ID
49+
getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
50+
return RTLCI.LibcallImplCallingConvs[Call];
51+
}
52+
53+
/// Return a function impl compatible with RTLIB::MEMCPY, or
54+
/// RTLIB::Unsupported if fully unsupported.
55+
RTLIB::LibcallImpl getMemcpyImpl() const {
56+
RTLIB::LibcallImpl Memcpy = getLibcallImpl(RTLIB::MEMCPY);
57+
if (Memcpy == RTLIB::Unsupported) {
58+
// Fallback to memmove if memcpy isn't available.
59+
return getLibcallImpl(RTLIB::MEMMOVE);
60+
}
61+
62+
return Memcpy;
63+
}
64+
};
65+
66+
} // end namespace llvm

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/ADT/StringRef.h"
3030
#include "llvm/CodeGen/DAGCombine.h"
3131
#include "llvm/CodeGen/ISDOpcodes.h"
32+
#include "llvm/CodeGen/LibcallLoweringInfo.h"
3233
#include "llvm/CodeGen/LowLevelTypeUtils.h"
3334
#include "llvm/CodeGen/MachineRegisterInfo.h"
3435
#include "llvm/CodeGen/RuntimeLibcallUtil.h"
@@ -3597,7 +3598,7 @@ class LLVM_ABI TargetLoweringBase {
35973598
}
35983599

35993600
const RTLIB::RuntimeLibcallsInfo &getRuntimeLibcallsInfo() const {
3600-
return Libcalls;
3601+
return RuntimeLibcallInfo;
36013602
}
36023603

36033604
void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
@@ -3610,9 +3611,9 @@ class LLVM_ABI TargetLoweringBase {
36103611
}
36113612

36123613
/// Get the libcall routine name for the specified libcall.
3614+
// FIXME: This should be removed. Only LibcallImpl should have a name.
36133615
const char *getLibcallName(RTLIB::Libcall Call) const {
3614-
// FIXME: Return StringRef
3615-
return Libcalls.getLibcallName(Call).data();
3616+
return Libcalls.getLibcallName(Call);
36163617
}
36173618

36183619
/// Get the libcall routine name for the specified libcall implementation
@@ -3625,19 +3626,14 @@ class LLVM_ABI TargetLoweringBase {
36253626
/// Check if this is valid libcall for the current module, otherwise
36263627
/// RTLIB::Unsupported.
36273628
RTLIB::LibcallImpl getSupportedLibcallImpl(StringRef FuncName) const {
3628-
return Libcalls.getSupportedLibcallImpl(FuncName);
3629+
return RuntimeLibcallInfo.getSupportedLibcallImpl(FuncName);
36293630
}
36303631

36313632
/// Get the comparison predicate that's to be used to test the result of the
36323633
/// comparison libcall against zero. This should only be used with
36333634
/// floating-point compare libcalls.
36343635
ISD::CondCode getSoftFloatCmpLibcallPredicate(RTLIB::LibcallImpl Call) const;
36353636

3636-
/// Set the CallingConv that should be used for the specified libcall.
3637-
void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) {
3638-
Libcalls.setLibcallImplCallingConv(Call, CC);
3639-
}
3640-
36413637
/// Get the CallingConv that should be used for the specified libcall
36423638
/// implementation.
36433639
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
@@ -3834,8 +3830,11 @@ class LLVM_ABI TargetLoweringBase {
38343830
std::map<std::pair<unsigned, MVT::SimpleValueType>, MVT::SimpleValueType>
38353831
PromoteToType;
38363832

3833+
/// FIXME: This should not live here; it should come from an analysis.
3834+
const RTLIB::RuntimeLibcallsInfo RuntimeLibcallInfo;
3835+
38373836
/// The list of libcalls that the target will use.
3838-
RTLIB::RuntimeLibcallsInfo Libcalls;
3837+
LibcallLoweringInfo Libcalls;
38393838

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

llvm/include/llvm/IR/RuntimeLibcalls.h

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ template <> struct enum_iteration_traits<RTLIB::LibcallImpl> {
4242
static constexpr bool is_iterable = true;
4343
};
4444

45+
class LibcallLoweringInfo;
46+
4547
namespace RTLIB {
4648

4749
// Return an iterator over all Libcall values.
@@ -70,6 +72,8 @@ struct RuntimeLibcallsInfo {
7072
LibcallImplBitset AvailableLibcallImpls;
7173

7274
public:
75+
friend class llvm::LibcallLoweringInfo;
76+
7377
explicit RuntimeLibcallsInfo(
7478
const Triple &TT,
7579
ExceptionHandling ExceptionModel = ExceptionHandling::None,
@@ -85,17 +89,6 @@ struct RuntimeLibcallsInfo {
8589
initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion, ABIName);
8690
}
8791

88-
/// Rename the default libcall routine name for the specified libcall.
89-
void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
90-
LibcallImpls[Call] = Impl;
91-
}
92-
93-
/// Get the libcall routine name for the specified libcall.
94-
// FIXME: This should be removed. Only LibcallImpl should have a name.
95-
StringRef getLibcallName(RTLIB::Libcall Call) const {
96-
return getLibcallImplName(LibcallImpls[Call]);
97-
}
98-
9992
/// Get the libcall routine name for the specified libcall implementation.
10093
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl) {
10194
if (CallImpl == RTLIB::Unsupported)
@@ -105,42 +98,24 @@ struct RuntimeLibcallsInfo {
10598
RuntimeLibcallNameSizeTable[CallImpl]);
10699
}
107100

108-
/// Return the lowering's selection of implementation call for \p Call
109-
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const {
110-
return LibcallImpls[Call];
111-
}
112-
113101
/// Set the CallingConv that should be used for the specified libcall
114102
/// implementation
115103
void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC) {
116104
LibcallImplCallingConvs[Call] = CC;
117105
}
118106

119-
// FIXME: Remove this wrapper in favor of directly using
120-
// getLibcallImplCallingConv
121-
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
122-
return LibcallImplCallingConvs[LibcallImpls[Call]];
123-
}
124-
125107
/// Get the CallingConv that should be used for the specified libcall.
126108
CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
127109
return LibcallImplCallingConvs[Call];
128110
}
129111

130-
ArrayRef<RTLIB::LibcallImpl> getLibcallImpls() const {
131-
// Trim UNKNOWN_LIBCALL from the back
132-
return ArrayRef(LibcallImpls).drop_back();
112+
/// Return the libcall provided by \p Impl
113+
static RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl) {
114+
return ImplToLibcall[Impl];
133115
}
134116

135-
/// Return a function name compatible with RTLIB::MEMCPY, or nullptr if fully
136-
/// unsupported.
137-
RTLIB::LibcallImpl getMemcpyImpl() const {
138-
RTLIB::LibcallImpl Memcpy = getLibcallImpl(RTLIB::MEMCPY);
139-
if (Memcpy != RTLIB::Unsupported)
140-
return Memcpy;
141-
142-
// Fallback to memmove if memcpy isn't available.
143-
return getLibcallImpl(RTLIB::MEMMOVE);
117+
unsigned getNumAvailableLibcallImpls() const {
118+
return AvailableLibcallImpls.count();
144119
}
145120

146121
bool isAvailable(RTLIB::LibcallImpl Impl) const {
@@ -151,11 +126,6 @@ struct RuntimeLibcallsInfo {
151126
AvailableLibcallImpls.set(Impl);
152127
}
153128

154-
/// Return the libcall provided by \p Impl
155-
static RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl) {
156-
return ImplToLibcall[Impl];
157-
}
158-
159129
/// Check if a function name is a recognized runtime call of any kind. This
160130
/// does not consider if this call is available for any current compilation,
161131
/// just that it is a known call somewhere. This returns the set of all
@@ -176,11 +146,8 @@ struct RuntimeLibcallsInfo {
176146
LLVM_ABI RTLIB::LibcallImpl
177147
getSupportedLibcallImpl(StringRef FuncName) const {
178148
for (RTLIB::LibcallImpl Impl : lookupLibcallImplName(FuncName)) {
179-
// FIXME: This should not depend on looking up ImplToLibcall, only the
180-
// list of libcalls for the module.
181-
RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]];
182-
if (Recognized != RTLIB::Unsupported)
183-
return Recognized;
149+
if (isAvailable(Impl))
150+
return Impl;
184151
}
185152

186153
return RTLIB::Unsupported;
@@ -197,10 +164,6 @@ struct RuntimeLibcallsInfo {
197164
LLVM_ABI static iota_range<RTLIB::LibcallImpl>
198165
lookupLibcallImplNameImpl(StringRef Name);
199166

200-
/// Stores the implementation choice for each each libcall.
201-
RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
202-
RTLIB::Unsupported};
203-
204167
static_assert(static_cast<int>(CallingConv::C) == 0,
205168
"default calling conv should be encoded as 0");
206169

@@ -274,6 +237,7 @@ struct RuntimeLibcallsInfo {
274237
};
275238

276239
} // namespace RTLIB
240+
277241
} // namespace llvm
278242

279243
#endif // LLVM_IR_RUNTIME_LIBCALLS_H

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ add_llvm_component_library(LLVMCodeGen
8888
LatencyPriorityQueue.cpp
8989
LazyMachineBlockFrequencyInfo.cpp
9090
LexicalScopes.cpp
91+
LibcallLoweringInfo.cpp
9192
LiveDebugVariables.cpp
9293
LiveIntervals.cpp
9394
LiveInterval.cpp
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===- LibcallLoweringInfo.cpp - Interface for runtime libcalls -----------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/CodeGen/LibcallLoweringInfo.h"
10+
11+
using namespace llvm;
12+
13+
LibcallLoweringInfo::LibcallLoweringInfo(
14+
const RTLIB::RuntimeLibcallsInfo &RTLCI)
15+
: RTLCI(RTLCI) {
16+
// TODO: This should be generated with lowering predicates, and assert the
17+
// call is available.
18+
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
19+
if (RTLCI.isAvailable(Impl)) {
20+
RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
21+
// FIXME: Hack, assume the first available libcall wins.
22+
if (LibcallImpls[LC] == RTLIB::Unsupported)
23+
LibcallImpls[LC] = Impl;
24+
}
25+
}
26+
}

llvm/lib/CodeGen/TargetLoweringBase.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -697,9 +697,11 @@ ISD::CondCode TargetLoweringBase::getSoftFloatCmpLibcallPredicate(
697697

698698
/// NOTE: The TargetMachine owns TLOF.
699699
TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm)
700-
: TM(tm), Libcalls(TM.getTargetTriple(), TM.Options.ExceptionModel,
701-
TM.Options.FloatABIType, TM.Options.EABIVersion,
702-
TM.Options.MCOptions.getABIName()) {
700+
: TM(tm),
701+
RuntimeLibcallInfo(TM.getTargetTriple(), TM.Options.ExceptionModel,
702+
TM.Options.FloatABIType, TM.Options.EABIVersion,
703+
TM.Options.MCOptions.getABIName()),
704+
Libcalls(RuntimeLibcallInfo) {
703705
initActions();
704706

705707
// Perform these initializations only once.

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using namespace llvm;
2020
using namespace RTLIB;
2121

22+
#define GET_RUNTIME_LIBCALLS_INFO
2223
#define GET_INIT_RUNTIME_LIBCALL_NAMES
2324
#define GET_SET_TARGET_RUNTIME_LIBCALL_SETS
2425
#define DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME

llvm/lib/LTO/LTO.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,11 +1396,10 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
13961396
SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) {
13971397
RTLIB::RuntimeLibcallsInfo Libcalls(TT);
13981398
SmallVector<const char *> LibcallSymbols;
1399-
ArrayRef<RTLIB::LibcallImpl> LibcallImpls = Libcalls.getLibcallImpls();
1400-
LibcallSymbols.reserve(LibcallImpls.size());
1399+
LibcallSymbols.reserve(Libcalls.getNumAvailableLibcallImpls());
14011400

1402-
for (RTLIB::LibcallImpl Impl : LibcallImpls) {
1403-
if (Impl != RTLIB::Unsupported)
1401+
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
1402+
if (Libcalls.isAvailable(Impl))
14041403
LibcallSymbols.push_back(Libcalls.getLibcallImplName(Impl).data());
14051404
}
14061405

llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -532,13 +532,19 @@ struct StaticLibcallNameMap {
532532
// FIXME: This is broken if there are ever different triples compiled with
533533
// different libcalls.
534534
RTLIB::RuntimeLibcallsInfo RTCI(TT);
535-
for (RTLIB::Libcall LC : RTLIB::libcalls()) {
536-
StringRef NameLibcall = RTCI.getLibcallName(LC);
537-
if (!NameLibcall.empty() &&
538-
getRuntimeLibcallSignatures().Table[LC] != unsupported) {
539-
assert(!Map.contains(NameLibcall) &&
540-
"duplicate libcall names in name map");
541-
Map[NameLibcall] = LC;
535+
536+
ArrayRef<RuntimeLibcallSignature> Table =
537+
getRuntimeLibcallSignatures().Table;
538+
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
539+
if (!RTCI.isAvailable(Impl))
540+
continue;
541+
RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
542+
if (Table[LC] != unsupported) {
543+
StringRef NameLibcall =
544+
RTLIB::RuntimeLibcallsInfo::getLibcallImplName(Impl);
545+
// FIXME: Map should be to LibcallImpl
546+
if (!Map.insert({NameLibcall, LC}).second)
547+
llvm_unreachable("duplicate libcall names in name map");
542548
}
543549
}
544550
}

llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ PreservedAnalyses DeclareRuntimeLibcallsPass::run(Module &M,
5454
const DataLayout &DL = M.getDataLayout();
5555
const Triple &TT = M.getTargetTriple();
5656

57-
for (RTLIB::LibcallImpl Impl : RTLCI.getLibcallImpls()) {
58-
if (Impl == RTLIB::Unsupported)
57+
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
58+
if (!RTLCI.isAvailable(Impl))
5959
continue;
6060

6161
auto [FuncTy, FuncAttrs] = RTLCI.getFunctionTy(Ctx, TT, DL, Impl);

0 commit comments

Comments
 (0)