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