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