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
9#include "llvm/IR/RuntimeLibcalls.h"
10#include "llvm/ADT/FloatingPointMode.h"
11#include "llvm/IR/Intrinsics.h"
12#include "llvm/IR/Module.h"
13#include "llvm/IR/SystemLibraries.h"
14#include "llvm/IR/Type.h"
15#include "llvm/TargetParser/ARMTargetParser.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_SET_TARGET_RUNTIME_LIBCALL_SETS
25#define DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME
26#define GET_RUNTIME_LIBCALL_INTRINSIC_TO_LIBCALL
27#include "llvm/IR/RuntimeLibcalls.inc"
28
29RuntimeLibcallsInfo::RuntimeLibcallsInfo(const Triple &TT,
30 ExceptionHandling ExceptionModel,
31 FloatABI::ABIType FloatABI,
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, ABIType: EABIVersion, ABIName,
42 LongDoubleFormat: TT.getDefaultLongDoubleFormat());
43
44 // TODO: Tablegen should generate these sets
45 switch (VecLib) {
46 case VectorLibrary::SLEEFGNUABI:
47 for (RTLIB::LibcallImpl Impl :
48 {RTLIB::impl__ZGVnN2vv_fmod, RTLIB::impl__ZGVnN4vv_fmodf,
49 RTLIB::impl__ZGVsMxvv_fmod, RTLIB::impl__ZGVsMxvv_fmodf,
50 RTLIB::impl__ZGVnN2vl8_modf, RTLIB::impl__ZGVnN4vl4_modff,
51 RTLIB::impl__ZGVsNxvl8_modf, RTLIB::impl__ZGVsNxvl4_modff,
52 RTLIB::impl__ZGVnN2vl8l8_sincos, RTLIB::impl__ZGVnN4vl4l4_sincosf,
53 RTLIB::impl__ZGVsNxvl8l8_sincos, RTLIB::impl__ZGVsNxvl4l4_sincosf,
54 RTLIB::impl__ZGVnN4vl4l4_sincospif, RTLIB::impl__ZGVnN2vl8l8_sincospi,
55 RTLIB::impl__ZGVsNxvl4l4_sincospif,
56 RTLIB::impl__ZGVsNxvl8l8_sincospi})
57 setAvailable(Impl);
58 break;
59 case VectorLibrary::ArmPL:
60 for (RTLIB::LibcallImpl Impl : {RTLIB::impl_armpl_svfmod_f32_x,
61 RTLIB::impl_armpl_svfmod_f64_x,
62 RTLIB::impl_armpl_vfmodq_f32,
63 RTLIB::impl_armpl_vfmodq_f64,
64 RTLIB::impl_armpl_vmodfq_f64,
65 RTLIB::impl_armpl_vmodfq_f32,
66 RTLIB::impl_armpl_svmodf_f64_x,
67 RTLIB::impl_armpl_svmodf_f32_x,
68 RTLIB::impl_armpl_vsincosq_f64,
69 RTLIB::impl_armpl_vsincosq_f32,
70 RTLIB::impl_armpl_svsincos_f64_x,
71 RTLIB::impl_armpl_svsincos_f32_x,
72 RTLIB::impl_armpl_vsincospiq_f32,
73 RTLIB::impl_armpl_vsincospiq_f64,
74 RTLIB::impl_armpl_svsincospi_f32_x,
75 RTLIB::impl_armpl_svsincospi_f64_x,
76 RTLIB::impl_armpl_svpow_f32_x,
77 RTLIB::impl_armpl_svpow_f64_x,
78 RTLIB::impl_armpl_vpowq_f32,
79 RTLIB::impl_armpl_vpowq_f64,
80 RTLIB::impl_armpl_svcbrt_f32_x,
81 RTLIB::impl_armpl_svcbrt_f64_x,
82 RTLIB::impl_armpl_vcbrtq_f32,
83 RTLIB::impl_armpl_vcbrtq_f64})
84 setAvailable(Impl);
85
86 for (RTLIB::LibcallImpl Impl :
87 {RTLIB::impl_armpl_vfmodq_f32, RTLIB::impl_armpl_vfmodq_f64,
88 RTLIB::impl_armpl_vsincosq_f64, RTLIB::impl_armpl_vsincosq_f32,
89 RTLIB::impl_armpl_vpowq_f32, RTLIB::impl_armpl_vpowq_f64,
90 RTLIB::impl_armpl_vcbrtq_f32, RTLIB::impl_armpl_vcbrtq_f64})
91 setLibcallImplCallingConv(Call: Impl, CC: CallingConv::AArch64_VectorCall);
92 break;
93 case VectorLibrary::AMDLIBM:
94 for (RTLIB::LibcallImpl Impl :
95 {RTLIB::impl_amd_vrd2_sincos, RTLIB::impl_amd_vrd4_sincos,
96 RTLIB::impl_amd_vrd8_sincos, RTLIB::impl_amd_vrs4_sincosf,
97 RTLIB::impl_amd_vrs8_sincosf, RTLIB::impl_amd_vrs16_sincosf})
98 setAvailable(Impl);
99 break;
100 default:
101 break;
102 }
103}
104
105// TODO: Consider the remaining module flags.
106RuntimeLibcallsInfo::RuntimeLibcallsInfo(const Module &M,
107 ExceptionHandling ExceptionModel,
108 EABI EABIVersion, StringRef ABIName,
109 VectorLibrary VecLib)
110 : RuntimeLibcallsInfo(M.getTargetTriple(), ExceptionModel, M.getFloatABI(),
111 EABIVersion, ABIName, VecLib) {}
112
113bool RuntimeLibcallsInfo::isLibraryAvailable(StringRef LibraryName) const {
114 // TODO: Drive this from module-level state (e.g. the linked runtime). For now
115 // every named library is reported as available.
116 return true;
117}
118
119/// Set default libcall names. If a target wants to opt-out of a libcall it
120/// should be placed here.
121void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
122 ExceptionHandling ExceptionModel,
123 FloatABI::ABIType FloatABI,
124 EABI EABIVersion, StringRef ABIName,
125 LongDoubleFormat LongDoubleFormat) {
126 setTargetRuntimeLibcallSets(TT, ExceptionModel, FloatABI, EABIVersion,
127 ABIName, LongDoubleFormat);
128}
129
130LLVM_ATTRIBUTE_ALWAYS_INLINE
131iota_range<RTLIB::LibcallImpl>
132RuntimeLibcallsInfo::libcallImplNameHit(uint16_t NameOffsetEntry,
133 uint16_t StrOffset) {
134 int NumAliases = 1;
135 for (uint16_t Entry : ArrayRef(RuntimeLibcallNameOffsetTable)
136 .drop_front(N: NameOffsetEntry + 1)) {
137 if (Entry != StrOffset)
138 break;
139 ++NumAliases;
140 }
141
142 RTLIB::LibcallImpl ImplStart = static_cast<RTLIB::LibcallImpl>(
143 &RuntimeLibcallNameOffsetTable[NameOffsetEntry] -
144 &RuntimeLibcallNameOffsetTable[0]);
145 return enum_seq(Begin: ImplStart,
146 End: static_cast<RTLIB::LibcallImpl>(ImplStart + NumAliases));
147}
148
149bool RuntimeLibcallsInfo::isAAPCS_ABI(const Triple &TT, StringRef ABIName) {
150 const ARM::ARMABI TargetABI = ARM::computeTargetABI(TT, ABIName);
151 return TargetABI == ARM::ARM_ABI_AAPCS || TargetABI == ARM::ARM_ABI_AAPCS16;
152}
153
154/// TODO: There is really no guarantee that sizeof(size_t) is equal to the index
155/// size of the default address space. This matches TargetLibraryInfo and should
156/// be kept in sync.
157static IntegerType *getSizeTType(LLVMContext &Ctx, const DataLayout &DL) {
158 return DL.getIndexType(C&: Ctx, /*AddressSpace=*/0);
159}
160
161std::pair<FunctionType *, AttributeList>
162RuntimeLibcallsInfo::getFunctionTy(LLVMContext &Ctx, const Triple &TT,
163 const DataLayout &DL,
164 RTLIB::LibcallImpl LibcallImpl) const {
165 // TODO: NoCallback probably unsafe in general
166 static constexpr Attribute::AttrKind CommonFnAttrs[] = {
167 Attribute::NoCallback, Attribute::NoFree, Attribute::NoSync,
168 Attribute::NoUnwind, Attribute::WillReturn};
169 static constexpr Attribute::AttrKind MemoryFnAttrs[] = {
170 Attribute::NoUnwind, Attribute::WillReturn};
171 static constexpr Attribute::AttrKind CommonPtrArgAttrs[] = {
172 Attribute::NoAlias, Attribute::WriteOnly, Attribute::NonNull};
173
174 switch (LibcallImpl) {
175 case RTLIB::impl___sincos_stret:
176 case RTLIB::impl___sincosf_stret: {
177 if (!darwinHasSinCosStret(TT)) // Non-darwin currently unexpected
178 return {};
179
180 Type *ScalarTy = LibcallImpl == RTLIB::impl___sincosf_stret
181 ? Type::getFloatTy(C&: Ctx)
182 : Type::getDoubleTy(C&: Ctx);
183
184 AttrBuilder FuncAttrBuilder(Ctx);
185 for (Attribute::AttrKind Attr : CommonFnAttrs)
186 FuncAttrBuilder.addAttribute(Val: Attr);
187
188 const bool UseSret =
189 TT.isX86_32() || ((TT.isARM() || TT.isThumb()) &&
190 ARM::computeTargetABI(TT) == ARM::ARM_ABI_APCS);
191
192 FuncAttrBuilder.addMemoryAttr(ME: MemoryEffects::argumentOrErrnoMemOnly(
193 ArgMR: UseSret ? ModRefInfo::Mod : ModRefInfo::NoModRef, ErrnoMR: ModRefInfo::Mod));
194
195 AttributeList Attrs;
196 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
197
198 if (UseSret) {
199 AttrBuilder AttrBuilder(Ctx);
200 StructType *StructTy = StructType::get(elt1: ScalarTy, elts: ScalarTy);
201 AttrBuilder.addStructRetAttr(Ty: StructTy);
202 AttrBuilder.addAlignmentAttr(Align: DL.getABITypeAlign(Ty: StructTy));
203 FunctionType *FuncTy = FunctionType::get(
204 Result: Type::getVoidTy(C&: Ctx), Params: {DL.getAllocaPtrType(Ctx), ScalarTy}, isVarArg: false);
205
206 return {FuncTy, Attrs.addParamAttributes(C&: Ctx, ArgNo: 0, B: AttrBuilder)};
207 }
208
209 Type *RetTy =
210 LibcallImpl == RTLIB::impl___sincosf_stret && TT.isX86_64()
211 ? static_cast<Type *>(FixedVectorType::get(ElementType: ScalarTy, NumElts: 2))
212 : static_cast<Type *>(StructType::get(elt1: ScalarTy, elts: ScalarTy));
213
214 return {FunctionType::get(Result: RetTy, Params: {ScalarTy}, isVarArg: false), Attrs};
215 }
216 case RTLIB::impl_malloc:
217 case RTLIB::impl_calloc: {
218 AttrBuilder FuncAttrBuilder(Ctx);
219 for (Attribute::AttrKind Attr : MemoryFnAttrs)
220 FuncAttrBuilder.addAttribute(Val: Attr);
221 FuncAttrBuilder.addAttribute(Val: Attribute::NoFree);
222
223 AllocFnKind AllocKind = AllocFnKind::Alloc;
224 if (LibcallImpl == RTLIB::impl_malloc)
225 AllocKind |= AllocFnKind::Uninitialized;
226
227 // TODO: Set memory attribute
228 FuncAttrBuilder.addAllocKindAttr(Kind: AllocKind);
229 FuncAttrBuilder.addAttribute(A: "alloc-family", V: "malloc");
230 FuncAttrBuilder.addAllocSizeAttr(ElemSizeArg: 0, NumElemsArg: LibcallImpl == RTLIB::impl_malloc
231 ? std::nullopt
232 : std::make_optional(t: 1));
233
234 AttributeList Attrs;
235 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
236
237 {
238 AttrBuilder ArgAttrBuilder(Ctx);
239 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
240 ArgAttrBuilder.addAttribute(Val: AK);
241
242 Attrs = Attrs.addRetAttribute(C&: Ctx, Kind: Attribute::NoUndef);
243 Attrs = Attrs.addRetAttribute(C&: Ctx, Kind: Attribute::NoAlias);
244 Attrs = Attrs.addParamAttribute(C&: Ctx, ArgNo: 0, Kind: Attribute::NoUndef);
245 if (LibcallImpl == RTLIB::impl_calloc)
246 Attrs = Attrs.addParamAttribute(C&: Ctx, ArgNo: 1, Kind: Attribute::NoUndef);
247 }
248
249 IntegerType *SizeT = getSizeTType(Ctx, DL);
250 PointerType *PtrTy = PointerType::get(C&: Ctx, AddressSpace: 0);
251 SmallVector<Type *, 2> ArgTys = {SizeT};
252 if (LibcallImpl == RTLIB::impl_calloc)
253 ArgTys.push_back(Elt: SizeT);
254
255 return {FunctionType::get(Result: PtrTy, Params: ArgTys, isVarArg: false), Attrs};
256 }
257 case RTLIB::impl_free: {
258 // TODO: Set memory attribute
259 AttrBuilder FuncAttrBuilder(Ctx);
260 for (Attribute::AttrKind Attr : MemoryFnAttrs)
261 FuncAttrBuilder.addAttribute(Val: Attr);
262
263 FuncAttrBuilder.addAllocKindAttr(Kind: AllocFnKind::Free);
264 FuncAttrBuilder.addAttribute(A: "alloc-family", V: "malloc");
265
266 AttributeList Attrs;
267 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
268
269 {
270 AttrBuilder ArgAttrBuilder(Ctx);
271 ArgAttrBuilder.addAttribute(Val: Attribute::NoUndef);
272 ArgAttrBuilder.addAttribute(Val: Attribute::AllocatedPointer);
273 ArgAttrBuilder.addCapturesAttr(CI: CaptureInfo::none());
274 Attrs = Attrs.addParamAttributes(C&: Ctx, ArgNo: 0, B: ArgAttrBuilder);
275 }
276
277 return {FunctionType::get(Result: Type::getVoidTy(C&: Ctx), Params: {PointerType::get(C&: Ctx, AddressSpace: 0)},
278 isVarArg: false),
279 Attrs};
280 }
281 case RTLIB::impl_sqrtf:
282 case RTLIB::impl_sqrt: {
283 AttrBuilder FuncAttrBuilder(Ctx);
284
285 for (Attribute::AttrKind Attr : CommonFnAttrs)
286 FuncAttrBuilder.addAttribute(Val: Attr);
287 FuncAttrBuilder.addMemoryAttr(ME: MemoryEffects::errnoMemOnly(MR: ModRefInfo::Mod));
288
289 AttributeList Attrs;
290 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
291
292 Type *ScalarTy = LibcallImpl == RTLIB::impl_sqrtf ? Type::getFloatTy(C&: Ctx)
293 : Type::getDoubleTy(C&: Ctx);
294 FunctionType *FuncTy = FunctionType::get(Result: ScalarTy, Params: {ScalarTy}, isVarArg: false);
295
296 Attrs = Attrs.addRetAttribute(
297 C&: Ctx, Attr: Attribute::getWithNoFPClass(Context&: Ctx, Mask: fcNegInf | fcNegSubnormal |
298 fcNegNormal));
299 return {FuncTy, Attrs};
300 }
301 case RTLIB::impl__ZGVnN2vv_fmod:
302 case RTLIB::impl__ZGVnN4vv_fmodf:
303 case RTLIB::impl__ZGVsMxvv_fmod:
304 case RTLIB::impl__ZGVsMxvv_fmodf:
305 case RTLIB::impl_armpl_vfmodq_f32:
306 case RTLIB::impl_armpl_vfmodq_f64:
307 case RTLIB::impl_armpl_svfmod_f32_x:
308 case RTLIB::impl_armpl_svfmod_f64_x:
309 case RTLIB::impl_armpl_vpowq_f32:
310 case RTLIB::impl_armpl_vpowq_f64:
311 case RTLIB::impl_armpl_svpow_f32_x:
312 case RTLIB::impl_armpl_svpow_f64_x:
313 case RTLIB::impl_armpl_vcbrtq_f32:
314 case RTLIB::impl_armpl_vcbrtq_f64:
315 case RTLIB::impl_armpl_svcbrt_f32_x:
316 case RTLIB::impl_armpl_svcbrt_f64_x: {
317 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vv_fmodf ||
318 LibcallImpl == RTLIB::impl__ZGVsMxvv_fmodf ||
319 LibcallImpl == RTLIB::impl_armpl_svfmod_f32_x ||
320 LibcallImpl == RTLIB::impl_armpl_vfmodq_f32 ||
321 LibcallImpl == RTLIB::impl_armpl_vpowq_f32 ||
322 LibcallImpl == RTLIB::impl_armpl_svpow_f32_x ||
323 LibcallImpl == RTLIB::impl_armpl_vcbrtq_f32 ||
324 LibcallImpl == RTLIB::impl_armpl_svcbrt_f32_x;
325
326 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsMxvv_fmod ||
327 LibcallImpl == RTLIB::impl__ZGVsMxvv_fmodf ||
328 LibcallImpl == RTLIB::impl_armpl_svfmod_f32_x ||
329 LibcallImpl == RTLIB::impl_armpl_svfmod_f64_x ||
330 LibcallImpl == RTLIB::impl_armpl_svpow_f32_x ||
331 LibcallImpl == RTLIB::impl_armpl_svpow_f64_x ||
332 LibcallImpl == RTLIB::impl_armpl_svcbrt_f32_x ||
333 LibcallImpl == RTLIB::impl_armpl_svcbrt_f64_x;
334
335 bool HasOneArg = LibcallImpl == RTLIB::impl_armpl_vcbrtq_f32 ||
336 LibcallImpl == RTLIB::impl_armpl_vcbrtq_f64 ||
337 LibcallImpl == RTLIB::impl_armpl_svcbrt_f32_x ||
338 LibcallImpl == RTLIB::impl_armpl_svcbrt_f64_x;
339
340 AttrBuilder FuncAttrBuilder(Ctx);
341
342 for (Attribute::AttrKind Attr : CommonFnAttrs)
343 FuncAttrBuilder.addAttribute(Val: Attr);
344
345 AttributeList Attrs;
346 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
347
348 Type *ScalarTy = IsF32 ? Type::getFloatTy(C&: Ctx) : Type::getDoubleTy(C&: Ctx);
349 unsigned EC = IsF32 ? 4 : 2;
350 VectorType *VecTy = VectorType::get(ElementType: ScalarTy, NumElements: EC, Scalable: IsScalable);
351
352 SmallVector<Type *, 3> ArgTys(HasOneArg ? 1 : 2, VecTy);
353 if (hasVectorMaskArgument(Impl: LibcallImpl))
354 ArgTys.push_back(Elt: VectorType::get(ElementType: Type::getInt1Ty(C&: Ctx), NumElements: EC, Scalable: IsScalable));
355
356 FunctionType *FuncTy = FunctionType::get(Result: VecTy, Params: ArgTys, isVarArg: false);
357 return {FuncTy, Attrs};
358 }
359 case RTLIB::impl__ZGVnN2vl8_modf:
360 case RTLIB::impl__ZGVnN4vl4_modff:
361 case RTLIB::impl__ZGVsNxvl8_modf:
362 case RTLIB::impl__ZGVsNxvl4_modff:
363 case RTLIB::impl_armpl_vmodfq_f64:
364 case RTLIB::impl_armpl_vmodfq_f32:
365 case RTLIB::impl_armpl_svmodf_f64_x:
366 case RTLIB::impl_armpl_svmodf_f32_x: {
367 AttrBuilder FuncAttrBuilder(Ctx);
368
369 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vl4_modff ||
370 LibcallImpl == RTLIB::impl__ZGVsNxvl4_modff ||
371 LibcallImpl == RTLIB::impl_armpl_vmodfq_f32 ||
372 LibcallImpl == RTLIB::impl_armpl_svmodf_f32_x;
373
374 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsNxvl8_modf ||
375 LibcallImpl == RTLIB::impl__ZGVsNxvl4_modff ||
376 LibcallImpl == RTLIB::impl_armpl_svmodf_f64_x ||
377 LibcallImpl == RTLIB::impl_armpl_svmodf_f32_x;
378
379 Type *ScalarTy = IsF32 ? Type::getFloatTy(C&: Ctx) : Type::getDoubleTy(C&: Ctx);
380 unsigned EC = IsF32 ? 4 : 2;
381 VectorType *VecTy = VectorType::get(ElementType: ScalarTy, NumElements: EC, Scalable: IsScalable);
382
383 for (Attribute::AttrKind Attr : CommonFnAttrs)
384 FuncAttrBuilder.addAttribute(Val: Attr);
385 FuncAttrBuilder.addMemoryAttr(ME: MemoryEffects::argMemOnly(MR: ModRefInfo::Mod));
386
387 AttributeList Attrs;
388 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
389
390 {
391 AttrBuilder ArgAttrBuilder(Ctx);
392 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
393 ArgAttrBuilder.addAttribute(Val: AK);
394 ArgAttrBuilder.addAlignmentAttr(Align: DL.getABITypeAlign(Ty: VecTy));
395 Attrs = Attrs.addParamAttributes(C&: Ctx, ArgNo: 1, B: ArgAttrBuilder);
396 }
397
398 PointerType *PtrTy = PointerType::get(C&: Ctx, AddressSpace: 0);
399 SmallVector<Type *, 4> ArgTys = {VecTy, PtrTy};
400 if (hasVectorMaskArgument(Impl: LibcallImpl))
401 ArgTys.push_back(Elt: VectorType::get(ElementType: Type::getInt1Ty(C&: Ctx), NumElements: EC, Scalable: IsScalable));
402
403 return {FunctionType::get(Result: VecTy, Params: ArgTys, isVarArg: false), Attrs};
404 }
405 case RTLIB::impl__ZGVnN2vl8l8_sincos:
406 case RTLIB::impl__ZGVnN4vl4l4_sincosf:
407 case RTLIB::impl__ZGVsNxvl8l8_sincos:
408 case RTLIB::impl__ZGVsNxvl4l4_sincosf:
409 case RTLIB::impl_armpl_vsincosq_f64:
410 case RTLIB::impl_armpl_vsincosq_f32:
411 case RTLIB::impl_armpl_svsincos_f64_x:
412 case RTLIB::impl_armpl_svsincos_f32_x:
413 case RTLIB::impl__ZGVnN4vl4l4_sincospif:
414 case RTLIB::impl__ZGVnN2vl8l8_sincospi:
415 case RTLIB::impl__ZGVsNxvl4l4_sincospif:
416 case RTLIB::impl__ZGVsNxvl8l8_sincospi:
417 case RTLIB::impl_armpl_vsincospiq_f32:
418 case RTLIB::impl_armpl_vsincospiq_f64:
419 case RTLIB::impl_armpl_svsincospi_f32_x:
420 case RTLIB::impl_armpl_svsincospi_f64_x: {
421 AttrBuilder FuncAttrBuilder(Ctx);
422
423 bool IsF32 = LibcallImpl == RTLIB::impl__ZGVnN4vl4l4_sincospif ||
424 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincospif ||
425 LibcallImpl == RTLIB::impl_armpl_vsincospiq_f32 ||
426 LibcallImpl == RTLIB::impl_armpl_svsincospi_f32_x ||
427 LibcallImpl == RTLIB::impl__ZGVnN4vl4l4_sincosf ||
428 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincosf ||
429 LibcallImpl == RTLIB::impl_armpl_vsincosq_f32 ||
430 LibcallImpl == RTLIB::impl_armpl_svsincos_f32_x;
431
432 Type *ScalarTy = IsF32 ? Type::getFloatTy(C&: Ctx) : Type::getDoubleTy(C&: Ctx);
433 unsigned EC = IsF32 ? 4 : 2;
434
435 bool IsScalable = LibcallImpl == RTLIB::impl__ZGVsNxvl8l8_sincos ||
436 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincosf ||
437 LibcallImpl == RTLIB::impl_armpl_svsincos_f32_x ||
438 LibcallImpl == RTLIB::impl_armpl_svsincos_f64_x ||
439 LibcallImpl == RTLIB::impl__ZGVsNxvl4l4_sincospif ||
440 LibcallImpl == RTLIB::impl__ZGVsNxvl8l8_sincospi ||
441 LibcallImpl == RTLIB::impl_armpl_svsincospi_f32_x ||
442 LibcallImpl == RTLIB::impl_armpl_svsincospi_f64_x;
443 VectorType *VecTy = VectorType::get(ElementType: ScalarTy, NumElements: EC, Scalable: IsScalable);
444
445 for (Attribute::AttrKind Attr : CommonFnAttrs)
446 FuncAttrBuilder.addAttribute(Val: Attr);
447 FuncAttrBuilder.addMemoryAttr(ME: MemoryEffects::argMemOnly(MR: ModRefInfo::Mod));
448
449 AttributeList Attrs;
450 Attrs = Attrs.addFnAttributes(C&: Ctx, B: FuncAttrBuilder);
451
452 {
453 AttrBuilder ArgAttrBuilder(Ctx);
454 for (Attribute::AttrKind AK : CommonPtrArgAttrs)
455 ArgAttrBuilder.addAttribute(Val: AK);
456 ArgAttrBuilder.addAlignmentAttr(Align: DL.getABITypeAlign(Ty: VecTy));
457 Attrs = Attrs.addParamAttributes(C&: Ctx, ArgNo: 1, B: ArgAttrBuilder);
458 Attrs = Attrs.addParamAttributes(C&: Ctx, ArgNo: 2, B: ArgAttrBuilder);
459 }
460
461 PointerType *PtrTy = PointerType::get(C&: Ctx, AddressSpace: 0);
462 SmallVector<Type *, 4> ArgTys = {VecTy, PtrTy, PtrTy};
463 if (hasVectorMaskArgument(Impl: LibcallImpl))
464 ArgTys.push_back(Elt: VectorType::get(ElementType: Type::getInt1Ty(C&: Ctx), NumElements: EC, Scalable: IsScalable));
465
466 return {FunctionType::get(Result: Type::getVoidTy(C&: Ctx), Params: ArgTys, isVarArg: false), Attrs};
467 }
468 default:
469 return {};
470 }
471
472 return {};
473}
474
475bool RuntimeLibcallsInfo::hasVectorMaskArgument(RTLIB::LibcallImpl Impl) {
476 /// FIXME: This should be generated by tablegen and support the argument at an
477 /// arbitrary position
478 switch (Impl) {
479 case RTLIB::impl_armpl_svfmod_f32_x:
480 case RTLIB::impl_armpl_svfmod_f64_x:
481 case RTLIB::impl_armpl_svmodf_f64_x:
482 case RTLIB::impl_armpl_svmodf_f32_x:
483 case RTLIB::impl_armpl_svsincos_f32_x:
484 case RTLIB::impl_armpl_svsincos_f64_x:
485 case RTLIB::impl_armpl_svsincospi_f32_x:
486 case RTLIB::impl_armpl_svsincospi_f64_x:
487 case RTLIB::impl__ZGVsMxvv_fmod:
488 case RTLIB::impl__ZGVsMxvv_fmodf:
489 case RTLIB::impl_armpl_svpow_f32_x:
490 case RTLIB::impl_armpl_svpow_f64_x:
491 case RTLIB::impl_armpl_svcbrt_f32_x:
492 case RTLIB::impl_armpl_svcbrt_f64_x:
493 return true;
494 default:
495 return false;
496 }
497}
498