LLVM 22.0.0git
RuntimeLibcalls.cpp
Go to the documentation of this file.
1//===- RuntimeLibcalls.cpp - Interface for runtime libcalls -----*- 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
12#include "llvm/IR/Module.h"
14#include "llvm/Support/Debug.h"
15#include "llvm/Support/xxhash.h"
17
18#define DEBUG_TYPE "runtime-libcalls-info"
19
20using namespace llvm;
21using namespace RTLIB;
22
23#define GET_RUNTIME_LIBCALLS_INFO
24#define GET_INIT_RUNTIME_LIBCALL_NAMES
25#define GET_SET_TARGET_RUNTIME_LIBCALL_SETS
26#define DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME
27#include "llvm/IR/RuntimeLibcalls.inc"
28
30 ExceptionHandling ExceptionModel,
32 EABI EABIVersion, StringRef ABIName,
33 VectorLibrary VecLib) {
34 // FIXME: The ExceptionModel parameter is to handle the field in
35 // TargetOptions. This interface fails to distinguish the forced disable
36 // case for targets which support exceptions by default. This should
37 // probably be a module flag and removed from TargetOptions.
38 if (ExceptionModel == ExceptionHandling::None)
39 ExceptionModel = TT.getDefaultExceptionHandling();
40
41 initLibcalls(TT, ExceptionModel, FloatABI, EABIVersion, ABIName);
42
43 // TODO: Tablegen should generate these sets
44 switch (VecLib) {
46 for (RTLIB::LibcallImpl Impl :
47 {RTLIB::impl__ZGVnN2vl8_modf, RTLIB::impl__ZGVnN4vl4_modff,
48 RTLIB::impl__ZGVsNxvl8_modf, RTLIB::impl__ZGVsNxvl4_modff,
49 RTLIB::impl__ZGVnN2vl8l8_sincos, RTLIB::impl__ZGVnN4vl4l4_sincosf,
50 RTLIB::impl__ZGVsNxvl8l8_sincos, RTLIB::impl__ZGVsNxvl4l4_sincosf,
51 RTLIB::impl__ZGVnN4vl4l4_sincospif, RTLIB::impl__ZGVnN2vl8l8_sincospi,
52 RTLIB::impl__ZGVsNxvl4l4_sincospif,
53 RTLIB::impl__ZGVsNxvl8l8_sincospi})
54 setAvailable(Impl);
55 break;
57 for (RTLIB::LibcallImpl Impl :
58 {RTLIB::impl_armpl_vmodfq_f64, RTLIB::impl_armpl_vmodfq_f32,
59 RTLIB::impl_armpl_svmodf_f64_x, RTLIB::impl_armpl_svmodf_f32_x,
60 RTLIB::impl_armpl_vsincosq_f64, RTLIB::impl_armpl_vsincosq_f32,
61 RTLIB::impl_armpl_svsincos_f64_x, RTLIB::impl_armpl_svsincos_f32_x,
62 RTLIB::impl_armpl_vsincospiq_f32, RTLIB::impl_armpl_vsincospiq_f64,
63 RTLIB::impl_armpl_svsincospi_f32_x,
64 RTLIB::impl_armpl_svsincospi_f64_x})
65 setAvailable(Impl);
66
67 for (RTLIB::LibcallImpl Impl :
68 {RTLIB::impl_armpl_vsincosq_f64, RTLIB::impl_armpl_vsincosq_f32})
70
71 break;
72 default:
73 break;
74 }
75}
76
78 : RuntimeLibcallsInfo(M.getTargetTriple()) {
79 // TODO: Consider module flags
80}
81
82/// Set default libcall names. If a target wants to opt-out of a libcall it
83/// should be placed here.
84void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
85 ExceptionHandling ExceptionModel,
87 EABI EABIVersion, StringRef ABIName) {
88 setTargetRuntimeLibcallSets(TT, ExceptionModel, FloatABI, EABIVersion,
89 ABIName);
90}
91
94RuntimeLibcallsInfo::libcallImplNameHit(uint16_t NameOffsetEntry,
95 uint16_t StrOffset) {
96 int NumAliases = 1;
97 for (uint16_t Entry : ArrayRef(RuntimeLibcallNameOffsetTable)
98 .drop_front(NameOffsetEntry + 1)) {
99 if (Entry != StrOffset)
100 break;
101 ++NumAliases;
102 }
103
104 RTLIB::LibcallImpl ImplStart = static_cast<RTLIB::LibcallImpl>(
105 &RuntimeLibcallNameOffsetTable[NameOffsetEntry] -
106 &RuntimeLibcallNameOffsetTable[0]);
107 return enum_seq(ImplStart,
108 static_cast<RTLIB::LibcallImpl>(ImplStart + NumAliases));
109}
110
111bool RuntimeLibcallsInfo::isAAPCS_ABI(const Triple &TT, StringRef ABIName) {
112 const ARM::ARMABI TargetABI = ARM::computeTargetABI(TT, ABIName);
113 return TargetABI == ARM::ARM_ABI_AAPCS || TargetABI == ARM::ARM_ABI_AAPCS16;
114}
115
116bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
117 switch (TT.getOS()) {
118 case Triple::MacOSX:
119 return !TT.isMacOSXVersionLT(10, 9);
120 case Triple::IOS:
121 return !TT.isOSVersionLT(7, 0);
123 case Triple::TvOS:
124 case Triple::WatchOS:
125 case Triple::XROS:
126 case Triple::BridgeOS:
127 return true;
128 default:
129 return false;
130 }
131}
132
133std::pair<FunctionType *, AttributeList>
135 const DataLayout &DL,
136 RTLIB::LibcallImpl LibcallImpl) const {
137 static constexpr Attribute::AttrKind CommonFnAttrs[] = {
138 Attribute::NoCallback, Attribute::NoFree, Attribute::NoSync,
139 Attribute::NoUnwind, Attribute::WillReturn};
140 static constexpr Attribute::AttrKind CommonPtrArgAttrs[] = {
141 Attribute::NoAlias, Attribute::WriteOnly, Attribute::NonNull};
142
143 switch (LibcallImpl) {
144 case RTLIB::impl___sincos_stret:
145 case RTLIB::impl___sincosf_stret: {
146 if (!darwinHasSinCosStret(TT)) // Non-darwin currently unexpected
147 return {};
148
149 Type *ScalarTy = LibcallImpl == RTLIB::impl___sincosf_stret
150 ? Type::getFloatTy(Ctx)
151 : Type::getDoubleTy(Ctx);
152
153 AttrBuilder FuncAttrBuilder(Ctx);
154 for (Attribute::AttrKind Attr : CommonFnAttrs)
155 FuncAttrBuilder.addAttribute(Attr);
156
157 const bool UseSret =
158 TT.isX86_32() || ((TT.isARM() || TT.isThumb()) &&
160
161 FuncAttrBuilder.addMemoryAttr(MemoryEffects::argumentOrErrnoMemOnly(
163
164 AttributeList Attrs;
165 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
166
167 if (UseSret) {
168 AttrBuilder AttrBuilder(Ctx);
169 StructType *StructTy = StructType::get(ScalarTy, ScalarTy);
170 AttrBuilder.addStructRetAttr(StructTy);
171 AttrBuilder.addAlignmentAttr(DL.getABITypeAlign(StructTy));
173 Type::getVoidTy(Ctx), {DL.getAllocaPtrType(Ctx), ScalarTy}, false);
174
175 return {FuncTy, Attrs.addParamAttributes(Ctx, 0, AttrBuilder)};
176 }
177
178 Type *RetTy =
179 LibcallImpl == RTLIB::impl___sincosf_stret && TT.isX86_64()
180 ? static_cast<Type *>(FixedVectorType::get(ScalarTy, 2))
181 : static_cast<Type *>(StructType::get(ScalarTy, ScalarTy));
182
183 return {FunctionType::get(RetTy, {ScalarTy}, false), Attrs};
184 }
185 case RTLIB::impl_sqrtf:
186 case RTLIB::impl_sqrt: {
187 AttrBuilder FuncAttrBuilder(Ctx);
188
189 for (Attribute::AttrKind Attr : CommonFnAttrs)
190 FuncAttrBuilder.addAttribute(Attr);
191 FuncAttrBuilder.addMemoryAttr(MemoryEffects::errnoMemOnly(ModRefInfo::Mod));
192
193 AttributeList Attrs;
194 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
195
196 Type *ScalarTy = LibcallImpl == RTLIB::impl_sqrtf ? Type::getFloatTy(Ctx)
197 : Type::getDoubleTy(Ctx);
198 FunctionType *FuncTy = FunctionType::get(ScalarTy, {ScalarTy}, false);
199
200 Attrs = Attrs.addRetAttribute(
202 fcNegNormal));
203 return {FuncTy, Attrs};
204 }
205 case RTLIB::impl__ZGVnN2vl8_modf:
206 case RTLIB::impl__ZGVnN4vl4_modff:
207 case RTLIB::impl__ZGVsNxvl8_modf:
208 case RTLIB::impl__ZGVsNxvl4_modff:
209 case RTLIB::impl_armpl_vmodfq_f64:
210 case RTLIB::impl_armpl_vmodfq_f32:
211 case RTLIB::impl_armpl_svmodf_f64_x:
212 case RTLIB::impl_armpl_svmodf_f32_x: {
213 AttrBuilder FuncAttrBuilder(Ctx);
214
215 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vl4_modff ||
216 LibcallImpl == RTLIB::impl__ZGVsNxvl4_modff ||
217 LibcallImpl == RTLIB::impl_armpl_vmodfq_f32 ||
218 LibcallImpl == RTLIB::impl_armpl_svmodf_f32_x;
219
220 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsNxvl8_modf ||
221 LibcallImpl == RTLIB::impl__ZGVsNxvl4_modff ||
222 LibcallImpl == RTLIB::impl_armpl_svmodf_f64_x ||
223 LibcallImpl == RTLIB::impl_armpl_svmodf_f32_x;
224
225 Type *ScalarTy = IsF32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
226 unsigned EC = IsF32 ? 4 : 2;
227 VectorType *VecTy = VectorType::get(ScalarTy, EC, IsScalable);
228
229 for (Attribute::AttrKind Attr : CommonFnAttrs)
230 FuncAttrBuilder.addAttribute(Attr);
231 FuncAttrBuilder.addMemoryAttr(MemoryEffects::argMemOnly(ModRefInfo::Mod));
232
233 AttributeList Attrs;
234 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
235
236 {
237 AttrBuilder ArgAttrBuilder(Ctx);
238 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
239 ArgAttrBuilder.addAttribute(AK);
240 ArgAttrBuilder.addAlignmentAttr(DL.getABITypeAlign(VecTy));
241 Attrs = Attrs.addParamAttributes(Ctx, 1, ArgAttrBuilder);
242 }
243
244 PointerType *PtrTy = PointerType::get(Ctx, 0);
245 SmallVector<Type *, 4> ArgTys = {VecTy, PtrTy};
246 if (hasVectorMaskArgument(LibcallImpl))
247 ArgTys.push_back(VectorType::get(Type::getInt1Ty(Ctx), EC, IsScalable));
248
249 return {FunctionType::get(VecTy, ArgTys, false), Attrs};
250 }
251 case RTLIB::impl__ZGVnN2vl8l8_sincos:
252 case RTLIB::impl__ZGVnN4vl4l4_sincosf:
253 case RTLIB::impl__ZGVsNxvl8l8_sincos:
254 case RTLIB::impl__ZGVsNxvl4l4_sincosf:
255 case RTLIB::impl_armpl_vsincosq_f64:
256 case RTLIB::impl_armpl_vsincosq_f32:
257 case RTLIB::impl_armpl_svsincos_f64_x:
258 case RTLIB::impl_armpl_svsincos_f32_x:
259 case RTLIB::impl__ZGVnN4vl4l4_sincospif:
260 case RTLIB::impl__ZGVnN2vl8l8_sincospi:
261 case RTLIB::impl__ZGVsNxvl4l4_sincospif:
262 case RTLIB::impl__ZGVsNxvl8l8_sincospi:
263 case RTLIB::impl_armpl_vsincospiq_f32:
264 case RTLIB::impl_armpl_vsincospiq_f64:
265 case RTLIB::impl_armpl_svsincospi_f32_x:
266 case RTLIB::impl_armpl_svsincospi_f64_x: {
267 AttrBuilder FuncAttrBuilder(Ctx);
268
269 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vl4l4_sincospif ||
270 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincospif ||
271 LibcallImpl == RTLIB::impl_armpl_vsincospiq_f32 ||
272 LibcallImpl == RTLIB::impl_armpl_svsincospi_f32_x ||
273 LibcallImpl == RTLIB::impl__ZGVnN4vl4l4_sincosf ||
274 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincosf ||
275 LibcallImpl == RTLIB::impl_armpl_vsincosq_f32 ||
276 LibcallImpl == RTLIB::impl_armpl_svsincos_f32_x;
277
278 Type *ScalarTy = IsF32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
279 unsigned EC = IsF32 ? 4 : 2;
280
281 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsNxvl8l8_sincos ||
282 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincosf ||
283 LibcallImpl == RTLIB::impl_armpl_svsincos_f32_x ||
284 LibcallImpl == RTLIB::impl_armpl_svsincos_f64_x ||
285 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincospif ||
286 LibcallImpl == RTLIB::impl__ZGVsNxvl8l8_sincospi ||
287 LibcallImpl == RTLIB::impl_armpl_svsincospi_f32_x ||
288 LibcallImpl == RTLIB::impl_armpl_svsincospi_f64_x;
289 VectorType *VecTy = VectorType::get(ScalarTy, EC, IsScalable);
290
291 for (Attribute::AttrKind Attr : CommonFnAttrs)
292 FuncAttrBuilder.addAttribute(Attr);
293 FuncAttrBuilder.addMemoryAttr(MemoryEffects::argMemOnly(ModRefInfo::Mod));
294
295 AttributeList Attrs;
296 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
297
298 {
299 AttrBuilder ArgAttrBuilder(Ctx);
300 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
301 ArgAttrBuilder.addAttribute(AK);
302 ArgAttrBuilder.addAlignmentAttr(DL.getABITypeAlign(VecTy));
303 Attrs = Attrs.addParamAttributes(Ctx, 1, ArgAttrBuilder);
304 Attrs = Attrs.addParamAttributes(Ctx, 2, ArgAttrBuilder);
305 }
306
307 PointerType *PtrTy = PointerType::get(Ctx, 0);
308 SmallVector<Type *, 4> ArgTys = {VecTy, PtrTy, PtrTy};
309 if (hasVectorMaskArgument(LibcallImpl))
310 ArgTys.push_back(VectorType::get(Type::getInt1Ty(Ctx), EC, IsScalable));
311
312 return {FunctionType::get(Type::getVoidTy(Ctx), ArgTys, false), Attrs};
313 }
314 default:
315 return {};
316 }
317
318 return {};
319}
320
321bool RuntimeLibcallsInfo::hasVectorMaskArgument(RTLIB::LibcallImpl Impl) {
322 /// FIXME: This should be generated by tablegen and support the argument at an
323 /// arbitrary position
324 switch (Impl) {
325 case RTLIB::impl_armpl_svmodf_f64_x:
326 case RTLIB::impl_armpl_svmodf_f32_x:
327 case RTLIB::impl_armpl_svsincos_f32_x:
328 case RTLIB::impl_armpl_svsincos_f64_x:
329 case RTLIB::impl_armpl_svsincospi_f32_x:
330 case RTLIB::impl_armpl_svsincospi_f64_x:
331 return true;
332 default:
333 return false;
334 }
335}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_ATTRIBUTE_ALWAYS_INLINE
LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do so, mark a method "always...
Definition Compiler.h:356
Utilities for dealing with flags related to floating point properties and mode controls.
Module.h This file contains the declarations for the Module class.
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:88
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:802
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:140
static MemoryEffectsBase errnoMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:151
static MemoryEffectsBase argumentOrErrnoMemOnly(ModRefInfo ArgMR=ModRefInfo::ModRef, ModRefInfo ErrnoMR=ModRefInfo::ModRef)
Definition ModRef.h:172
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
Class to represent pointers.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:413
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:280
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:293
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:285
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:284
Base class of all SIMD vector types.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
LLVM_ABI LLVM_READONLY ARMABI computeTargetABI(const Triple &TT, StringRef ABIName="")
@ AArch64_VectorCall
Used between AArch64 Advanced SIMD functions.
This is an optimization pass for GlobalISel generic memory operations.
auto enum_seq(EnumT Begin, EnumT End)
Iterate over an enum type from Begin up to - but not including - End.
Definition Sequence.h:337
ExceptionHandling
Definition CodeGen.h:53
@ None
No exception support.
Definition CodeGen.h:54
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ NoModRef
The access neither references nor modifies the value stored in memory.
Definition ModRef.h:30
ArrayRef(const T &OneElt) -> ArrayRef< T >
VectorLibrary
List of known vector-functions libraries.
EABI
Definition CodeGen.h:73
std::pair< FunctionType *, AttributeList > getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const
void setAvailable(RTLIB::LibcallImpl Impl)
static bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl)
Returns true if the function has a vector mask argument, which is assumed to be the last argument.
void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC)
Set the CallingConv that should be used for the specified libcall implementation.