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