Skip to content

Commit 3325765

Browse files
committed
TableGen: Allow defining sets of runtime libraries
Add a way to define a SystemLibrary for a complete set of libcalls, subdivided by a predicate based on the triple. Libraries can be defined using dag set operations, and the prior default set can be subtracted from and added to (though I think eventually all targets should move to explicit opt-ins. We're still doing things like reporting ppcf128 libcalls as available dy default on all targets). Start migrating some of the easier targets to only use the new system. Targets that don't define a SystemLibrary are still manually mutating a table set to the old defaults.
1 parent 3b3d494 commit 3325765

File tree

9 files changed

+889
-418
lines changed

9 files changed

+889
-418
lines changed

llvm/include/llvm/IR/RuntimeLibcalls.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ struct RuntimeLibcallsInfo {
5252
FloatABI::ABIType FloatABI = FloatABI::Default,
5353
EABI EABIVersion = EABI::Default, StringRef ABIName = "") {
5454
initSoftFloatCmpLibcallPredicates();
55-
initDefaultLibCallImpls();
5655
initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion, ABIName);
5756
}
5857

@@ -97,6 +96,7 @@ struct RuntimeLibcallsInfo {
9796
/// Get the comparison predicate that's to be used to test the result of the
9897
/// comparison libcall against zero. This should only be used with
9998
/// floating-point compare libcalls.
99+
// FIXME: This should be a function of RTLIB::LibcallImpl
100100
CmpInst::Predicate
101101
getSoftFloatCmpLibcallPredicate(RTLIB::Libcall Call) const {
102102
return SoftFloatCompareLibcallPredicates[Call];
@@ -172,13 +172,7 @@ struct RuntimeLibcallsInfo {
172172
void initDefaultLibCallImpls();
173173

174174
/// Generated by tablegen.
175-
void setPPCLibCallNameOverrides();
176-
177-
/// Generated by tablegen.
178-
void setZOSLibCallNameOverrides();
179-
180-
/// Generated by tablegen.
181-
void setWindowsArm64LibCallNameOverrides();
175+
void setTargetRuntimeLibcallSets(const Triple &TT);
182176

183177
void initSoftFloatCmpLibcallPredicates();
184178

llvm/include/llvm/IR/RuntimeLibcalls.td

Lines changed: 309 additions & 184 deletions
Large diffs are not rendered by default.

llvm/include/llvm/IR/RuntimeLibcallsImpl.td

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
include "llvm/TableGen/SetTheory.td"
10+
11+
// Predicate for whether a libcall exists for the target ABI. This is
12+
// a module level property that should only be computed based on the
13+
// triple.
14+
class RuntimeLibcallPredicate<code cond> {
15+
// Expression of an llvm::Triple named TT for whether a libcall
16+
// should exist.
17+
code Cond = cond;
18+
}
19+
20+
// Predicate for whether a libcall should be used for the current
21+
// function/subtarget.
22+
class LibcallLoweringPredicate<code cond> { code Cond = cond; }
23+
24+
def AlwaysAvailable : RuntimeLibcallPredicate<[{}]>;
25+
926
/// Abstract definition for functionality the compiler may need to
1027
/// emit a call to. Emits the RTLIB::Libcall enum - This enum defines
1128
/// all of the runtime library calls the backend can emit. The various
@@ -28,5 +45,24 @@ class RuntimeLibcall {
2845
class RuntimeLibcallImpl<RuntimeLibcall P, string Name = NAME> {
2946
RuntimeLibcall Provides = P;
3047
string LibCallFuncName = Name;
48+
list<LibcallLoweringPredicate> LoweringPredicates;
3149
bit IsDefault = false;
3250
}
51+
52+
class LibcallImpls<dag funcList,
53+
RuntimeLibcallPredicate Pred = AlwaysAvailable> {
54+
// Function of the triple where this applies
55+
RuntimeLibcallPredicate AvailabilityPredicate = Pred;
56+
dag MemberList = funcList;
57+
}
58+
59+
/// Convenience wrapper around LibcallImplSet to make a single libcall
60+
/// implementation conditionally conditionally available.
61+
class AvailableIf<RuntimeLibcallImpl Impl, RuntimeLibcallPredicate Pred>
62+
: LibcallImpls<(add Impl), Pred>;
63+
64+
/// Define a complete top level set of runtime libcalls for a target.
65+
class SystemRuntimeLibrary<RuntimeLibcallPredicate Pred, dag funcList> {
66+
RuntimeLibcallPredicate TriplePred = Pred;
67+
LibcallImpls MemberList = LibcallImpls<funcList>;
68+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===- SetTheory.td - DAG set operator declarations --------*- tablegen -*-===//
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+
// FIXME: This is not used everywhere, and different files declare
10+
// different subsets of used operators.
11+
//
12+
// It just happens TargetSelectionDAG.td defines records with the same
13+
// names as the tablegen DAG operators for SelectionDAG operators.
14+
15+
// Target.td separately declares the special set operators.
16+
17+
def add; // Forward declare
18+
def sub;
19+
def and;
20+
def shl;
21+
// def trunc; // FIXME: Name collision
22+
def rotl;
23+
def rotr;
24+
25+
def sequence;
26+
def decimate;
27+
def interleave;

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 6 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,16 @@
1212
using namespace llvm;
1313
using namespace RTLIB;
1414

15-
#define GET_INIT_RUNTIME_LIBCALL_UTILS
1615
#define GET_INIT_RUNTIME_LIBCALL_NAMES
16+
#define GET_SET_TARGET_RUNTIME_LIBCALL_SETS
1717
#include "llvm/IR/RuntimeLibcalls.inc"
18-
#undef GET_INIT_RUNTIME_LIBCALL_UTILS
1918
#undef GET_INIT_RUNTIME_LIBCALL_NAMES
19+
#undef GET_SET_TARGET_RUNTIME_LIBCALL_SETS
2020

2121
static cl::opt<bool>
2222
HexagonEnableFastMathRuntimeCalls("hexagon-fast-math", cl::Hidden,
2323
cl::desc("Enable Fast Math processing"));
2424

25-
static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
26-
const Triple &TT) {
27-
#define LCALLNAMES(A, B, N) \
28-
Info.setLibcallImpl(A##N##_RELAX, B##N##_relax); \
29-
Info.setLibcallImpl(A##N##_ACQ, B##N##_acq); \
30-
Info.setLibcallImpl(A##N##_REL, B##N##_rel); \
31-
Info.setLibcallImpl(A##N##_ACQ_REL, B##N##_acq_rel);
32-
#define LCALLNAME4(A, B) \
33-
LCALLNAMES(A, B, 1) \
34-
LCALLNAMES(A, B, 2) LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8)
35-
#define LCALLNAME5(A, B) \
36-
LCALLNAMES(A, B, 1) \
37-
LCALLNAMES(A, B, 2) \
38-
LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8) LCALLNAMES(A, B, 16)
39-
40-
if (TT.isWindowsArm64EC()) {
41-
LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::arm64ec___aarch64_cas)
42-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::arm64ec___aarch64_swp)
43-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::arm64ec___aarch64_ldadd)
44-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::arm64ec___aarch64_ldset)
45-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::arm64ec___aarch64_ldclr)
46-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::arm64ec___aarch64_ldeor)
47-
} else {
48-
LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::__aarch64_cas)
49-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::__aarch64_swp)
50-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::__aarch64_ldadd)
51-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::__aarch64_ldset)
52-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::__aarch64_ldclr)
53-
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::__aarch64_ldeor)
54-
}
55-
#undef LCALLNAMES
56-
#undef LCALLNAME4
57-
#undef LCALLNAME5
58-
}
59-
6025
static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
6126
FloatABI::ABIType FloatABIType,
6227
EABI EABIVersion) {
@@ -358,6 +323,8 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
358323
ExceptionHandling ExceptionModel,
359324
FloatABI::ABIType FloatABI,
360325
EABI EABIVersion, StringRef ABIName) {
326+
setTargetRuntimeLibcallSets(TT);
327+
361328
// Use the f128 variants of math functions on x86
362329
if (TT.isX86() && TT.isGNUEnvironment())
363330
setLongDoubleIsF128Libm(*this, /*FiniteOnlyFuncs=*/true);
@@ -367,28 +334,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
367334
setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
368335
}
369336

