LLVM 24.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
11#include "llvm/IR/Intrinsics.h"
12#include "llvm/IR/Module.h"
14#include "llvm/IR/Type.h"
16
17#define DEBUG_TYPE "runtime-libcalls-info"
18
19using namespace llvm;
20using namespace RTLIB;
21
22#define GET_RUNTIME_LIBCALLS_INFO
23#define GET_INIT_RUNTIME_LIBCALL_NAMES
24#define GET_INIT_RUNTIME_LIBCALL_SIGNATURES
25#define GET_SET_TARGET_RUNTIME_LIBCALL_SETS
26#define DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME
27#define GET_RUNTIME_LIBCALL_INTRINSIC_TO_LIBCALL
28#include "llvm/IR/RuntimeLibcalls.inc"
29
31 ExceptionHandling ExceptionModel,
33 StringRef ABIName,
34 VectorLibrary VecLib) {
35 // Only an unspecified model resolves to the triple default; None is left as
36 // an explicit disable.
37 if (ExceptionModel == ExceptionHandling::Default)
38 ExceptionModel = TT.getDefaultExceptionHandling();
39
40 initLibcalls(TT, ExceptionModel, FloatABI, ABIName,
41 TT.getDefaultLongDoubleFormat());
42
43 // TODO: Tablegen should generate these sets
44 switch (VecLib) {
46 for (RTLIB::LibcallImpl Impl :
47 {RTLIB::impl__ZGVnN2vv_fmod, RTLIB::impl__ZGVnN4vv_fmodf,
48 RTLIB::impl__ZGVsMxvv_fmod, RTLIB::impl__ZGVsMxvv_fmodf,
49 RTLIB::impl__ZGVnN2vl8_modf, RTLIB::impl__ZGVnN4vl4_modff,
50 RTLIB::impl__ZGVsNxvl8_modf, RTLIB::impl__ZGVsNxvl4_modff,
51 RTLIB::impl__ZGVnN2vl8l8_sincos, RTLIB::impl__ZGVnN4vl4l4_sincosf,
52 RTLIB::impl__ZGVsNxvl8l8_sincos, RTLIB::impl__ZGVsNxvl4l4_sincosf,
53 RTLIB::impl__ZGVnN4vl4l4_sincospif, RTLIB::impl__ZGVnN2vl8l8_sincospi,
54 RTLIB::impl__ZGVsNxvl4l4_sincospif,
55 RTLIB::impl__ZGVsNxvl8l8_sincospi})
56 setAvailable(Impl);
57 break;
59 for (RTLIB::LibcallImpl Impl : {RTLIB::impl_armpl_svfmod_f32_x,
60 RTLIB::impl_armpl_svfmod_f64_x,
61 RTLIB::impl_armpl_vfmodq_f32,
62 RTLIB::impl_armpl_vfmodq_f64,
63 RTLIB::impl_armpl_vmodfq_f64,
64 RTLIB::impl_armpl_vmodfq_f32,
65 RTLIB::impl_armpl_svmodf_f64_x,
66 RTLIB::impl_armpl_svmodf_f32_x,
67 RTLIB::impl_armpl_vsincosq_f64,
68 RTLIB::impl_armpl_vsincosq_f32,
69 RTLIB::impl_armpl_svsincos_f64_x,
70 RTLIB::impl_armpl_svsincos_f32_x,
71 RTLIB::impl_armpl_vsincospiq_f32,
72 RTLIB::impl_armpl_vsincospiq_f64,
73 RTLIB::impl_armpl_svsincospi_f32_x,
74 RTLIB::impl_armpl_svsincospi_f64_x,
75 RTLIB::impl_armpl_svpow_f32_x,
76 RTLIB::impl_armpl_svpow_f64_x,
77 RTLIB::impl_armpl_vpowq_f32,
78 RTLIB::impl_armpl_vpowq_f64,
79 RTLIB::impl_armpl_svcbrt_f32_x,
80 RTLIB::impl_armpl_svcbrt_f64_x,
81 RTLIB::impl_armpl_vcbrtq_f32,
82 RTLIB::impl_armpl_vcbrtq_f64})
83 setAvailable(Impl);
84
85 for (RTLIB::LibcallImpl Impl :
86 {RTLIB::impl_armpl_vfmodq_f32, RTLIB::impl_armpl_vfmodq_f64,
87 RTLIB::impl_armpl_vsincosq_f64, RTLIB::impl_armpl_vsincosq_f32,
88 RTLIB::impl_armpl_vpowq_f32, RTLIB::impl_armpl_vpowq_f64,
89 RTLIB::impl_armpl_vcbrtq_f32, RTLIB::impl_armpl_vcbrtq_f64})
91 break;
93 for (RTLIB::LibcallImpl Impl :
94 {RTLIB::impl_amd_vrd2_sincos, RTLIB::impl_amd_vrd4_sincos,
95 RTLIB::impl_amd_vrd8_sincos, RTLIB::impl_amd_vrs4_sincosf,
96 RTLIB::impl_amd_vrs8_sincosf, RTLIB::impl_amd_vrs16_sincosf})
97 setAvailable(Impl);
98 break;
99 default:
100 break;
101 }
102}
103
104// TODO: Consider the remaining module flags.
106 VectorLibrary VecLib)
107 : RuntimeLibcallsInfo(M.getTargetTriple(), M.getExceptionModel(),
108 M.getFloatABI(), ABIName, VecLib) {}
109
110bool RuntimeLibcallsInfo::isLibraryAvailable(StringRef LibraryName) const {
111 // TODO: Drive this from module-level state (e.g. the linked runtime). For now
112 // every named library is reported as available.
113 return true;
114}
115
116/// Set default libcall names. If a target wants to opt-out of a libcall it
117/// should be placed here.
118void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
119 ExceptionHandling ExceptionModel,
121 StringRef ABIName,
123 setTargetRuntimeLibcallSets(TT, ExceptionModel, FloatABI, ABIName,
125}
126
129RuntimeLibcallsInfo::libcallImplNameHit(uint16_t NameOffsetEntry,
130 uint16_t StrOffset) {
131 int NumAliases = 1;
132 for (uint16_t Entry : ArrayRef(RuntimeLibcallNameOffsetTable)
133 .drop_front(NameOffsetEntry + 1)) {
134 if (Entry != StrOffset)
135 break;
136 ++NumAliases;
137 }
138
139 RTLIB::LibcallImpl ImplStart = static_cast<RTLIB::LibcallImpl>(
140 &RuntimeLibcallNameOffsetTable[NameOffsetEntry] -
141 &RuntimeLibcallNameOffsetTable[0]);
142 return enum_seq(ImplStart,
143 static_cast<RTLIB::LibcallImpl>(ImplStart + NumAliases));
144}
145
146bool RuntimeLibcallsInfo::isAAPCS_ABI(const Triple &TT, StringRef ABIName) {
147 const ARM::ARMABI TargetABI = ARM::computeTargetABI(TT, ABIName);
148 return TargetABI == ARM::ARM_ABI_AAPCS || TargetABI == ARM::ARM_ABI_AAPCS16;
149}
150
151/// TODO: There is really no guarantee that sizeof(size_t) is equal to the index
152/// size of the default address space. This matches TargetLibraryInfo and should
153/// be kept in sync.
155 return DL.getIndexType(Ctx, /*AddressSpace=*/0);
156}
157
158static std::pair<Type *, Attribute> convertToIRTypeAndAttr(FuncArgTypeID ID,
159 LLVMContext &Ctx,
160 const DataLayout &DL,
161 unsigned IntBits) {
162
163 // FIXME: Use the llvm/ABI library to get accurate IR types and attributes.
164 switch (ID) {
165 case Void:
166 return {Type::getVoidTy(Ctx), Attribute()};
167 case Bool:
168 return {IntegerType::get(Ctx, 1), Attribute::get(Ctx, Attribute::ZExt)};
169 case Int16:
170 case UInt16:
171 return {IntegerType::get(Ctx, 16), Attribute()};
172 case Int32:
173 case UInt32:
174 return {IntegerType::get(Ctx, 32), Attribute()};
175 case Int:
176 case UInt:
177 case IntPlus:
178 case UIntPlus:
179 case Long:
180 case ULong:
181 case IntX:
182 case UIntX:
183 return {IntegerType::get(Ctx, IntBits), Attribute()};
184 case Int64:
185 case UInt64:
186 case LLong:
187 case ULLong:
188 return {IntegerType::get(Ctx, 64), Attribute()};
189 case SizeT:
190 case SSizeT:
191 return {getSizeTType(Ctx, DL), Attribute()};
192 case Flt:
193 case Floating:
194 return {Type::getFloatTy(Ctx), Attribute()};
195 case Dbl:
196 case LDbl:
197 return {Type::getDoubleTy(Ctx), Attribute()};
198 case Ptr:
199 return {PointerType::get(Ctx, 0), Attribute()};
200 default:
201 return {};
202 }
203}
204
205std::pair<FunctionType *, AttributeList>
207 LLVMContext &Ctx, const Triple &TT, const DataLayout &DL,
208 RTLIB::LibcallImpl LibcallImpl) const {
209 Libcall LC = getLibcallFromImpl(LibcallImpl);
210 const FuncArgTypeID *ProtoTypes = &SignatureTable[SignatureOffset[LC]];
211
212 if (ProtoTypes[0] == NoFuncArgType)
213 return {};
214
215 unsigned IntBits = getIntSize(TT);
216 AttributeList Attrs;
217
218 auto [RetTy, RetAttr] =
219 convertToIRTypeAndAttr(ProtoTypes[0], Ctx, DL, IntBits);
220 if (RetAttr.isValid())
221 Attrs = Attrs.addRetAttribute(Ctx, RetAttr);
222
223 Type *LastTy = RetTy, *ArgTy;
224 Attribute LastAttr = RetAttr, ArgAttr;
226 bool IsVarArg = false;
227 unsigned Idx = 1;
228 for (FuncArgTypeID TyID = ProtoTypes[Idx]; TyID != NoFuncArgType;
229 TyID = ProtoTypes[++Idx]) {
230 if (TyID == Ellip) {
231 // The ellipsis ends the protoype list so it must be followed by
232 // NoFuncArgType.
233 assert(ProtoTypes[Idx + 1] == NoFuncArgType);
234 IsVarArg = true;
235 break;
236 }
237
238 if (TyID == Same) {
239 ArgTy = LastTy;
240 ArgAttr = LastAttr;
241 } else {
242 std::tie(ArgTy, ArgAttr) =
243 convertToIRTypeAndAttr(ProtoTypes[Idx], Ctx, DL, IntBits);
244 LastTy = ArgTy;
245 LastAttr = ArgAttr;
246 }
247
248 ArgTys.push_back(ArgTy);
249 if (ArgAttr.isValid())
250 Attrs = Attrs.addParamAttribute(Ctx, Idx - 1, ArgAttr);
251 }
252
253 return {FunctionType::get(RetTy, ArgTys, IsVarArg), Attrs};
254}
255
256std::pair<FunctionType *, AttributeList>
258 const DataLayout &DL,
259 RTLIB::LibcallImpl LibcallImpl) const {
260 // TODO: NoCallback probably unsafe in general
261 static constexpr Attribute::AttrKind CommonFnAttrs[] = {
262 Attribute::NoCallback, Attribute::NoFree, Attribute::NoSync,
263 Attribute::NoUnwind, Attribute::WillReturn};
264 static constexpr Attribute::AttrKind MemoryFnAttrs[] = {
265 Attribute::NoUnwind, Attribute::WillReturn};
266 static constexpr Attribute::AttrKind CommonPtrArgAttrs[] = {
267 Attribute::NoAlias, Attribute::WriteOnly, Attribute::NonNull};
268
269 switch (LibcallImpl) {
270 case RTLIB::impl___sincos_stret:
271 case RTLIB::impl___sincosf_stret: {
272 if (!darwinHasSinCosStret(TT)) // Non-darwin currently unexpected
273 return {};
274
275 Type *ScalarTy = LibcallImpl == RTLIB::impl___sincosf_stret
276 ? Type::getFloatTy(Ctx)
277 : Type::getDoubleTy(Ctx);
278
279 AttrBuilder FuncAttrBuilder(Ctx);
280 for (Attribute::AttrKind Attr : CommonFnAttrs)
281 FuncAttrBuilder.addAttribute(Attr);
282
283 const bool UseSret =
284 TT.isX86_32() || ((TT.isARM() || TT.isThumb()) &&
286
287 FuncAttrBuilder.addMemoryAttr(MemoryEffects::argumentOrErrnoMemOnly(
289
290 AttributeList Attrs;
291 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
292
293 if (UseSret) {
294 AttrBuilder AttrBuilder(Ctx);
295 StructType *StructTy = StructType::get(ScalarTy, ScalarTy);
296 AttrBuilder.addStructRetAttr(StructTy);
297 AttrBuilder.addAlignmentAttr(DL.getABITypeAlign(StructTy));
299 Type::getVoidTy(Ctx), {DL.getAllocaPtrType(Ctx), ScalarTy}, false);
300
301 return {FuncTy, Attrs.addParamAttributes(Ctx, 0, AttrBuilder)};
302 }
303
304 Type *RetTy =
305 LibcallImpl == RTLIB::impl___sincosf_stret && TT.isX86_64()
306 ? static_cast<Type *>(FixedVectorType::get(ScalarTy, 2))
307 : static_cast<Type *>(StructType::get(ScalarTy, ScalarTy));
308
309 return {FunctionType::get(RetTy, {ScalarTy}, false), Attrs};
310 }
311 case RTLIB::impl_malloc:
312 case RTLIB::impl_calloc: {
313 AttrBuilder FuncAttrBuilder(Ctx);
314 for (Attribute::AttrKind Attr : MemoryFnAttrs)
315 FuncAttrBuilder.addAttribute(Attr);
316 FuncAttrBuilder.addAttribute(Attribute::NoFree);
317
319 if (LibcallImpl == RTLIB::impl_malloc)
320 AllocKind |= AllocFnKind::Uninitialized;
321
322 // TODO: Set memory attribute
323 FuncAttrBuilder.addAllocKindAttr(AllocKind);
324 FuncAttrBuilder.addAttribute("alloc-family", "malloc");
325 FuncAttrBuilder.addAllocSizeAttr(0, LibcallImpl == RTLIB::impl_malloc
326 ? std::nullopt
327 : std::make_optional(1));
328
329 AttributeList Attrs;
330 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
331
332 {
333 AttrBuilder ArgAttrBuilder(Ctx);
334 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
335 ArgAttrBuilder.addAttribute(AK);
336
337 Attrs = Attrs.addRetAttribute(Ctx, Attribute::NoUndef);
338 Attrs = Attrs.addRetAttribute(Ctx, Attribute::NoAlias);
339 Attrs = Attrs.addParamAttribute(Ctx, 0, Attribute::NoUndef);
340 if (LibcallImpl == RTLIB::impl_calloc)
341 Attrs = Attrs.addParamAttribute(Ctx, 1, Attribute::NoUndef);
342 }
343
344 IntegerType *SizeT = getSizeTType(Ctx, DL);
345 PointerType *PtrTy = PointerType::get(Ctx, 0);
346 SmallVector<Type *, 2> ArgTys = {SizeT};
347 if (LibcallImpl == RTLIB::impl_calloc)
348 ArgTys.push_back(SizeT);
349
350 return {FunctionType::get(PtrTy, ArgTys, false), Attrs};
351 }
352 case RTLIB::impl_free: {
353 // TODO: Set memory attribute
354 AttrBuilder FuncAttrBuilder(Ctx);
355 for (Attribute::AttrKind Attr : MemoryFnAttrs)
356 FuncAttrBuilder.addAttribute(Attr);
357
358 FuncAttrBuilder.addAllocKindAttr(AllocFnKind::Free);
359 FuncAttrBuilder.addAttribute("alloc-family", "malloc");
360
361 AttributeList Attrs;
362 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
363
364 {
365 AttrBuilder ArgAttrBuilder(Ctx);
366 ArgAttrBuilder.addAttribute(Attribute::NoUndef);
367 ArgAttrBuilder.addAttribute(Attribute::AllocatedPointer);
368 ArgAttrBuilder.addCapturesAttr(CaptureInfo::none());
369 Attrs = Attrs.addParamAttributes(Ctx, 0, ArgAttrBuilder);
370 }
371
372 return {FunctionType::get(Type::getVoidTy(Ctx), {PointerType::get(Ctx, 0)},
373 false),
374 Attrs};
375 }
376 case RTLIB::impl___aeabi_idivmod:
377 case RTLIB::impl___aeabi_uidivmod:
378 case RTLIB::impl___aeabi_ldivmod:
379 case RTLIB::impl___aeabi_uldivmod:
380 case RTLIB::impl___rt_sdiv:
381 case RTLIB::impl___rt_udiv:
382 case RTLIB::impl___rt_sdiv64:
383 case RTLIB::impl___rt_udiv64: {
384 // The ARM AEABI (__aeabi_*divmod) and Windows (__rt_*div*) divmod functions
385 // return both values modeled as an inreg { iN, iN } struct (quotient,
386 // remainder). The __rt_*div* cases pass the arguments in opposite order,
387 // though this doesn't affect the declaration.
388 bool IsSigned;
389 unsigned Bits;
390 switch (LibcallImpl) {
391 case RTLIB::impl___aeabi_idivmod:
392 case RTLIB::impl___rt_sdiv:
393 IsSigned = true;
394 Bits = 32;
395 break;
396 case RTLIB::impl___aeabi_uidivmod:
397 case RTLIB::impl___rt_udiv:
398 IsSigned = false;
399 Bits = 32;
400 break;
401 case RTLIB::impl___aeabi_ldivmod:
402 case RTLIB::impl___rt_sdiv64:
403 IsSigned = true;
404 Bits = 64;
405 break;
406 case RTLIB::impl___aeabi_uldivmod:
407 case RTLIB::impl___rt_udiv64:
408 IsSigned = false;
409 Bits = 64;
410 break;
411 default:
412 llvm_unreachable("unexpected divmod libcall");
413 }
414
415 Type *IntTy = IntegerType::get(Ctx, Bits);
416 StructType *RetTy = StructType::get(IntTy, IntTy);
417 FunctionType *FuncTy = FunctionType::get(RetTy, {IntTy, IntTy}, false);
418
419 AttrBuilder FuncAttrBuilder(Ctx);
420 for (Attribute::AttrKind Attr : CommonFnAttrs)
421 FuncAttrBuilder.addAttribute(Attr);
422 FuncAttrBuilder.addMemoryAttr(MemoryEffects::none());
423
424 AttributeList Attrs;
425 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
426
427 Attribute::AttrKind ExtKind = IsSigned ? Attribute::SExt : Attribute::ZExt;
428 Attrs = Attrs.addRetAttribute(Ctx, Attribute::InReg);
429 Attrs = Attrs.addParamAttribute(Ctx, 0, ExtKind);
430 Attrs = Attrs.addParamAttribute(Ctx, 1, ExtKind);
431
432 return {FuncTy, Attrs};
433 }
434 case RTLIB::impl_sqrtf:
435 case RTLIB::impl_sqrt: {
436 AttrBuilder FuncAttrBuilder(Ctx);
437
438 for (Attribute::AttrKind Attr : CommonFnAttrs)
439 FuncAttrBuilder.addAttribute(Attr);
440 FuncAttrBuilder.addMemoryAttr(MemoryEffects::errnoMemOnly(ModRefInfo::Mod));
441
442 AttributeList Attrs;
443 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
444
445 Type *ScalarTy = LibcallImpl == RTLIB::impl_sqrtf ? Type::getFloatTy(Ctx)
446 : Type::getDoubleTy(Ctx);
447 FunctionType *FuncTy = FunctionType::get(ScalarTy, {ScalarTy}, false);
448
449 Attrs = Attrs.addRetAttribute(
451 fcNegNormal));
452 return {FuncTy, Attrs};
453 }
454 case RTLIB::impl__ZGVnN2vv_fmod:
455 case RTLIB::impl__ZGVnN4vv_fmodf:
456 case RTLIB::impl__ZGVsMxvv_fmod:
457 case RTLIB::impl__ZGVsMxvv_fmodf:
458 case RTLIB::impl_armpl_vfmodq_f32:
459 case RTLIB::impl_armpl_vfmodq_f64:
460 case RTLIB::impl_armpl_svfmod_f32_x:
461 case RTLIB::impl_armpl_svfmod_f64_x:
462 case RTLIB::impl_armpl_vpowq_f32:
463 case RTLIB::impl_armpl_vpowq_f64:
464 case RTLIB::impl_armpl_svpow_f32_x:
465 case RTLIB::impl_armpl_svpow_f64_x:
466 case RTLIB::impl_armpl_vcbrtq_f32:
467 case RTLIB::impl_armpl_vcbrtq_f64:
468 case RTLIB::impl_armpl_svcbrt_f32_x:
469 case RTLIB::impl_armpl_svcbrt_f64_x: {
470 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vv_fmodf ||
471 LibcallImpl == RTLIB::impl__ZGVsMxvv_fmodf ||
472 LibcallImpl == RTLIB::impl_armpl_svfmod_f32_x ||
473 LibcallImpl == RTLIB::impl_armpl_vfmodq_f32 ||
474 LibcallImpl == RTLIB::impl_armpl_vpowq_f32 ||
475 LibcallImpl == RTLIB::impl_armpl_svpow_f32_x ||
476 LibcallImpl == RTLIB::impl_armpl_vcbrtq_f32 ||
477 LibcallImpl == RTLIB::impl_armpl_svcbrt_f32_x;
478
479 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsMxvv_fmod ||
480 LibcallImpl == RTLIB::impl__ZGVsMxvv_fmodf ||
481 LibcallImpl == RTLIB::impl_armpl_svfmod_f32_x ||
482 LibcallImpl == RTLIB::impl_armpl_svfmod_f64_x ||
483 LibcallImpl == RTLIB::impl_armpl_svpow_f32_x ||
484 LibcallImpl == RTLIB::impl_armpl_svpow_f64_x ||
485 LibcallImpl == RTLIB::impl_armpl_svcbrt_f32_x ||
486 LibcallImpl == RTLIB::impl_armpl_svcbrt_f64_x;
487
488 bool HasOneArg = LibcallImpl == RTLIB::impl_armpl_vcbrtq_f32 ||
489 LibcallImpl == RTLIB::impl_armpl_vcbrtq_f64 ||
490 LibcallImpl == RTLIB::impl_armpl_svcbrt_f32_x ||
491 LibcallImpl == RTLIB::impl_armpl_svcbrt_f64_x;
492
493 AttrBuilder FuncAttrBuilder(Ctx);
494
495 for (Attribute::AttrKind Attr : CommonFnAttrs)
496 FuncAttrBuilder.addAttribute(Attr);
497
498 AttributeList Attrs;
499 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
500
501 Type *ScalarTy = IsF32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
502 unsigned EC = IsF32 ? 4 : 2;
503 VectorType *VecTy = VectorType::get(ScalarTy, EC, IsScalable);
504
505 SmallVector<Type *, 3> ArgTys(HasOneArg ? 1 : 2, VecTy);
506 if (hasVectorMaskArgument(LibcallImpl))
507 ArgTys.push_back(VectorType::get(Type::getInt1Ty(Ctx), EC, IsScalable));
508
509 FunctionType *FuncTy = FunctionType::get(VecTy, ArgTys, false);
510 return {FuncTy, Attrs};
511 }
512 case RTLIB::impl__ZGVnN2vl8_modf:
513 case RTLIB::impl__ZGVnN4vl4_modff:
514 case RTLIB::impl__ZGVsNxvl8_modf:
515 case RTLIB::impl__ZGVsNxvl4_modff:
516 case RTLIB::impl_armpl_vmodfq_f64:
517 case RTLIB::impl_armpl_vmodfq_f32:
518 case RTLIB::impl_armpl_svmodf_f64_x:
519 case RTLIB::impl_armpl_svmodf_f32_x: {
520 AttrBuilder FuncAttrBuilder(Ctx);
521
522 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vl4_modff ||
523 LibcallImpl == RTLIB::impl__ZGVsNxvl4_modff ||
524 LibcallImpl == RTLIB::impl_armpl_vmodfq_f32 ||
525 LibcallImpl == RTLIB::impl_armpl_svmodf_f32_x;
526
527 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsNxvl8_modf ||
528 LibcallImpl == RTLIB::impl__ZGVsNxvl4_modff ||
529 LibcallImpl == RTLIB::impl_armpl_svmodf_f64_x ||
530 LibcallImpl == RTLIB::impl_armpl_svmodf_f32_x;
531
532 Type *ScalarTy = IsF32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
533 unsigned EC = IsF32 ? 4 : 2;
534 VectorType *VecTy = VectorType::get(ScalarTy, EC, IsScalable);
535
536 for (Attribute::AttrKind Attr : CommonFnAttrs)
537 FuncAttrBuilder.addAttribute(Attr);
538 FuncAttrBuilder.addMemoryAttr(MemoryEffects::argMemOnly(ModRefInfo::Mod));
539
540 AttributeList Attrs;
541 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
542
543 {
544 AttrBuilder ArgAttrBuilder(Ctx);
545 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
546 ArgAttrBuilder.addAttribute(AK);
547 ArgAttrBuilder.addAlignmentAttr(DL.getABITypeAlign(VecTy));
548 Attrs = Attrs.addParamAttributes(Ctx, 1, ArgAttrBuilder);
549 }
550
551 PointerType *PtrTy = PointerType::get(Ctx, 0);
552 SmallVector<Type *, 4> ArgTys = {VecTy, PtrTy};
553 if (hasVectorMaskArgument(LibcallImpl))
554 ArgTys.push_back(VectorType::get(Type::getInt1Ty(Ctx), EC, IsScalable));
555
556 return {FunctionType::get(VecTy, ArgTys, false), Attrs};
557 }
558 case RTLIB::impl__ZGVnN2vl8l8_sincos:
559 case RTLIB::impl__ZGVnN4vl4l4_sincosf:
560 case RTLIB::impl__ZGVsNxvl8l8_sincos:
561 case RTLIB::impl__ZGVsNxvl4l4_sincosf:
562 case RTLIB::impl_armpl_vsincosq_f64:
563 case RTLIB::impl_armpl_vsincosq_f32:
564 case RTLIB::impl_armpl_svsincos_f64_x:
565 case RTLIB::impl_armpl_svsincos_f32_x:
566 case RTLIB::impl__ZGVnN4vl4l4_sincospif:
567 case RTLIB::impl__ZGVnN2vl8l8_sincospi:
568 case RTLIB::impl__ZGVsNxvl4l4_sincospif:
569 case RTLIB::impl__ZGVsNxvl8l8_sincospi:
570 case RTLIB::impl_armpl_vsincospiq_f32:
571 case RTLIB::impl_armpl_vsincospiq_f64:
572 case RTLIB::impl_armpl_svsincospi_f32_x:
573 case RTLIB::impl_armpl_svsincospi_f64_x: {
574 AttrBuilder FuncAttrBuilder(Ctx);
575
576 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vl4l4_sincospif ||
577 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincospif ||
578 LibcallImpl == RTLIB::impl_armpl_vsincospiq_f32 ||
579 LibcallImpl == RTLIB::impl_armpl_svsincospi_f32_x ||
580 LibcallImpl == RTLIB::impl__ZGVnN4vl4l4_sincosf ||
581 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincosf ||
582 LibcallImpl == RTLIB::impl_armpl_vsincosq_f32 ||
583 LibcallImpl == RTLIB::impl_armpl_svsincos_f32_x;
584
585 Type *ScalarTy = IsF32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
586 unsigned EC = IsF32 ? 4 : 2;
587
588 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsNxvl8l8_sincos ||
589 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincosf ||
590 LibcallImpl == RTLIB::impl_armpl_svsincos_f32_x ||
591 LibcallImpl == RTLIB::impl_armpl_svsincos_f64_x ||
592 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincospif ||
593 LibcallImpl == RTLIB::impl__ZGVsNxvl8l8_sincospi ||
594 LibcallImpl == RTLIB::impl_armpl_svsincospi_f32_x ||
595 LibcallImpl == RTLIB::impl_armpl_svsincospi_f64_x;
596 VectorType *VecTy = VectorType::get(ScalarTy, EC, IsScalable);
597
598 for (Attribute::AttrKind Attr : CommonFnAttrs)
599 FuncAttrBuilder.addAttribute(Attr);
600 FuncAttrBuilder.addMemoryAttr(MemoryEffects::argMemOnly(ModRefInfo::Mod));
601
602 AttributeList Attrs;
603 Attrs = Attrs.addFnAttributes(Ctx, FuncAttrBuilder);
604
605 {
606 AttrBuilder ArgAttrBuilder(Ctx);
607 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
608 ArgAttrBuilder.addAttribute(AK);
609 ArgAttrBuilder.addAlignmentAttr(DL.getABITypeAlign(VecTy));
610 Attrs = Attrs.addParamAttributes(Ctx, 1, ArgAttrBuilder);
611 Attrs = Attrs.addParamAttributes(Ctx, 2, ArgAttrBuilder);
612 }
613
614 PointerType *PtrTy = PointerType::get(Ctx, 0);
615 SmallVector<Type *, 4> ArgTys = {VecTy, PtrTy, PtrTy};
616 if (hasVectorMaskArgument(LibcallImpl))
617 ArgTys.push_back(VectorType::get(Type::getInt1Ty(Ctx), EC, IsScalable));
618
619 return {FunctionType::get(Type::getVoidTy(Ctx), ArgTys, false), Attrs};
620 }
621 default:
622 return getDefaultFunctionTy(Ctx, TT, DL, LibcallImpl);
623 }
624
625 return {};
626}
627
628bool RuntimeLibcallsInfo::hasVectorMaskArgument(RTLIB::LibcallImpl Impl) {
629 /// FIXME: This should be generated by tablegen and support the argument at an
630 /// arbitrary position
631 switch (Impl) {
632 case RTLIB::impl_armpl_svfmod_f32_x:
633 case RTLIB::impl_armpl_svfmod_f64_x:
634 case RTLIB::impl_armpl_svmodf_f64_x:
635 case RTLIB::impl_armpl_svmodf_f32_x:
636 case RTLIB::impl_armpl_svsincos_f32_x:
637 case RTLIB::impl_armpl_svsincos_f64_x:
638 case RTLIB::impl_armpl_svsincospi_f32_x:
639 case RTLIB::impl_armpl_svsincospi_f64_x:
640 case RTLIB::impl__ZGVsMxvv_fmod:
641 case RTLIB::impl__ZGVsMxvv_fmodf:
642 case RTLIB::impl_armpl_svpow_f32_x:
643 case RTLIB::impl_armpl_svpow_f64_x:
644 case RTLIB::impl_armpl_svcbrt_f32_x:
645 case RTLIB::impl_armpl_svcbrt_f64_x:
646 return true;
647 default:
648 return false;
649 }
650}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
@ RetAttr
#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:372
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 IntegerType * getSizeTType(LLVMContext &Ctx, const DataLayout &DL)
TODO: There is really no guarantee that sizeof(size_t) is equal to the index size of the default addr...
static std::pair< Type *, Attribute > convertToIRTypeAndAttr(FuncArgTypeID ID, LLVMContext &Ctx, const DataLayout &DL, unsigned IntBits)
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
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:125
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Definition ModRef.h:427
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
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.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
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:143
static MemoryEffectsBase errnoMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:154
static MemoryEffectsBase argumentOrErrnoMemOnly(ModRefInfo ArgMR=ModRefInfo::ModRef, ModRefInfo ErrnoMR=ModRefInfo::ModRef)
Definition ModRef.h:198
static MemoryEffectsBase none()
Definition ModRef.h:128
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Class to represent pointers.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Definition Type.cpp:887
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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:467
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:272
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:296
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:277
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:276
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
AllocFnKind
Definition Attributes.h:54
LongDoubleFormat
The floating-point format used for the target's "long double" type.
Definition CodeGen.h:117
constexpr auto enum_seq(EnumT Begin, EnumT End)
Iterate over an enum type from Begin up to - but not including - End.
Definition Sequence.h:373
@ 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 >
ExceptionHandling
Definition CodeGen.h:54
@ Default
Not specified; resolve to the target's default model.
Definition CodeGen.h:55
VectorLibrary
List of known vector-functions libraries.
LLVM_ABI std::pair< FunctionType *, AttributeList > getFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const
void setAvailable(RTLIB::LibcallImpl Impl)
static LLVM_ABI bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl)
Returns true if the function has a vector mask argument, which is assumed to be the last argument.
unsigned getIntSize(const Triple &TT) const
Get size of a C-level int or unsigned int, in bits.
void setLibcallImplCallingConv(RTLIB::LibcallImpl Call, CallingConv::ID CC)
Set the CallingConv that should be used for the specified libcall implementation.
LLVM_ABI std::pair< FunctionType *, AttributeList > getDefaultFunctionTy(LLVMContext &Ctx, const Triple &TT, const DataLayout &DL, RTLIB::LibcallImpl LibcallImpl) const
Get the C-type function signature of the Libcall if provided, and convert it to IR FunctionType and A...
static RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl)
Return the libcall provided by Impl.