Skip to content

Commit fb21f16

Browse files
authored
RuntimeLibcalls: Add stub API for getting function signatures (#166290)
Eventually this should be generated by tablegen for all functions. For now add a manually implementation for sincos_stret, which I have an immediate use for. This will allow pulling repeated code across targets into shared call sequence code. Also add sqrt just to make sure we can handle adding return attributes on the declaration.
1 parent 6217f35 commit fb21f16

File tree

7 files changed

+189
-4
lines changed

7 files changed

+189
-4
lines changed

llvm/include/llvm/IR/RuntimeLibcalls.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ struct RuntimeLibcallsInfo {
186186
return RTLIB::Unsupported;
187187
}
188188

189+
/// \returns the function type and attributes for the \p LibcallImpl,
190+
/// depending on the target \p TT. If the function has incomplete type
191+
/// information, return nullptr for the function type.
192+
std::pair<FunctionType *, AttributeList>
193+
getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL,
194+
RTLIB::LibcallImpl LibcallImpl) const;
195+
189196
private:
190197
LLVM_ABI static iota_range<RTLIB::LibcallImpl>
191198
lookupLibcallImplNameImpl(StringRef Name);

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/IR/RuntimeLibcalls.h"
10+
#include "llvm/ADT/FloatingPointMode.h"
1011
#include "llvm/ADT/StringTable.h"
12+
#include "llvm/IR/DataLayout.h"
1113
#include "llvm/Support/Debug.h"
1214
#include "llvm/Support/xxhash.h"
1315
#include "llvm/TargetParser/ARMTargetParser.h"
@@ -72,3 +74,80 @@ bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
7274
return false;
7375
}
7476
}
77+
78+
std::pair<FunctionType *, AttributeList>
79+
RuntimeLibcallsInfo::getFunctionTy(LLVMContext &Ctx, const Triple &TT,
80+
const DataLayout &DL,
81+
RTLIB::LibcallImpl LibcallImpl) const {
82+
static constexpr Attribute::AttrKind CommonFnAttrs[] = {
83+
Attribute::NoCallback, Attribute::NoFree, Attribute::NoSync,
84+
Attribute::NoUnwind, Attribute::WillReturn};
85+
86+
switch (LibcallImpl) {
87+
case RTLIB::impl___sincos_stret:
88+
case RTLIB::impl___sincosf_stret: {
89+
if (!darwinHasSinCosStret(TT)) // Non-darwin currently unexpected
90+
return {};
91+
92+
Type *ScalarTy = LibcallImpl == RTLIB::impl___sincosf_stret
93+
? Type::getFloatTy(Ctx)
94+
: Type::getDoubleTy(Ctx);
95+
96+
AttrBuilder FuncAttrBuilder(Ctx);
97+
for (Attribute::AttrKind Attr : CommonFnAttrs)
98+
FuncAttrBuilder.addAttribute(Attr);
99+
100+
const bool UseSret =
101+
TT.isX86_32() || ((TT.isARM() || TT.isThumb()) &&
102+
ARM::computeTargetABI(TT) == ARM::ARM_ABI_APCS);
103+
104+
FuncAttrBuilder.addMemoryAttr(MemoryEffects::argumentOrErrnoMemOnly(
105+
UseSret ? ModRefInfo::Mod : ModRefInfo::NoModRef, ModRefInfo::Mod));
106+
107+
AttributeList Attrs;
108+
Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
109+
110+
if (UseSret) {
111+
AttrBuilder AttrBuilder(Ctx);
112+
StructType *StructTy = StructType::get(ScalarTy, ScalarTy);
113+
AttrBuilder.addStructRetAttr(StructTy);
114+
AttrBuilder.addAlignmentAttr(DL.getABITypeAlign(StructTy));
115+
FunctionType *FuncTy = FunctionType::get(
116+
Type::getVoidTy(Ctx), {DL.getAllocaPtrType(Ctx), ScalarTy}, false);
117+
118+
return {FuncTy, Attrs.addParamAttributes(Ctx, 0, AttrBuilder)};
119+
}
120+
121+
Type *RetTy =
122+
LibcallImpl == RTLIB::impl___sincosf_stret && TT.isX86_64()
123+
? static_cast<Type *>(FixedVectorType::get(ScalarTy, 2))
124+
: static_cast<Type *>(StructType::get(ScalarTy, ScalarTy));
125+
126+
return {FunctionType::get(RetTy, {ScalarTy}, false), Attrs};
127+
}
128+
case RTLIB::impl_sqrtf:
129+
case RTLIB::impl_sqrt: {
130+
AttrBuilder FuncAttrBuilder(Ctx);
131+
132+
for (Attribute::AttrKind Attr : CommonFnAttrs)
133+
FuncAttrBuilder.addAttribute(Attr);
134+
FuncAttrBuilder.addMemoryAttr(MemoryEffects::errnoMemOnly(ModRefInfo::Mod));
135+
136+
AttributeList Attrs;
137+
Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
138+
139+
Type *ScalarTy = LibcallImpl == RTLIB::impl_sqrtf ? Type::getFloatTy(Ctx)
140+
: Type::getDoubleTy(Ctx);
141+
FunctionType *FuncTy = FunctionType::get(ScalarTy, {ScalarTy}, false);
142+
143+
Attrs = Attrs.addRetAttribute(
144+
Ctx, Attribute::getWithNoFPClass(Ctx, fcNegInf | fcNegSubnormal |
145+
fcNegNormal));
146+
return {FuncTy, Attrs};
147+
}
148+
default:
149+
return {};
150+
}
151+
152+
return {};
153+
}

llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,62 @@
1616

1717
using namespace llvm;
1818

19+
static void mergeAttributes(LLVMContext &Ctx, const Module &M,
20+
const DataLayout &DL, const Triple &TT,
21+
Function *Func, FunctionType *FuncTy,
22+
AttributeList FuncAttrs) {
23+
AttributeList OldAttrs = Func->getAttributes();
24+
AttributeList NewAttrs = OldAttrs;
25+
26+
{
27+
AttrBuilder OldBuilder(Ctx, OldAttrs.getFnAttrs());
28+
AttrBuilder NewBuilder(Ctx, FuncAttrs.getFnAttrs());
29+
OldBuilder.merge(NewBuilder);
30+
NewAttrs = NewAttrs.addFnAttributes(Ctx, OldBuilder);
31+
}
32+
33+
{
34+
AttrBuilder OldBuilder(Ctx, OldAttrs.getRetAttrs());
35+
AttrBuilder NewBuilder(Ctx, FuncAttrs.getRetAttrs());
36+
OldBuilder.merge(NewBuilder);
37+
NewAttrs = NewAttrs.addRetAttributes(Ctx, OldBuilder);
38+
}
39+
40+
for (unsigned I = 0, E = FuncTy->getNumParams(); I != E; ++I) {
41+
AttrBuilder OldBuilder(Ctx, OldAttrs.getParamAttrs(I));
42+
AttrBuilder NewBuilder(Ctx, FuncAttrs.getParamAttrs(I));
43+
OldBuilder.merge(NewBuilder);
44+
NewAttrs = NewAttrs.addParamAttributes(Ctx, I, OldBuilder);
45+
}
46+
47+
Func->setAttributes(NewAttrs);
48+
}
49+
1950
PreservedAnalyses DeclareRuntimeLibcallsPass::run(Module &M,
2051
ModuleAnalysisManager &MAM) {
2152
RTLIB::RuntimeLibcallsInfo RTLCI(M.getTargetTriple());
2253
LLVMContext &Ctx = M.getContext();
54+
const DataLayout &DL = M.getDataLayout();
55+
const Triple &TT = M.getTargetTriple();
2356

2457
for (RTLIB::LibcallImpl Impl : RTLCI.getLibcallImpls()) {
2558
if (Impl == RTLIB::Unsupported)
2659
continue;
2760

28-
// TODO: Declare with correct type, calling convention, and attributes.
61+
auto [FuncTy, FuncAttrs] = RTLCI.getFunctionTy(Ctx, TT, DL, Impl);
2962

30-
FunctionType *FuncTy =
31-
FunctionType::get(Type::getVoidTy(Ctx), {}, /*IsVarArgs=*/true);
63+
// TODO: Declare with correct type, calling convention, and attributes.
64+
if (!FuncTy)
65+
FuncTy = FunctionType::get(Type::getVoidTy(Ctx), {}, /*IsVarArgs=*/true);
3266

3367
StringRef FuncName = RTLCI.getLibcallImplName(Impl);
34-
M.getOrInsertFunction(FuncName, FuncTy);
68+
69+
Function *Func =
70+
cast<Function>(M.getOrInsertFunction(FuncName, FuncTy).getCallee());
71+
if (Func->getFunctionType() == FuncTy) {
72+
mergeAttributes(Ctx, M, DL, TT, Func, FuncTy, FuncAttrs);
73+
Func->setCallingConv(RTLCI.getLibcallImplCallingConv(Impl));
74+
}
3575
}
3676

3777
return PreservedAnalyses::none();

llvm/test/Transforms/Util/DeclareRuntimeLibcalls/basic.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,9 @@ define float @sinf(float %x) {
1111
}
1212

1313
; CHECK: declare void @acosf(...)
14+
15+
; CHECK: declare nofpclass(ninf nsub nnorm) float @sqrtf(float) [[SQRT_ATTRS:#[0-9]+]]
16+
; CHECK: declare nofpclass(ninf nsub nnorm) double @sqrt(double) [[SQRT_ATTRS:#[0-9]+]]
17+
1418
; CHECK: declare void @__umodti3(...)
1519

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
2+
3+
define noundef nofpclass(nan) float @sqrtf(float %x) "foo" {
4+
%ret = call float asm "; $0 = sqrt($1)", "=r,r"(float %x)
5+
ret float %ret
6+
}
7+
8+
; FIXME: Individual fields of nofpclass not merged
9+
; CHECK: define noundef nofpclass(ninf nsub nnorm) float @sqrtf(float %x) [[SQRT_ATTR:#[0-9]+]] {
10+
11+
; CHECK: attributes [[SQRT_ATTR]] = { nocallback nofree nosync nounwind willreturn memory(errnomem: write) "foo" }
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=x86_64-apple-macos10.9 < %s | FileCheck -check-prefixes=CHECK,X64 %s
2+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=arm64-apple-macos10.9 < %s | FileCheck -check-prefixes=CHECK,STRUCT %s
3+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=thumbv7k-apple-watchos2.0 < %s | FileCheck -check-prefixes=CHECK,STRUCT %s
4+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=armv7-apple-ios7 < %s | FileCheck -check-prefix=SRET %s
5+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=thumbv7-apple-ios7 < %s | FileCheck -check-prefix=SRET %s
6+
7+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=armv7-apple-ios6 < %s | FileCheck -check-prefix=NONE %s
8+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=x86_64-apple-macos10.8 < %s | FileCheck -check-prefix=NONE %s
9+
10+
; X64: declare <2 x float> @__sincosf_stret(float) [[SINCOS_ATTRS:#[0-9]+]]
11+
; X64: declare { double, double } @__sincos_stret(double) [[SINCOS_ATTRS:#[0-9]+]]
12+
13+
; STRUCT: declare { float, float } @__sincosf_stret(float) [[SINCOS_ATTRS:#[0-9]+]]
14+
; STRUCT: declare { double, double } @__sincos_stret(double) [[SINCOS_ATTRS:#[0-9]+]]
15+
16+
; SRET: declare void @__sincosf_stret(ptr sret({ float, float }) align 4, float) [[SINCOS_ATTRS:#[0-9]+]]
17+
; SRET: declare void @__sincos_stret(ptr sret({ double, double }) align 4, double) [[SINCOS_ATTRS:#[0-9]+]]
18+
19+
; CHECK: attributes [[SINCOS_ATTRS]] = { nocallback nofree nosync nounwind willreturn memory(errnomem: write) }
20+
; SRET: attributes [[SINCOS_ATTRS]] = { nocallback nofree nosync nounwind willreturn memory(argmem: write, errnomem: write) }
21+
22+
; NONE-NOT: __sincos_stret
23+
; NONE-NOT: __sincosf_stret
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: opt -S -passes=declare-runtime-libcalls -mtriple=x86_64-apple-macos10.9 < %s | FileCheck %s
2+
3+
; Make sure there is no crash if there are definitions or declarations
4+
; with the wrong type signature.
5+
6+
; CHECK: define void @sqrtf() {
7+
define void @sqrtf() {
8+
ret void
9+
}
10+
11+
; CHECK: define float @sqrt(float %0) {
12+
define float @sqrt(float) {
13+
ret float 0.0
14+
}
15+
16+
; CHECK: declare double @__sincos_stret(double)
17+
declare double @__sincos_stret(double)
18+
19+
; CHECK: declare { float, float } @__sincosf_stret(float)
20+
declare { float, float } @__sincosf_stret(float)
21+

0 commit comments

Comments
 (0)