370-
if (TT.isPPC()) {
371-
setPPCLibCallNameOverrides();
372-
373-
// TODO: Do the finite only functions exist?
374-
setLongDoubleIsF128Libm(*this, /*FiniteOnlyFuncs=*/false);
375-
376-
// TODO: Tablegen predicate support
377-
if (TT.isOSAIX()) {
378-
if (TT.isPPC64()) {
379-
setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
380-
setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove64);
381-
setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset64);
382-
setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero64);
383-
} else {
384-
setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
385-
setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove);
386-
setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset);
387-
setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero);
388-
}
389-
}
390-
}
391-
392337
// A few names are different on particular architectures or environments.
393338
if (TT.isOSDarwin()) {
394339
// For f16/f32 conversions, Darwin uses the standard naming scheme,
@@ -485,14 +430,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
485430
setLibcallImpl(RTLIB::FREXP_PPCF128, RTLIB::Unsupported);
486431
}
487432

488-
// Disable most libcalls on AMDGPU and NVPTX.
489-
if (TT.isAMDGPU() || TT.isNVPTX()) {
490-
for (RTLIB::Libcall LC : RTLIB::libcalls()) {
491-
if (!isAtomicLibCall(LC))
492-
setLibcallImpl(LC, RTLIB::Unsupported);
493-
}
494-
}
495-
496433
if (TT.isOSMSVCRT()) {
497434
// MSVCRT doesn't have powi; fall back to pow
498435
setLibcallImpl(RTLIB::POWI_F32, RTLIB::Unsupported);
@@ -520,55 +457,14 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
520457
}
521458
}
522459

523-
if (TT.isAArch64()) {
524-
if (TT.isWindowsArm64EC()) {
525-
setWindowsArm64LibCallNameOverrides();
526-
setLibcallImpl(RTLIB::SC_MEMCPY, RTLIB::arm64ec___arm_sc_memcpy);
527-
setLibcallImpl(RTLIB::SC_MEMMOVE, RTLIB::arm64ec___arm_sc_memmove);
528-
setLibcallImpl(RTLIB::SC_MEMSET, RTLIB::arm64ec___arm_sc_memset);
529-
} else {
530-
setLibcallImpl(RTLIB::SC_MEMCPY, RTLIB::__arm_sc_memcpy);
531-
setLibcallImpl(RTLIB::SC_MEMMOVE, RTLIB::__arm_sc_memmove);
532-
setLibcallImpl(RTLIB::SC_MEMSET, RTLIB::__arm_sc_memset);
533-
}
534-
535-
setAArch64LibcallNames(*this, TT);
536-
} else if (TT.isARM() || TT.isThumb()) {
460+
if (TT.isARM() || TT.isThumb())
537461
setARMLibcallNames(*this, TT, FloatABI, EABIVersion);
538-
} else if (TT.getArch() == Triple::ArchType::avr) {
539-
// Division rtlib functions (not supported), use divmod functions instead
540-
setLibcallImpl(RTLIB::SDIV_I8, RTLIB::Unsupported);
541-
setLibcallImpl(RTLIB::SDIV_I16, RTLIB::Unsupported);
542-
setLibcallImpl(RTLIB::SDIV_I32, RTLIB::Unsupported);
543-
setLibcallImpl(RTLIB::UDIV_I8, RTLIB::Unsupported);
544-
setLibcallImpl(RTLIB::UDIV_I16, RTLIB::Unsupported);
545-
setLibcallImpl(RTLIB::UDIV_I32, RTLIB::Unsupported);
546-
547-
// Modulus rtlib functions (not supported), use divmod functions instead
548-
setLibcallImpl(RTLIB::SREM_I8, RTLIB::Unsupported);
549-
setLibcallImpl(RTLIB::SREM_I16, RTLIB::Unsupported);
550-
setLibcallImpl(RTLIB::SREM_I32, RTLIB::Unsupported);
551-
setLibcallImpl(RTLIB::UREM_I8, RTLIB::Unsupported);
552-
setLibcallImpl(RTLIB::UREM_I16, RTLIB::Unsupported);
553-
setLibcallImpl(RTLIB::UREM_I32, RTLIB::Unsupported);
554-
555-
// Division and modulus rtlib functions
556-
setLibcallImpl(RTLIB::SDIVREM_I8, RTLIB::__divmodqi4);
557-
setLibcallImpl(RTLIB::SDIVREM_I16, RTLIB::__divmodhi4);
558-
setLibcallImpl(RTLIB::SDIVREM_I32, RTLIB::__divmodsi4);
559-
setLibcallImpl(RTLIB::UDIVREM_I8, RTLIB::__udivmodqi4);
560-
setLibcallImpl(RTLIB::UDIVREM_I16, RTLIB::__udivmodhi4);
561-
setLibcallImpl(RTLIB::UDIVREM_I32, RTLIB::__udivmodsi4);
562-
462+
else if (TT.getArch() == Triple::ArchType::avr) {
563463
// Several of the runtime library functions use a special calling conv
564464
setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
565465
setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::AVR_BUILTIN);
566466
setLibcallCallingConv(RTLIB::UDIVREM_I8, CallingConv::AVR_BUILTIN);
567467
setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::AVR_BUILTIN);
568-
569-
// Trigonometric rtlib functions
570-
setLibcallImpl(RTLIB::SIN_F32, RTLIB::avr_sin);
571-
setLibcallImpl(RTLIB::COS_F32, RTLIB::avr_cos);
572468
}
573469

574470
if (!TT.isWasm()) {
@@ -582,11 +478,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
582478
}
583479

584480
setLibcallImpl(RTLIB::MULO_I128, RTLIB::Unsupported);
585-
} else {
586-
// Define the emscripten name for return address helper.
587-
// TODO: when implementing other Wasm backends, make this generic or only do
588-
// this on emscripten depending on what they end up doing.
589-
setLibcallImpl(RTLIB::RETURN_ADDRESS, RTLIB::emscripten_return_address);
590481
}
591482

592483
if (TT.getArch() == Triple::ArchType::hexagon) {
@@ -633,10 +524,4 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
633524

634525
if (TT.getArch() == Triple::ArchType::msp430)
635526
setMSP430Libcalls(*this, TT);
636-
637-
if (TT.isSystemZ() && TT.isOSzOS())
638-
setZOSLibCallNameOverrides();
639-
640-
if (TT.getArch() == Triple::ArchType::xcore)
641-
setLibcallImpl(RTLIB::MEMCPY_ALIGN_4, RTLIB::__memcpy_4);
642527
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s 2> %t.err | FileCheck %s
2+
// RUN: FileCheck -check-prefix=ERR %s < %t.err
3+
4+
// Check behavior of libcall emission when multiple RuntimeLibcallImpl
5+
// implementations provide the same RuntimeLibcall
6+
7+
include "llvm/IR/RuntimeLibCallsImpl.td"
8+
9+
def SOME_FUNC : RuntimeLibcall;
10+
def OTHER_FUNC : RuntimeLibcall;
11+
def ANOTHER_DUP : RuntimeLibcall;
12+
13+
def isTargetArchA : RuntimeLibcallPredicate<[{isTargetArchA()}]>;
14+
def isTargetArchB : RuntimeLibcallPredicate<[{isTargetArchB()}]>;
15+
def isTargetArchC : RuntimeLibcallPredicate<[{isTargetArchC()}]>;
16+
17+
def func_a : RuntimeLibcallImpl<SOME_FUNC>;
18+
def func_b : RuntimeLibcallImpl<SOME_FUNC>;
19+
def func_c : RuntimeLibcallImpl<SOME_FUNC>;
20+
def other_func : RuntimeLibcallImpl<OTHER_FUNC>;
21+
22+
def dup0 : RuntimeLibcallImpl<ANOTHER_DUP>;
23+
def dup1 : RuntimeLibcallImpl<ANOTHER_DUP>;
24+
25+
// func_a and func_b both provide SOME_FUNC.
26+
27+
// CHECK: if (isTargetArchA()) {
28+
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
29+
// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::func_b}, // func_b
30+
// CHECK-NEXT: };
31+
32+
// ERR: :[[@LINE+1]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_b, func_a
33+
def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA,
34+
(add func_b, func_a)
35+
>;
36+
37+
// CHECK: if (isTargetArchB()) {
38+
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
39+
// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func
40+
// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a
41+
// CHECK-NEXT: };
42+
43+
// ERR: :[[@LINE+1]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_a, func_b
44+
def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB,
45+
(add func_a, other_func, func_b)
46+
>;
47+
48+
// CHECK: if (isTargetArchC()) {
49+
// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
50+
// CHECK-NEXT: {RTLIB::ANOTHER_DUP, RTLIB::dup1}, // dup1
51+
// CHECK-NEXT: {RTLIB::OTHER_FUNC, RTLIB::other_func}, // other_func
52+
// CHECK-NEXT: {RTLIB::SOME_FUNC, RTLIB::func_a}, // func_a
53+
// CHECK-NEXT: };
54+
55+
// ERR: :[[@LINE+3]]:5: warning: conflicting implementations for libcall ANOTHER_DUP: dup1, dup0
56+
// ERR: :[[@LINE+2]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_a, func_b
57+
// ERR: :[[@LINE+1]]:5: warning: conflicting implementations for libcall SOME_FUNC: func_a, func_c
58+
def TheSystemLibraryC : SystemRuntimeLibrary<isTargetArchC,
59+
(add func_a, dup1, other_func, func_b, func_c, dup0)
60+
>;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: not llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s 2>&1 | FileCheck -check-prefix=ERR %s
2+
3+
include "llvm/IR/RuntimeLibCallsImpl.td"
4+
5+
def FUNC0 : RuntimeLibcall;
6+
def FUNC1 : RuntimeLibcall;
7+
8+
def isFoo : RuntimeLibcallPredicate<[{isFoo()}]>;
9+
def isBar : RuntimeLibcallPredicate<[{isBar()}]>;
10+
def isTargetArch : RuntimeLibcallPredicate<[{isTargetArch()}]>;
11+
12+
def func0 : RuntimeLibcallImpl<FUNC0>;
13+
def func1 : RuntimeLibcallImpl<FUNC1>;
14+
15+
// ERR: :[[@LINE+2]]:8: error: combining nested libcall set predicates currently unhandled
16+
def TheSystemLibrary : SystemRuntimeLibrary<isTargetArch,
17+
(add LibcallImpls<(add func0, LibcallImpls<(add func1), isBar>), isFoo>)
18+
>;

0 commit comments

Comments
 (0)