clang 23.0.0git
CIRGenBuiltinAArch64.cpp
Go to the documentation of this file.
1//===---- CIRGenBuiltinAArch64.cpp - Emit CIR for AArch64 builtins --------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7//
8// This contains code to emit ARM64 Builtin calls as CIR or a function call
9// to be later resolved.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenBuilder.h"
14#include "CIRGenFunction.h"
19
20// TODO(cir): once all builtins are covered, decide whether we still
21// need to use LLVM intrinsics or if there's a better approach to follow. Right
22// now the intrinsics are reused to make it convenient to encode all thousands
23// of them and passing down to LLVM lowering.
24#include "llvm/IR/Intrinsics.h"
25#include "llvm/IR/IntrinsicsAArch64.h"
26
27#include "mlir/IR/BuiltinTypes.h"
28#include "mlir/IR/Value.h"
31
32using namespace clang;
33using namespace clang::CIRGen;
34using namespace llvm;
35using namespace clang::aarch64;
36
37// Generate vscale * scalingFactor
38static mlir::Value genVscaleTimesFactor(mlir::Location loc,
39 CIRGenBuilderTy builder,
40 mlir::Type cirTy,
41 int32_t scalingFactor) {
42 mlir::Value vscale = builder.emitIntrinsicCallOp(loc, "vscale", cirTy);
43 return builder.createNUWAMul(loc, vscale,
44 builder.getUInt64(scalingFactor, loc));
45}
46
47#define SVEMAP1(NameBase, LLVMIntrinsic, TypeModifier) \
48 {SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, TypeModifier}
49
50#define SVEMAP2(NameBase, TypeModifier) \
51 {SVE::BI__builtin_sve_##NameBase, 0, TypeModifier}
53#define GET_SVE_LLVM_INTRINSIC_MAP
54#include "clang/Basic/arm_sve_builtin_cg.inc"
55#undef GET_SVE_LLVM_INTRINSIC_MAP
56};
57
61
62// Check if Builtin `builtinId` is present in `intrinsicMap`. If yes, returns
63// the corresponding info struct.
64template <typename IntrinsicInfo>
65static const IntrinsicInfo *
67 unsigned builtinID, bool &mapProvenSorted) {
68
69#ifndef NDEBUG
70 if (!mapProvenSorted) {
71 assert(llvm::is_sorted(intrinsicMap));
72 mapProvenSorted = true;
73 }
74#endif
75
76 const IntrinsicInfo *info = llvm::lower_bound(intrinsicMap, builtinID);
77
78 if (info != intrinsicMap.end() && info->BuiltinID == builtinID)
79 return info;
80
81 return nullptr;
82}
83
84//===----------------------------------------------------------------------===//
85// Generic helpers
86//===----------------------------------------------------------------------===//
87// Emit an intrinsic where all operands are of the same type as the result.
88// Depending on mode, this may be a constrained floating-point intrinsic.
89static mlir::Value
91 StringRef intrName, mlir::Type retTy,
94
95 return builder.emitIntrinsicCallOp(loc, intrName, retTy, ops);
96}
97
98static llvm::StringRef getLLVMIntrNameNoPrefix(llvm::Intrinsic::ID intrID) {
99 llvm::StringRef llvmIntrName = llvm::Intrinsic::getBaseName(intrID);
100 assert(llvmIntrName.starts_with("llvm.") && "Not an LLVM intrinsic!");
101 return llvmIntrName.drop_front(/*strlen("llvm.")=*/5);
102}
103
104//===----------------------------------------------------------------------===//
105// NEON helpers
106//===----------------------------------------------------------------------===//
107/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
108/// argument that specifies the vector type. The additional argument is meant
109/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function
110/// should be kept consistent with the logic in Sema.
111/// TODO: Make this return false for SISD builtins.
112/// TODO(cir): Share this with ARM.cpp
113static bool hasExtraNeonArgument(unsigned builtinID) {
114 // Required by the headers included below, but not in this particular
115 // function.
116 [[maybe_unused]] int PtrArgNum = -1;
117 [[maybe_unused]] bool HasConstPtr = false;
118
119 // The mask encodes the type. We don't care about the actual value. Instead,
120 // we just check whether its been set.
121 uint64_t mask = 0;
122 switch (builtinID) {
123#define GET_NEON_OVERLOAD_CHECK
124#include "clang/Basic/arm_fp16.inc"
125#include "clang/Basic/arm_neon.inc"
126#undef GET_NEON_OVERLOAD_CHECK
127 // Non-neon builtins for controling VFP that take extra argument for
128 // discriminating the type.
129 case ARM::BI__builtin_arm_vcvtr_f:
130 case ARM::BI__builtin_arm_vcvtr_d:
131 mask = 1;
132 }
133 switch (builtinID) {
134 default:
135 break;
136 }
137
138 return mask != 0;
139}
140
141static cir::VectorType getFloatNeonType(CIRGenFunction &cgf,
142 NeonTypeFlags intTypeFlags) {
143 int isQuad = intTypeFlags.isQuad();
144 switch (intTypeFlags.getEltType()) {
146 return cir::VectorType::get(cgf.fP16Ty, (4 << isQuad));
148 return cir::VectorType::get(cgf.floatTy, (2 << isQuad));
150 return cir::VectorType::get(cgf.doubleTy, (1 << isQuad));
151 default:
152 llvm_unreachable("Type can't be converted to floating-point!");
153 }
154}
155
156static int64_t getIntValueFromConstOp(mlir::Value val) {
157 return val.getDefiningOp<cir::ConstantOp>().getIntValue().getSExtValue();
158}
159
160/// Build a constant shift amount vector of `vecTy` to shift a vector
161/// Here `shiftVal` is a constant integer that will be broadcast into a
162/// a const vector of `vecTy` which is the return value of this function
163/// If `neg` is true, the shift amount is negated before splatting (used
164/// when encoding a right shift as a left shift by a negative amount for
165/// intrinsics like aarch64.neon.{s,u}rshl).
166static mlir::Value emitNeonShiftVector(CIRGenBuilderTy &builder,
167 mlir::Value shiftVal,
168 cir::VectorType vecTy,
169 mlir::Location loc, bool neg) {
170 if (neg) {
171 int64_t shiftAmt = -getIntValueFromConstOp(shiftVal);
172 shiftVal = builder.getConstantInt(loc, vecTy.getElementType(), shiftAmt);
173 }
174 mlir::Type eltTy = vecTy.getElementType();
175 if (shiftVal.getType() != eltTy) {
176 shiftVal = builder.createIntCast(shiftVal, eltTy);
177 }
178 return cir::VecSplatOp::create(builder, loc, vecTy, shiftVal);
179}
180
181// TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.
182template <typename Operation>
183static mlir::Value
187 std::optional<llvm::StringRef> intrinsicName,
188 mlir::Type funcResTy, mlir::Location loc,
189 bool isConstrainedFPIntrinsic = false, unsigned shift = 0,
190 bool rightshift = false) {
191 // TODO(cir): Consider removing the following unreachable when we have
192 // emitConstrainedFPCall feature implemented
194 if (isConstrainedFPIntrinsic)
195 cgm.errorNYI(loc, std::string("constrained FP intrinsic"));
196
197 for (unsigned j = 0; j < argTypes.size(); ++j) {
198 if (isConstrainedFPIntrinsic) {
200 }
201 if (shift > 0 && shift == j) {
202 args[j] = emitNeonShiftVector(builder, args[j],
203 mlir::cast<cir::VectorType>(argTypes[j]),
204 loc, rightshift);
205 } else {
206 args[j] = builder.createBitcast(args[j], argTypes[j]);
207 }
208 }
209 if (isConstrainedFPIntrinsic) {
211 return nullptr;
212 }
213 if constexpr (std::is_same_v<Operation, cir::LLVMIntrinsicCallOp>) {
214 return Operation::create(builder, loc,
215 builder.getStringAttr(intrinsicName.value()),
216 funcResTy, args)
217 .getResult();
218 } else {
219 return Operation::create(builder, loc, funcResTy, args).getResult();
220 }
221}
222
223// TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.
224static mlir::Value emitNeonCall(CIRGenModule &cgm, CIRGenBuilderTy &builder,
227 llvm::StringRef intrinsicName,
228 mlir::Type funcResTy, mlir::Location loc,
229 bool isConstrainedFPIntrinsic = false,
230 unsigned shift = 0, bool rightshift = false) {
232 cgm, builder, std::move(argTypes), args, intrinsicName, funcResTy, loc,
233 isConstrainedFPIntrinsic, shift, rightshift);
234}
235
236// Computes the input vector type for a NEON pairwise widening operation (e.g.
237// vpaddl/vpadal). Given a result vector type, it derives the corresponding
238// input type by halving the element bit width and doubling the number of lanes,
239// while setting the signedness based on usgn.
240static cir::VectorType getNeonPairwiseWidenInputType(cir::VectorType resType,
241 bool usgn) {
242 mlir::Type elemTy = resType.getElementType();
243 uint64_t resLanes = resType.getSize();
244 auto intTy = mlir::dyn_cast<cir::IntType>(elemTy);
245 assert(intTy && "vpaddl result type must be an integer vector");
246
247 unsigned resWidth = intTy.getWidth();
248 assert((resWidth == 16 || resWidth == 32 || resWidth == 64) &&
249 "unexpected vpaddl result element width");
250
251 unsigned argWidth = resWidth / 2;
252 unsigned argLanes = resLanes * 2;
253 cir::VectorType result = cir::VectorType::get(
254 cir::IntType::get(resType.getContext(), argWidth, /* is_signed */ !usgn),
255 argLanes);
256 return result;
257}
258
259// Derive the LLVM intrinsic's per-operand argument types and its result
260// type for use when emitting the intrinsic call.
261//
262// `modifier` is the TypeModifier bitmask from `ARMNeonVectorIntrinsicInfo`
263// (callers pass `info.TypeModifier`; see AArch64CodeGenUtils.h). It encodes
264// how the intrinsic's argument and return types relate to the builtin's
265// scalar types. For SISD builtins the key flags are:
266// - VectorizeArgTypes: wrap each arg type into a fixed-width vector
267// - Use64BitVectors / Use128BitVectors: choose the vector width
268// (when neither is set the vector has 1 element)
269// - AddRetType / VectorizeRetType: analogous flags for the return type
270//
271// ARM.cpp lets LLVM resolve the intrinsic's signature (via
272// `CGM.getIntrinsic`) and then walks the resolved Function* formal
273// parameter types. CIR has no LLVMContext here, so we derive the same
274// argument/result types directly from the Clang operand types.
275static std::pair<mlir::Type, llvm::SmallVector<mlir::Type>>
277 mlir::Type arg0Ty, mlir::Type resultTy,
279 int vectorSize = 0;
280 if (modifier & Use64BitVectors)
281 vectorSize = 64;
282 else if (modifier & Use128BitVectors)
283 vectorSize = 128;
284
285 auto wrapAsVector = [&](mlir::Type ty) -> cir::VectorType {
286 unsigned bits = cgf.cgm.getDataLayout().getTypeSizeInBits(ty);
287 unsigned elts = vectorSize ? vectorSize / bits : 1;
288 return cir::VectorType::get(ty, elts);
289 };
290
291 // Determine the vectorized data type.
292 cir::VectorType vecArgTy;
293 if (modifier & VectorizeArgTypes)
294 vecArgTy = wrapAsVector(arg0Ty);
295
296 // Determine the intrinsic result type: `VectorizeRetType` returns a
297 // vector; otherwise, if data args are vectorized and `AddRetType` is
298 // unset, use a vector return with the same shape as those args.
299 mlir::Type funcResTy = resultTy;
300 if (modifier & VectorizeRetType)
301 funcResTy = wrapAsVector(resultTy);
302 else if (vecArgTy && !(modifier & AddRetType))
303 funcResTy = wrapAsVector(resultTy);
304
305 // When VectorizeArgTypes is set, wrap every operand that has the same
306 // scalar type as arg0 into a vector. This covers intrinsics with multiple
307 // data operands of the same type (e.g. vsri takes two data operands,
308 // both of which must be wrapped into the same vector type).
310 argTypes.reserve(ops.size());
311 for (mlir::Value op : ops) {
312 if ((modifier & VectorizeArgTypes) && vecArgTy && op.getType() == arg0Ty)
313 argTypes.push_back(vecArgTy);
314 else
315 argTypes.push_back(op.getType());
316 }
317
318 return {funcResTy, std::move(argTypes)};
319}
320
324 assert(info.LLVMIntrinsic && "Generic code assumes a valid intrinsic");
325
326 switch (info.BuiltinID) {
327 case NEON::BI__builtin_neon_vcled_s64:
328 case NEON::BI__builtin_neon_vcled_u64:
329 case NEON::BI__builtin_neon_vcles_f32:
330 case NEON::BI__builtin_neon_vcled_f64:
331 case NEON::BI__builtin_neon_vcltd_s64:
332 case NEON::BI__builtin_neon_vcltd_u64:
333 case NEON::BI__builtin_neon_vclts_f32:
334 case NEON::BI__builtin_neon_vcltd_f64:
335 case NEON::BI__builtin_neon_vcales_f32:
336 case NEON::BI__builtin_neon_vcaled_f64:
337 case NEON::BI__builtin_neon_vcalts_f32:
338 case NEON::BI__builtin_neon_vcaltd_f64:
339 cgf.cgm.errorNYI(expr->getSourceRange(),
340 std::string("unimplemented AArch64 builtin call: ") +
342 break;
343 }
344
345 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
346 static_cast<llvm::Intrinsic::ID>(info.LLVMIntrinsic));
347 mlir::Location loc = cgf.getLoc(expr->getExprLoc());
348
349 // The switch stmt is intended to help catch NYI cases and will be removed
350 // once the CIR implementation is complete. Avoid adding specialized
351 // code in cases - that should only be required for a handful of examples.
352 switch (info.BuiltinID) {
353 default:
354 cgf.cgm.errorNYI(expr->getSourceRange(),
355 std::string("unimplemented AArch64 builtin call: ") +
357 break;
358 case NEON::BI__builtin_neon_vminv_s8:
359 case NEON::BI__builtin_neon_vminvq_s8:
360 case NEON::BI__builtin_neon_vminv_s16:
361 case NEON::BI__builtin_neon_vminvq_s16:
362 case NEON::BI__builtin_neon_vminv_s32:
363 case NEON::BI__builtin_neon_vminvq_s32:
364 case NEON::BI__builtin_neon_vminv_u8:
365 case NEON::BI__builtin_neon_vminvq_u8:
366 case NEON::BI__builtin_neon_vminv_u16:
367 case NEON::BI__builtin_neon_vminvq_u16:
368 case NEON::BI__builtin_neon_vminv_u32:
369 case NEON::BI__builtin_neon_vminvq_u32:
370 case NEON::BI__builtin_neon_vminv_f32:
371 case NEON::BI__builtin_neon_vminvq_f32:
372 case NEON::BI__builtin_neon_vminvq_f64:
373 case NEON::BI__builtin_neon_vminnmv_f32:
374 case NEON::BI__builtin_neon_vminnmvq_f32:
375 case NEON::BI__builtin_neon_vminnmvq_f64:
376 case NEON::BI__builtin_neon_vabdd_f64:
377 case NEON::BI__builtin_neon_vabds_f32:
378 case NEON::BI__builtin_neon_vshld_s64:
379 case NEON::BI__builtin_neon_vshld_u64:
380 case NEON::BI__builtin_neon_vpmins_f32:
381 case NEON::BI__builtin_neon_vpminqd_f64:
382 case NEON::BI__builtin_neon_vpminnms_f32:
383 case NEON::BI__builtin_neon_vpminnmqd_f64:
384 case NEON::BI__builtin_neon_vcvts_n_f32_s32:
385 case NEON::BI__builtin_neon_vcvts_n_f32_u32:
386 case NEON::BI__builtin_neon_vcvts_n_s32_f32:
387 case NEON::BI__builtin_neon_vcvts_n_u32_f32:
388 case NEON::BI__builtin_neon_vcvtd_n_f64_s64:
389 case NEON::BI__builtin_neon_vcvtd_n_f64_u64:
390 case NEON::BI__builtin_neon_vcvtd_n_s64_f64:
391 case NEON::BI__builtin_neon_vcvtd_n_u64_f64:
392 case NEON::BI__builtin_neon_vaddlv_s32:
393 case NEON::BI__builtin_neon_vaddlv_u32:
394 case NEON::BI__builtin_neon_vaddlvq_s32:
395 case NEON::BI__builtin_neon_vaddlvq_u32:
396 case NEON::BI__builtin_neon_vaddv_s8:
397 case NEON::BI__builtin_neon_vaddv_s16:
398 case NEON::BI__builtin_neon_vaddv_s32:
399 case NEON::BI__builtin_neon_vaddv_u8:
400 case NEON::BI__builtin_neon_vaddv_u16:
401 case NEON::BI__builtin_neon_vaddv_u32:
402 case NEON::BI__builtin_neon_vaddv_f32:
403 case NEON::BI__builtin_neon_vaddvq_s8:
404 case NEON::BI__builtin_neon_vaddvq_s16:
405 case NEON::BI__builtin_neon_vaddvq_s32:
406 case NEON::BI__builtin_neon_vaddvq_s64:
407 case NEON::BI__builtin_neon_vaddvq_u8:
408 case NEON::BI__builtin_neon_vaddvq_u16:
409 case NEON::BI__builtin_neon_vaddvq_u32:
410 case NEON::BI__builtin_neon_vaddvq_u64:
411 case NEON::BI__builtin_neon_vaddvq_f32:
412 case NEON::BI__builtin_neon_vaddvq_f64:
413 case NEON::BI__builtin_neon_vabdh_f16:
414 case NEON::BI__builtin_neon_vrecpeh_f16:
415 case NEON::BI__builtin_neon_vrecpxh_f16:
416 case NEON::BI__builtin_neon_vrsqrteh_f16:
417 case NEON::BI__builtin_neon_vrsqrtsh_f16:
418 case NEON::BI__builtin_neon_vmaxv_s8:
419 case NEON::BI__builtin_neon_vmaxvq_s8:
420 case NEON::BI__builtin_neon_vmaxv_s16:
421 case NEON::BI__builtin_neon_vmaxvq_s16:
422 case NEON::BI__builtin_neon_vmaxv_s32:
423 case NEON::BI__builtin_neon_vmaxvq_s32:
424 case NEON::BI__builtin_neon_vmaxv_u8:
425 case NEON::BI__builtin_neon_vmaxvq_u8:
426 case NEON::BI__builtin_neon_vmaxv_u16:
427 case NEON::BI__builtin_neon_vmaxvq_u16:
428 case NEON::BI__builtin_neon_vmaxv_u32:
429 case NEON::BI__builtin_neon_vmaxvq_u32:
430 case NEON::BI__builtin_neon_vmaxv_f32:
431 case NEON::BI__builtin_neon_vmaxvq_f32:
432 case NEON::BI__builtin_neon_vmaxvq_f64:
433 case NEON::BI__builtin_neon_vqrshrund_n_s64:
434 case NEON::BI__builtin_neon_vqrshrnd_n_s64:
435 case NEON::BI__builtin_neon_vqrshrnd_n_u64:
436 case NEON::BI__builtin_neon_vmaxnmv_f32:
437 case NEON::BI__builtin_neon_vmaxnmvq_f32:
438 case NEON::BI__builtin_neon_vmaxnmvq_f64:
439 case NEON::BI__builtin_neon_vsrid_n_s64:
440 case NEON::BI__builtin_neon_vsrid_n_u64:
441 case NEON::BI__builtin_neon_vslid_n_s64:
442 case NEON::BI__builtin_neon_vslid_n_u64:
443 case NEON::BI__builtin_neon_vpmaxs_f32:
444 case NEON::BI__builtin_neon_vpmaxqd_f64:
445 case NEON::BI__builtin_neon_vpmaxnms_f32:
446 case NEON::BI__builtin_neon_vpmaxnmqd_f64:
447 break;
448 }
449
450 CIRGenBuilderTy &builder = cgf.getBuilder();
451 mlir::Type arg0Ty = cgf.convertType(expr->getArg(0)->getType());
452 mlir::Type resultTy = cgf.convertType(expr->getType());
453
454 // Derive per-operand argument types and the result type from the
455 // TypeModifier flags. `emitNeonCall` takes care of per-operand
456 // bitcasts to `argTypes`.
457 auto [funcResTy, argTypes] = deriveNeonSISDIntrinsicOperandTypes(
458 cgf, info.TypeModifier, arg0Ty, resultTy, ops);
459
460 return emitNeonCall(cgf.cgm, builder, std::move(argTypes), ops, llvmIntrName,
461 funcResTy, loc);
462}
463
464//===----------------------------------------------------------------------===//
465// Emit-helpers
466//===----------------------------------------------------------------------===//
467static mlir::Value
469 mlir::Location loc, mlir::Value src,
470 mlir::Type retTy, const cir::CmpOpKind kind) {
471
472 bool scalarCmp = !isa<cir::VectorType>(src.getType());
473 if (!scalarCmp) {
474 assert(!cast<cir::VectorType>(retTy).getIsScalable() &&
475 "This is only intended for fixed-width vectors");
476 // Vector types are cast to i8 vectors. Recover original type.
477 src = builder.createBitcast(src, retTy);
478 }
479
480 mlir::Value zero = builder.getNullValue(src.getType(), loc);
481
482 if (!scalarCmp)
483 return builder.createVecCompare(loc, kind, src, zero);
484
485 // For scalars, cast !cir.bool to !cir.int<s, 1> so that the compare
486 // result is sign- rather zero-extended when casting to the output
487 // retType.
488 mlir::Value cmp = builder.createCast(
489 loc, cir::CastKind::bool_to_int,
490 builder.createCompare(loc, kind, src, zero), builder.getSIntNTy(1));
491
492 return builder.createCast(loc, cir::CastKind::integral, cmp, retTy);
493}
494
495// TODO(cir): Remove `loc` from the list of arguments once all NYIs are gone.
496static cir::VectorType getNeonType(CIRGenFunction *cgf, NeonTypeFlags typeFlags,
497 mlir::Location loc,
498 bool hasLegalHalfType = true,
499 bool v1Ty = false,
500 bool allowBFloatArgsAndRet = true) {
501 int isQuad = typeFlags.isQuad();
502 switch (typeFlags.getEltType()) {
505 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt8Ty
506 : cgf->sInt8Ty,
507 v1Ty ? 1 : (8 << isQuad));
509 return cir::VectorType::get(cgf->uInt8Ty, v1Ty ? 1 : (8 << isQuad));
512 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt16Ty
513 : cgf->sInt16Ty,
514 v1Ty ? 1 : (4 << isQuad));
516 if (allowBFloatArgsAndRet)
517 return cir::VectorType::get(cgf->getCIRGenModule().bFloat16Ty,
518 v1Ty ? 1 : (4 << isQuad));
519 return cir::VectorType::get(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad));
521 if (hasLegalHalfType)
522 return cir::VectorType::get(cgf->getCIRGenModule().fP16Ty,
523 v1Ty ? 1 : (4 << isQuad));
524 return cir::VectorType::get(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad));
526 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt32Ty
527 : cgf->sInt32Ty,
528 v1Ty ? 1 : (2 << isQuad));
531 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt64Ty
532 : cgf->sInt64Ty,
533 v1Ty ? 1 : (1 << isQuad));
535 // FIXME: i128 and f128 doesn't get fully support in Clang and llvm.
536 // There is a lot of i128 and f128 API missing.
537 // so we use v16i8 to represent poly128 and get pattern matched.
538 cgf->getCIRGenModule().errorNYI(loc, std::string("NEON type: Poly128"));
539 [[fallthrough]];
541 return cir::VectorType::get(cgf->getCIRGenModule().floatTy,
542 v1Ty ? 1 : (2 << isQuad));
544 return cir::VectorType::get(cgf->getCIRGenModule().doubleTy,
545 v1Ty ? 1 : (1 << isQuad));
546 }
547 llvm_unreachable("Unknown vector element type!");
548}
549
550static mlir::Value emitNeonSplat(CIRGenBuilderTy &builder, mlir::Location loc,
551 mlir::Value v, mlir::Value lane,
552 unsigned int resEltCnt) {
553 assert(isa<cir::ConstantOp>(lane.getDefiningOp()) &&
554 "lane number is not a constant!");
555 int64_t laneCst = getIntValueFromConstOp(lane);
556 llvm::SmallVector<int64_t, 4> shuffleMask(resEltCnt, laneCst);
557 return builder.createVecShuffle(loc, v, shuffleMask);
558}
559
560/// Flip the signedness of `vecTy`'s element type, keeping the width and
561/// number of lanes the same. Used when a NEON intrinsic takes a shift
562/// amount vector that must be signed (e.g. aarch64.neon.urshl takes a
563/// signed amount even though the data vector is unsigned).
564static cir::VectorType getSignChangedVectorType(CIRGenBuilderTy &builder,
565 cir::VectorType vecTy) {
566 auto elemTy = mlir::cast<cir::IntType>(vecTy.getElementType());
567 elemTy = elemTy.isSigned() ? builder.getUIntNTy(elemTy.getWidth())
568 : builder.getSIntNTy(elemTy.getWidth());
569 return cir::VectorType::get(elemTy, vecTy.getSize());
570}
571
572static mlir::Value emitCommonNeonShift(CIRGenBuilderTy &builder,
573 mlir::Location loc,
574 cir::VectorType resTy,
575 mlir::Value shifTgt,
576 mlir::Value shiftAmt, bool shiftLeft) {
577 shiftAmt = emitNeonShiftVector(builder, shiftAmt, resTy, loc, /*neg=*/false);
578 return cir::ShiftOp::create(builder, loc, resTy,
579 builder.createBitcast(shifTgt, resTy), shiftAmt,
580 shiftLeft);
581}
582
583// Right-shift a vector by a constant.
584static mlir::Value emitNeonRShiftImm(CIRGenFunction &cgf, mlir::Value shiftVec,
585 mlir::Value shiftVal,
586 cir::VectorType vecTy, bool usgn,
587 mlir::Location loc) {
588 CIRGenBuilderTy &builder = cgf.getBuilder();
589 int64_t shiftAmt = getIntValueFromConstOp(shiftVal);
590 int eltSize =
591 cgf.cgm.getDataLayout().getTypeSizeInBits(vecTy.getElementType());
592
593 shiftVec = builder.createBitcast(shiftVec, vecTy);
594 // lshr/ashr are undefined when the shift amount is equal to the vector
595 // element size.
596 if (shiftAmt == eltSize) {
597 if (usgn) {
598 // Right-shifting an unsigned value by its size yields 0.
599 return builder.getZero(loc, vecTy);
600 }
601 // Right-shifting a signed value by its size is equivalent
602 // to a shift of size-1.
603 --shiftAmt;
604 shiftVal = builder.getConstInt(loc, vecTy.getElementType(), shiftAmt);
605 }
606 return emitCommonNeonShift(builder, loc, vecTy, shiftVec, shiftVal,
607 /*shiftLeft=*/false);
608}
609
610static cir::VectorType getIntVecFromVecTy(CIRGenBuilderTy &builder,
611 cir::VectorType vecTy) {
612 if (!cir::isAnyFloatingPointType(vecTy.getElementType()))
613 return vecTy;
614
615 if (mlir::isa<cir::SingleType>(vecTy.getElementType()))
616 return cir::VectorType::get(builder.getSInt32Ty(), vecTy.getSize());
617 if (mlir::isa<cir::DoubleType>(vecTy.getElementType()))
618 return cir::VectorType::get(builder.getSInt64Ty(), vecTy.getSize());
619 llvm_unreachable(
620 "Unsupported element type in getVecOfIntTypeWithSameEltWidth");
621}
622
623static mlir::Value emitCommonNeonBuiltinExpr(
624 CIRGenFunction &cgf, unsigned builtinID, unsigned llvmIntrinsic,
625 unsigned altLLVMIntrinsic, const char *nameHint, unsigned modifier,
627 mlir::Location loc = cgf.getLoc(expr->getExprLoc());
628 clang::ASTContext &ctx = cgf.getContext();
629
630 // Extract the trailing immediate argument that encodes the type discriminator
631 // for this overloaded intrinsic.
632 // TODO: Move to the parent code that takes care of argument processing.
633 const clang::Expr *arg = expr->getArg(expr->getNumArgs() - 1);
634 std::optional<llvm::APSInt> neonTypeConst = arg->getIntegerConstantExpr(ctx);
635 if (!neonTypeConst)
636 return nullptr;
637
638 // Determine the type of this overloaded NEON intrinsic.
639 NeonTypeFlags neonType(neonTypeConst->getZExtValue());
640 const bool isUnsigned = neonType.isUnsigned();
641 const bool hasLegalHalfType = cgf.getTarget().hasFastHalfType();
642 const bool usgn = neonType.isUnsigned();
643
644 // The value of allowBFloatArgsAndRet is true for AArch64, but it should
645 // come from ABI info.
646 // TODO(cir): Use ABInfo to extract this information
647 const bool allowBFloatArgsAndRet = cgf.getTarget().hasFastHalfType();
648 // FIXME
649 // getTargetHooks().getABIInfo().allowBFloatArgsAndRet();
650
651 cir::VectorType vTy = getNeonType(&cgf, neonType, loc, hasLegalHalfType,
652 false, allowBFloatArgsAndRet);
653 cir::VectorType ty = vTy;
654 if (!ty)
655 return nullptr;
656
657 switch (builtinID) {
658 case NEON::BI__builtin_neon_splat_lane_v:
659 case NEON::BI__builtin_neon_splat_laneq_v:
660 case NEON::BI__builtin_neon_splatq_lane_v:
661 case NEON::BI__builtin_neon_splatq_laneq_v: {
662 uint64_t numElements = vTy.getSize();
663 if (builtinID == NEON::BI__builtin_neon_splatq_lane_v)
664 numElements *= 2;
665 if (builtinID == NEON::BI__builtin_neon_splat_laneq_v)
666 numElements /= 2;
667 ops[0] = cgf.getBuilder().createBitcast(loc, ops[0], vTy);
668 return emitNeonSplat(cgf.getBuilder(), loc, ops[0], ops[1], numElements);
669 }
670 case NEON::BI__builtin_neon_vpadd_v:
671 case NEON::BI__builtin_neon_vpaddq_v:
672 case NEON::BI__builtin_neon_vabs_v:
673 case NEON::BI__builtin_neon_vabsq_v:
674 cgf.cgm.errorNYI(expr->getSourceRange(),
675 std::string("unimplemented AArch64 builtin call: ") +
676 ctx.BuiltinInfo.getName(builtinID));
677 return mlir::Value{};
678 case NEON::BI__builtin_neon_vadd_v:
679 case NEON::BI__builtin_neon_vaddq_v: {
680 unsigned numBytes = (builtinID == NEON::BI__builtin_neon_vaddq_v) ? 16 : 8;
681 cir::VectorType byteTy =
682 cir::VectorType::get(cgf.getBuilder().getUInt8Ty(), numBytes);
683 ops[0] = cgf.getBuilder().createBitcast(ops[0], byteTy);
684 ops[1] = cgf.getBuilder().createBitcast(ops[1], byteTy);
685 mlir::Value result = cgf.getBuilder().createXor(loc, ops[0], ops[1]);
686 return cgf.getBuilder().createBitcast(result, ty);
687 }
688 case NEON::BI__builtin_neon_vaddhn_v:
689 case NEON::BI__builtin_neon_vcale_v:
690 case NEON::BI__builtin_neon_vcaleq_v:
691 case NEON::BI__builtin_neon_vcalt_v:
692 case NEON::BI__builtin_neon_vcaltq_v:
693 case NEON::BI__builtin_neon_vcage_v:
694 case NEON::BI__builtin_neon_vcageq_v:
695 case NEON::BI__builtin_neon_vcagt_v:
696 case NEON::BI__builtin_neon_vcagtq_v:
697 cgf.cgm.errorNYI(expr->getSourceRange(),
698 std::string("unimplemented AArch64 builtin call: ") +
699 ctx.BuiltinInfo.getName(builtinID));
700 return mlir::Value{};
701 case NEON::BI__builtin_neon_vceqz_v:
702 case NEON::BI__builtin_neon_vceqzq_v:
703 return emitAArch64CompareBuiltinExpr(cgf, cgf.getBuilder(), loc, ops[0],
704 vTy, cir::CmpOpKind::eq);
705 case NEON::BI__builtin_neon_vcgez_v:
706 case NEON::BI__builtin_neon_vcgezq_v:
707 case NEON::BI__builtin_neon_vclez_v:
708 case NEON::BI__builtin_neon_vclezq_v:
709 case NEON::BI__builtin_neon_vcgtz_v:
710 case NEON::BI__builtin_neon_vcgtzq_v:
711 case NEON::BI__builtin_neon_vcltz_v:
712 case NEON::BI__builtin_neon_vcltzq_v:
713 case NEON::BI__builtin_neon_vclz_v:
714 case NEON::BI__builtin_neon_vclzq_v:
715 case NEON::BI__builtin_neon_vcvt_f32_v:
716 case NEON::BI__builtin_neon_vcvtq_f32_v:
717 case NEON::BI__builtin_neon_vcvt_f16_s16:
718 case NEON::BI__builtin_neon_vcvt_f16_u16:
719 case NEON::BI__builtin_neon_vcvtq_f16_s16:
720 case NEON::BI__builtin_neon_vcvtq_f16_u16:
721 case NEON::BI__builtin_neon_vcvt_n_f16_s16:
722 case NEON::BI__builtin_neon_vcvt_n_f16_u16:
723 case NEON::BI__builtin_neon_vcvtq_n_f16_s16:
724 case NEON::BI__builtin_neon_vcvtq_n_f16_u16:
725 cgf.cgm.errorNYI(expr->getSourceRange(),
726 std::string("unimplemented AArch64 builtin call: ") +
727 ctx.BuiltinInfo.getName(builtinID));
728 return mlir::Value{};
729 case NEON::BI__builtin_neon_vcvt_n_f32_v:
730 case NEON::BI__builtin_neon_vcvt_n_f64_v:
731 case NEON::BI__builtin_neon_vcvtq_n_f32_v:
732 case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
733 // The constant argument to an _n_ intrinsic always is Int32Ty.
734 mlir::Type cstIntTy = cgf.sInt32Ty;
735 llvm::StringRef llvmIntrName =
736 getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(
737 usgn ? llvmIntrinsic : altLLVMIntrinsic));
738 return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(),
739 /*argTypes=*/{vTy, cstIntTy}, ops, llvmIntrName,
740 /*funcResTy=*/getFloatNeonType(cgf, neonType), loc);
741 }
742 case NEON::BI__builtin_neon_vcvt_n_s16_f16:
743 case NEON::BI__builtin_neon_vcvt_n_s32_v:
744 case NEON::BI__builtin_neon_vcvt_n_u16_f16:
745 case NEON::BI__builtin_neon_vcvt_n_u32_v:
746 case NEON::BI__builtin_neon_vcvt_n_s64_v:
747 case NEON::BI__builtin_neon_vcvt_n_u64_v:
748 case NEON::BI__builtin_neon_vcvtq_n_s16_f16:
749 case NEON::BI__builtin_neon_vcvtq_n_s32_v:
750 case NEON::BI__builtin_neon_vcvtq_n_u16_f16:
751 case NEON::BI__builtin_neon_vcvtq_n_u32_v:
752 case NEON::BI__builtin_neon_vcvtq_n_s64_v:
753 case NEON::BI__builtin_neon_vcvtq_n_u64_v: {
754 // The constant argument to an _n_ intrinsic always is Int32Ty.
755 mlir::Type cstIntTy = cgf.sInt32Ty;
756 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
757 static_cast<llvm::Intrinsic::ID>(llvmIntrinsic));
758 return emitNeonCall(
759 cgf.getCIRGenModule(), cgf.getBuilder(),
760 /*argTypes=*/{getFloatNeonType(cgf, neonType), cstIntTy}, ops,
761 llvmIntrName,
762 /*funcResTy=*/vTy, loc);
763 }
764 case NEON::BI__builtin_neon_vcvt_s32_v:
765 case NEON::BI__builtin_neon_vcvt_u32_v:
766 case NEON::BI__builtin_neon_vcvt_s64_v:
767 case NEON::BI__builtin_neon_vcvt_u64_v:
768 case NEON::BI__builtin_neon_vcvt_s16_f16:
769 case NEON::BI__builtin_neon_vcvt_u16_f16:
770 case NEON::BI__builtin_neon_vcvtq_s32_v:
771 case NEON::BI__builtin_neon_vcvtq_u32_v:
772 case NEON::BI__builtin_neon_vcvtq_s64_v:
773 case NEON::BI__builtin_neon_vcvtq_u64_v:
774 case NEON::BI__builtin_neon_vcvtq_s16_f16:
775 case NEON::BI__builtin_neon_vcvtq_u16_f16: {
776 auto ty = getFloatNeonType(cgf, neonType);
777 // Undo the bitcast inserted by intrinsics that expand to this builtin
778 // (e.g. vcvt_u32_f32).
779 // TODO: While the bitcasts eventually cancel each other out, we should
780 // avoid them altogether.
781 ops[0] =
782 cgf.getBuilder().createCast(loc, cir::CastKind::bitcast, ops[0], ty);
784 // AArch64: use fptosi.sat/fptoui.sat unless under strict FP.
785 llvm::StringRef llvmIntrName = usgn ? "fptoui.sat" : "fptosi.sat";
786 return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(),
787 /*argTypes=*/{ty}, ops, llvmIntrName, vTy, loc);
788 }
789 case NEON::BI__builtin_neon_vcvta_s16_f16:
790 case NEON::BI__builtin_neon_vcvta_s32_v:
791 case NEON::BI__builtin_neon_vcvta_s64_v:
792 case NEON::BI__builtin_neon_vcvta_u16_f16:
793 case NEON::BI__builtin_neon_vcvta_u32_v:
794 case NEON::BI__builtin_neon_vcvta_u64_v:
795 case NEON::BI__builtin_neon_vcvtaq_s16_f16:
796 case NEON::BI__builtin_neon_vcvtaq_s32_v:
797 case NEON::BI__builtin_neon_vcvtaq_s64_v:
798 case NEON::BI__builtin_neon_vcvtaq_u16_f16:
799 case NEON::BI__builtin_neon_vcvtaq_u32_v:
800 case NEON::BI__builtin_neon_vcvtaq_u64_v:
801 case NEON::BI__builtin_neon_vcvtn_s16_f16:
802 case NEON::BI__builtin_neon_vcvtn_s32_v:
803 case NEON::BI__builtin_neon_vcvtn_s64_v:
804 case NEON::BI__builtin_neon_vcvtn_u16_f16:
805 case NEON::BI__builtin_neon_vcvtn_u32_v:
806 case NEON::BI__builtin_neon_vcvtn_u64_v:
807 case NEON::BI__builtin_neon_vcvtnq_s16_f16:
808 case NEON::BI__builtin_neon_vcvtnq_s32_v:
809 case NEON::BI__builtin_neon_vcvtnq_s64_v:
810 case NEON::BI__builtin_neon_vcvtnq_u16_f16:
811 case NEON::BI__builtin_neon_vcvtnq_u32_v:
812 case NEON::BI__builtin_neon_vcvtnq_u64_v:
813 case NEON::BI__builtin_neon_vcvtp_s16_f16:
814 case NEON::BI__builtin_neon_vcvtp_s32_v:
815 case NEON::BI__builtin_neon_vcvtp_s64_v:
816 case NEON::BI__builtin_neon_vcvtp_u16_f16:
817 case NEON::BI__builtin_neon_vcvtp_u32_v:
818 case NEON::BI__builtin_neon_vcvtp_u64_v:
819 case NEON::BI__builtin_neon_vcvtpq_s16_f16:
820 case NEON::BI__builtin_neon_vcvtpq_s32_v:
821 case NEON::BI__builtin_neon_vcvtpq_s64_v:
822 case NEON::BI__builtin_neon_vcvtpq_u16_f16:
823 case NEON::BI__builtin_neon_vcvtpq_u32_v:
824 case NEON::BI__builtin_neon_vcvtpq_u64_v:
825 case NEON::BI__builtin_neon_vcvtm_s16_f16:
826 case NEON::BI__builtin_neon_vcvtm_s32_v:
827 case NEON::BI__builtin_neon_vcvtm_s64_v:
828 case NEON::BI__builtin_neon_vcvtm_u16_f16:
829 case NEON::BI__builtin_neon_vcvtm_u32_v:
830 case NEON::BI__builtin_neon_vcvtm_u64_v:
831 case NEON::BI__builtin_neon_vcvtmq_s16_f16:
832 case NEON::BI__builtin_neon_vcvtmq_s32_v:
833 case NEON::BI__builtin_neon_vcvtmq_s64_v:
834 case NEON::BI__builtin_neon_vcvtmq_u16_f16:
835 case NEON::BI__builtin_neon_vcvtmq_u32_v:
836 case NEON::BI__builtin_neon_vcvtmq_u64_v:
837 case NEON::BI__builtin_neon_vcvtx_f32_v:
838 case NEON::BI__builtin_neon_vext_v:
839 case NEON::BI__builtin_neon_vextq_v:
840 case NEON::BI__builtin_neon_vfma_v:
841 cgf.cgm.errorNYI(expr->getSourceRange(),
842 std::string("unimplemented AArch64 builtin call: ") +
843 ctx.BuiltinInfo.getName(builtinID));
844 return mlir::Value{};
845 case NEON::BI__builtin_neon_vfmaq_v: {
846 // NEON intrinsic: vfmaq(accumulator, multiplicand1, multiplicand2)
847 // LLVM intrinsic: fma(multiplicand1, multiplicand2, accumulator)
848 // Reorder arguments to match LLVM fma signature
849 mlir::Value op0 = cgf.getBuilder().createBitcast(ops[0], ty);
850 mlir::Value op1 = cgf.getBuilder().createBitcast(ops[1], ty);
851 mlir::Value op2 = cgf.getBuilder().createBitcast(ops[2], ty);
852 llvm::SmallVector<mlir::Value> fmaOps = {op1, op2, op0};
853 return emitCallMaybeConstrainedBuiltin(cgf.getBuilder(), loc, "fma", ty,
854 fmaOps);
855 }
856 case NEON::BI__builtin_neon_vld1_v:
857 case NEON::BI__builtin_neon_vld1q_v:
858 case NEON::BI__builtin_neon_vld1_x2_v:
859 case NEON::BI__builtin_neon_vld1q_x2_v:
860 case NEON::BI__builtin_neon_vld1_x3_v:
861 case NEON::BI__builtin_neon_vld1q_x3_v:
862 case NEON::BI__builtin_neon_vld1_x4_v:
863 case NEON::BI__builtin_neon_vld1q_x4_v:
864 case NEON::BI__builtin_neon_vld2_v:
865 case NEON::BI__builtin_neon_vld2q_v:
866 case NEON::BI__builtin_neon_vld3_v:
867 case NEON::BI__builtin_neon_vld3q_v:
868 case NEON::BI__builtin_neon_vld4_v:
869 case NEON::BI__builtin_neon_vld4q_v:
870 case NEON::BI__builtin_neon_vld2_dup_v:
871 case NEON::BI__builtin_neon_vld2q_dup_v:
872 case NEON::BI__builtin_neon_vld3_dup_v:
873 case NEON::BI__builtin_neon_vld3q_dup_v:
874 case NEON::BI__builtin_neon_vld4_dup_v:
875 case NEON::BI__builtin_neon_vld4q_dup_v:
876 case NEON::BI__builtin_neon_vld1_dup_v:
877 case NEON::BI__builtin_neon_vld1q_dup_v:
878 case NEON::BI__builtin_neon_vld2_lane_v:
879 case NEON::BI__builtin_neon_vld2q_lane_v:
880 case NEON::BI__builtin_neon_vld3_lane_v:
881 case NEON::BI__builtin_neon_vld3q_lane_v:
882 case NEON::BI__builtin_neon_vld4_lane_v:
883 case NEON::BI__builtin_neon_vld4q_lane_v:
884 cgf.cgm.errorNYI(expr->getSourceRange(),
885 std::string("Reached code-path for ARM builtin call ") +
886 ctx.BuiltinInfo.getName(builtinID) +
887 "(ARM builtins are not supported ATM)");
888 return mlir::Value{};
889 case NEON::BI__builtin_neon_vmovl_v: {
890 cir::VectorType dTy =
892 ty, /*isExtended=*/false, !usgn);
893 ops[0] = cgf.getBuilder().createBitcast(loc, ops[0], dTy);
894 return cgf.getBuilder().createIntCast(ops[0], ty);
895 }
896 case NEON::BI__builtin_neon_vmovn_v:
897 case NEON::BI__builtin_neon_vmull_v:
898 case NEON::BI__builtin_neon_vpadal_v:
899 case NEON::BI__builtin_neon_vpadalq_v:
900 cgf.cgm.errorNYI(expr->getSourceRange(),
901 std::string("Reached code-path for ARM builtin call ") +
902 ctx.BuiltinInfo.getName(builtinID) +
903 "(ARM builtins are not supported ATM)");
904 return mlir::Value{};
905 case NEON::BI__builtin_neon_vpaddl_v:
906 case NEON::BI__builtin_neon_vpaddlq_v: {
907 llvm::StringRef llvmIntrName =
908 getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(
909 usgn ? llvmIntrinsic : altLLVMIntrinsic));
910 return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(),
911 /*argTypes=*/{getNeonPairwiseWidenInputType(vTy, usgn)},
912 ops, llvmIntrName,
913 /*funcResTy=*/vTy, loc);
914 }
915 case NEON::BI__builtin_neon_vqdmlal_v:
916 case NEON::BI__builtin_neon_vqdmlsl_v:
917 case NEON::BI__builtin_neon_vqdmulhq_lane_v:
918 case NEON::BI__builtin_neon_vqdmulh_lane_v:
919 case NEON::BI__builtin_neon_vqrdmulhq_lane_v:
920 case NEON::BI__builtin_neon_vqrdmulh_lane_v:
921 case NEON::BI__builtin_neon_vqdmulhq_laneq_v:
922 case NEON::BI__builtin_neon_vqdmulh_laneq_v:
923 case NEON::BI__builtin_neon_vqrdmulhq_laneq_v:
924 case NEON::BI__builtin_neon_vqrdmulh_laneq_v:
925 case NEON::BI__builtin_neon_vqshl_n_v:
926 case NEON::BI__builtin_neon_vqshlq_n_v:
927 case NEON::BI__builtin_neon_vqshlu_n_v:
928 case NEON::BI__builtin_neon_vqshluq_n_v:
929 case NEON::BI__builtin_neon_vrecpe_v:
930 case NEON::BI__builtin_neon_vrecpeq_v:
931 case NEON::BI__builtin_neon_vrsqrte_v:
932 case NEON::BI__builtin_neon_vrsqrteq_v:
933 case NEON::BI__builtin_neon_vrndi_v:
934 case NEON::BI__builtin_neon_vrndiq_v:
935 cgf.cgm.errorNYI(expr->getSourceRange(),
936 std::string("unimplemented AArch64 builtin call: ") +
937 ctx.BuiltinInfo.getName(builtinID));
938 return mlir::Value{};
939 case NEON::BI__builtin_neon_vrshr_n_v:
940 case NEON::BI__builtin_neon_vrshrq_n_v: {
941 llvm::StringRef intrName =
942 usgn ? "aarch64.neon.urshl" : "aarch64.neon.srshl";
943 return emitNeonCall(
944 cgf.cgm, cgf.getBuilder(),
945 {ty, usgn ? getSignChangedVectorType(cgf.getBuilder(), ty) : ty}, ops,
946 intrName, ty, loc, /*isConstrainedFPIntrinsic=*/false,
947 /*shift=*/1,
948 /*rightshift=*/true);
949 }
950 case NEON::BI__builtin_neon_vsha512hq_u64:
951 case NEON::BI__builtin_neon_vsha512h2q_u64:
952 case NEON::BI__builtin_neon_vsha512su0q_u64:
953 case NEON::BI__builtin_neon_vsha512su1q_u64:
954 cgf.cgm.errorNYI(expr->getSourceRange(),
955 std::string("unimplemented AArch64 builtin call: ") +
956 ctx.BuiltinInfo.getName(builtinID));
957 return mlir::Value{};
958 case NEON::BI__builtin_neon_vshl_n_v:
959 case NEON::BI__builtin_neon_vshlq_n_v:
960 return emitCommonNeonShift(cgf.getBuilder(), loc, vTy, ops[0], ops[1],
961 /*shiftLeft=*/true);
962 case NEON::BI__builtin_neon_vshll_n_v:
963 case NEON::BI__builtin_neon_vshrn_n_v:
964 cgf.cgm.errorNYI(expr->getSourceRange(),
965 std::string("unimplemented AArch64 builtin call: ") +
966 ctx.BuiltinInfo.getName(builtinID));
967 return mlir::Value{};
968 case NEON::BI__builtin_neon_vshr_n_v:
969 case NEON::BI__builtin_neon_vshrq_n_v:
970 return emitNeonRShiftImm(cgf, ops[0], ops[1], vTy, isUnsigned, loc);
971 case NEON::BI__builtin_neon_vst1_v:
972 case NEON::BI__builtin_neon_vst1q_v:
973 case NEON::BI__builtin_neon_vst2_v:
974 case NEON::BI__builtin_neon_vst2q_v:
975 case NEON::BI__builtin_neon_vst3_v:
976 case NEON::BI__builtin_neon_vst3q_v:
977 case NEON::BI__builtin_neon_vst4_v:
978 case NEON::BI__builtin_neon_vst4q_v:
979 case NEON::BI__builtin_neon_vst2_lane_v:
980 case NEON::BI__builtin_neon_vst2q_lane_v:
981 case NEON::BI__builtin_neon_vst3_lane_v:
982 case NEON::BI__builtin_neon_vst3q_lane_v:
983 case NEON::BI__builtin_neon_vst4_lane_v:
984 case NEON::BI__builtin_neon_vst4q_lane_v:
985 case NEON::BI__builtin_neon_vsm3partw1q_u32:
986 case NEON::BI__builtin_neon_vsm3partw2q_u32:
987 case NEON::BI__builtin_neon_vsm3ss1q_u32:
988 case NEON::BI__builtin_neon_vsm4ekeyq_u32:
989 case NEON::BI__builtin_neon_vsm4eq_u32:
990 case NEON::BI__builtin_neon_vsm3tt1aq_u32:
991 case NEON::BI__builtin_neon_vsm3tt1bq_u32:
992 case NEON::BI__builtin_neon_vsm3tt2aq_u32:
993 case NEON::BI__builtin_neon_vsm3tt2bq_u32:
994 case NEON::BI__builtin_neon_vst1_x2_v:
995 case NEON::BI__builtin_neon_vst1q_x2_v:
996 case NEON::BI__builtin_neon_vst1_x3_v:
997 case NEON::BI__builtin_neon_vst1q_x3_v:
998 case NEON::BI__builtin_neon_vst1_x4_v:
999 case NEON::BI__builtin_neon_vst1q_x4_v:
1000 case NEON::BI__builtin_neon_vsubhn_v:
1001 case NEON::BI__builtin_neon_vtrn_v:
1002 case NEON::BI__builtin_neon_vtrnq_v:
1003 case NEON::BI__builtin_neon_vtst_v:
1004 case NEON::BI__builtin_neon_vtstq_v:
1005 case NEON::BI__builtin_neon_vuzp_v:
1006 case NEON::BI__builtin_neon_vuzpq_v:
1007 case NEON::BI__builtin_neon_vxarq_u64:
1008 case NEON::BI__builtin_neon_vzip_v:
1009 case NEON::BI__builtin_neon_vzipq_v:
1010 case NEON::BI__builtin_neon_vdot_s32:
1011 case NEON::BI__builtin_neon_vdot_u32:
1012 case NEON::BI__builtin_neon_vdotq_s32:
1013 case NEON::BI__builtin_neon_vdotq_u32:
1014 case NEON::BI__builtin_neon_vfmlal_low_f16:
1015 case NEON::BI__builtin_neon_vfmlalq_low_f16:
1016 case NEON::BI__builtin_neon_vfmlsl_low_f16:
1017 case NEON::BI__builtin_neon_vfmlslq_low_f16:
1018 case NEON::BI__builtin_neon_vfmlal_high_f16:
1019 case NEON::BI__builtin_neon_vfmlalq_high_f16:
1020 case NEON::BI__builtin_neon_vfmlsl_high_f16:
1021 case NEON::BI__builtin_neon_vfmlslq_high_f16:
1022 case NEON::BI__builtin_neon_vmmlaq_s32:
1023 case NEON::BI__builtin_neon_vmmlaq_u32:
1024 cgf.cgm.errorNYI(expr->getSourceRange(),
1025 std::string("unimplemented AArch64 builtin call: ") +
1026 ctx.BuiltinInfo.getName(builtinID));
1027 return mlir::Value{};
1028 case NEON::BI__builtin_neon_vmul_v:
1029 case NEON::BI__builtin_neon_vmulq_v:
1030 return cgf.getBuilder().emitIntrinsicCallOp(loc, "aarch64.neon.pmul", vTy,
1031 ops);
1032 case NEON::BI__builtin_neon_vusmmlaq_s32:
1033 case NEON::BI__builtin_neon_vusdot_s32:
1034 case NEON::BI__builtin_neon_vusdotq_s32:
1035 case NEON::BI__builtin_neon_vbfdot_f32:
1036 case NEON::BI__builtin_neon_vbfdotq_f32:
1037 case NEON::BI__builtin_neon___a32_vcvt_bf16_f32:
1038 cgf.cgm.errorNYI(expr->getSourceRange(),
1039 std::string("unimplemented AArch64 builtin call: ") +
1040 ctx.BuiltinInfo.getName(builtinID));
1041 return mlir::Value{};
1042 }
1043
1044 // The switch stmt is intended to help catch NYI cases and will be removed
1045 // once the CIR implementation is complete. Avoid adding specialized
1046 // code in cases - that should only be required for a handful of examples.
1047 switch (builtinID) {
1048 default:
1049 cgf.cgm.errorNYI(expr->getSourceRange(),
1050 std::string("unimplemented AArch64 builtin call: ") +
1051 cgf.getContext().BuiltinInfo.getName(builtinID));
1052 break;
1053 case NEON::BI__builtin_neon_vshl_v:
1054 case NEON::BI__builtin_neon_vshlq_v: {
1055 llvm::StringRef llvmIntrName =
1056 getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(
1057 usgn ? llvmIntrinsic : altLLVMIntrinsic));
1058
1059 mlir::Value result =
1061 /*argTypes=*/{vTy, vTy}, ops, llvmIntrName,
1062 /*funcResTy=*/vTy, loc);
1063 mlir::Type resultType = cgf.convertType(expr->getType());
1064 return cgf.getBuilder().createBitcast(result, resultType);
1065 }
1066 }
1067
1068 // NYI
1069 return nullptr;
1070}
1071
1073 unsigned builtinID, const CallExpr *expr, SmallVectorImpl<mlir::Value> &ops,
1074 SVETypeFlags typeFlags) {
1075 // Find out if any arguments are required to be integer constant expressions.
1076 unsigned iceArguments = 0;
1078 getContext().GetBuiltinType(builtinID, error, &iceArguments);
1079 assert(error == ASTContext::GE_None && "Should not codegen an error");
1080
1081 for (unsigned i = 0, e = expr->getNumArgs(); i != e; i++) {
1082 bool isIce = iceArguments & (1 << i);
1083 mlir::Value arg = emitScalarExpr(expr->getArg(i));
1084
1085 if (isIce) {
1086 cgm.errorNYI(expr->getSourceRange(),
1087 std::string("unimplemented AArch64 builtin call: ") +
1088 getContext().BuiltinInfo.getName(builtinID));
1089 }
1090
1091 // FIXME: Handle types like svint16x2_t, which are currently incorrectly
1092 // converted to i32. These should be treated as structs and unpacked.
1093
1094 ops.push_back(arg);
1095 }
1096 return true;
1097}
1098
1099// Reinterpret the input predicate so that it can be used to correctly isolate
1100// the elements of the specified datatype.
1101mlir::Value CIRGenFunction::emitSVEPredicateCast(mlir::Value pred,
1102 unsigned minNumElts,
1103 mlir::Location loc) {
1104
1105 // TODO: Handle "aarch64.svcount" once we get round to supporting SME.
1106
1107 auto retTy = cir::VectorType::get(builder.getUIntNTy(1), minNumElts,
1108 /*is_scalable=*/true);
1109 if (pred.getType() == retTy)
1110 return pred;
1111
1112 llvm::Intrinsic::ID intID;
1113 switch (minNumElts) {
1114 default:
1115 llvm_unreachable("unsupported element count!");
1116 case 1:
1117 case 2:
1118 case 4:
1119 case 8:
1120 intID = Intrinsic::aarch64_sve_convert_from_svbool;
1121 break;
1122 case 16:
1123 intID = Intrinsic::aarch64_sve_convert_to_svbool;
1124 break;
1125 }
1126
1127 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(intID);
1128 auto call = builder.emitIntrinsicCallOp(loc, llvmIntrName, retTy,
1129 mlir::ValueRange{pred});
1130 assert(call.getType() == retTy && "Unexpected return type!");
1131 return call;
1132}
1133
1134//===----------------------------------------------------------------------===//
1135// SVE helpers
1136//===----------------------------------------------------------------------===//
1137// Get the minimum number of elements in an SVE vector for the given element
1138// type. The actual number of elements in the vector would be an integer (power
1139// of two) multiple of this value.
1141 switch (sveType) {
1142 default:
1143 llvm_unreachable("Invalid SVETypeFlag!");
1144
1145 case SVETypeFlags::EltTyInt8:
1146 return 16;
1147 case SVETypeFlags::EltTyInt16:
1148 return 8;
1149 case SVETypeFlags::EltTyInt32:
1150 return 4;
1151 case SVETypeFlags::EltTyInt64:
1152 return 2;
1153
1154 case SVETypeFlags::EltTyMFloat8:
1155 return 16;
1156 case SVETypeFlags::EltTyFloat16:
1157 case SVETypeFlags::EltTyBFloat16:
1158 return 8;
1159 case SVETypeFlags::EltTyFloat32:
1160 return 4;
1161 case SVETypeFlags::EltTyFloat64:
1162 return 2;
1163
1164 case SVETypeFlags::EltTyBool8:
1165 return 16;
1166 case SVETypeFlags::EltTyBool16:
1167 return 8;
1168 case SVETypeFlags::EltTyBool32:
1169 return 4;
1170 case SVETypeFlags::EltTyBool64:
1171 return 2;
1172 }
1173}
1174
1175// TODO(cir): Share with OGCG
1176constexpr unsigned sveBitsPerBlock = 128;
1177
1178static cir::VectorType getSVEVectorForElementType(CIRGenModule &cgm,
1179 mlir::Type eltTy) {
1180 unsigned numElts =
1182 return cir::VectorType::get(eltTy, numElts, /*is_scalable=*/true);
1183}
1184
1185//===----------------------------------------------------------------------===//
1186// SVE helpers
1187//===----------------------------------------------------------------------===//
1188std::optional<mlir::Value>
1190 const CallExpr *expr) {
1191 mlir::Type ty = convertType(expr->getType());
1192
1193 if (builtinID >= SVE::BI__builtin_sve_reinterpret_s8_s8 &&
1194 builtinID <= SVE::BI__builtin_sve_reinterpret_f64_f64_x4) {
1195 cgm.errorNYI(expr->getSourceRange(),
1196 std::string("unimplemented AArch64 builtin call: ") +
1197 getContext().BuiltinInfo.getName(builtinID));
1198 return mlir::Value{};
1199 }
1200
1202
1203 auto *builtinIntrInfo =
1206
1207 // The operands of the builtin call
1209
1210 SVETypeFlags typeFlags(builtinIntrInfo->TypeModifier);
1212 typeFlags))
1213 return mlir::Value{};
1214
1215 if (typeFlags.isLoad() || typeFlags.isStore() || typeFlags.isGatherLoad() ||
1216 typeFlags.isScatterStore() || typeFlags.isPrefetch() ||
1217 typeFlags.isGatherPrefetch() || typeFlags.isStructLoad() ||
1218 typeFlags.isStructStore() || typeFlags.isTupleSet() ||
1219 typeFlags.isTupleGet() || typeFlags.isTupleCreate() ||
1220 typeFlags.isUndef())
1221 cgm.errorNYI(expr->getSourceRange(),
1222 std::string("unimplemented AArch64 builtin call: ") +
1223 getContext().BuiltinInfo.getName(builtinID));
1224
1225 mlir::Location loc = getLoc(expr->getExprLoc());
1226
1227 // Handle built-ins for which there is a corresponding LLVM Intrinsic.
1228 // -------------------------------------------------------------------
1229 if (builtinIntrInfo->LLVMIntrinsic != 0) {
1230 // Emit set FPMR for intrinsics that require it.
1231 if (typeFlags.setsFPMR())
1232 cgm.errorNYI(expr->getSourceRange(),
1233 std::string("unimplemented AArch64 builtin call: ") +
1234 getContext().BuiltinInfo.getName(builtinID));
1235
1236 // Zero-ing predication
1237 if (typeFlags.getMergeType() == SVETypeFlags::MergeZeroExp) {
1238 auto null = builder.getNullValue(convertType(expr->getType()),
1239 getLoc(expr->getExprLoc()));
1240 ops.insert(ops.begin(), null);
1241 }
1242
1243 if (typeFlags.getMergeType() == SVETypeFlags::MergeAnyExp)
1244 ops.insert(ops.begin(),
1245 builder.getConstant(loc, cir::UndefAttr::get(ty)));
1246
1247 // Some ACLE builtins leave out the argument to specify the predicate
1248 // pattern, which is expected to be expanded to an SV_ALL pattern.
1249 if (typeFlags.isAppendSVALL())
1250 cgm.errorNYI(expr->getSourceRange(),
1251 std::string("unimplemented AArch64 builtin call: ") +
1252 getContext().BuiltinInfo.getName(builtinID));
1253 if (typeFlags.isInsertOp1SVALL())
1254 cgm.errorNYI(expr->getSourceRange(),
1255 std::string("unimplemented AArch64 builtin call: ") +
1256 getContext().BuiltinInfo.getName(builtinID));
1257
1258 // Predicates must match the main datatype.
1259 for (mlir::Value &op : ops)
1260 if (auto predTy = dyn_cast<cir::VectorType>(op.getType()))
1261 if (auto cirInt = dyn_cast<cir::IntType>(predTy.getElementType()))
1262 if (cirInt.getWidth() == 1)
1264 op, getSVEMinEltCount(typeFlags.getEltType()), loc);
1265
1266 // Splat scalar operand to vector (intrinsics with _n infix)
1267 if (typeFlags.hasSplatOperand()) {
1268 unsigned opNo = typeFlags.getSplatOperand();
1269 ops[opNo] = cir::VecSplatOp::create(
1270 builder, loc, getSVEVectorForElementType(cgm, ops[opNo].getType()),
1271 ops[opNo]);
1272 }
1273
1274 if (typeFlags.isReverseCompare())
1275 cgm.errorNYI(expr->getSourceRange(),
1276 std::string("unimplemented AArch64 builtin call: ") +
1277 getContext().BuiltinInfo.getName(builtinID));
1278 if (typeFlags.isReverseUSDOT())
1279 cgm.errorNYI(expr->getSourceRange(),
1280 std::string("unimplemented AArch64 builtin call: ") +
1281 getContext().BuiltinInfo.getName(builtinID));
1282 if (typeFlags.isReverseMergeAnyBinOp() &&
1283 typeFlags.getMergeType() == SVETypeFlags::MergeAny)
1284 cgm.errorNYI(expr->getSourceRange(),
1285 std::string("unimplemented AArch64 builtin call: ") +
1286 getContext().BuiltinInfo.getName(builtinID));
1287 if (typeFlags.isReverseMergeAnyAccOp() &&
1288 typeFlags.getMergeType() == SVETypeFlags::MergeAny)
1289 cgm.errorNYI(expr->getSourceRange(),
1290 std::string("unimplemented AArch64 builtin call: ") +
1291 getContext().BuiltinInfo.getName(builtinID));
1292
1293 // Predicated intrinsics with _z suffix.
1294 if (typeFlags.getMergeType() == SVETypeFlags::MergeZero) {
1295 cgm.errorNYI(expr->getSourceRange(),
1296 std::string("unimplemented AArch64 builtin call: ") +
1297 getContext().BuiltinInfo.getName(builtinID));
1298 }
1299
1300 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
1301 static_cast<llvm::Intrinsic::ID>(builtinIntrInfo->LLVMIntrinsic));
1302 auto retTy = convertType(expr->getType());
1303
1304 auto call = builder.emitIntrinsicCallOp(loc, llvmIntrName, retTy,
1305 mlir::ValueRange{ops});
1306 if (call.getType() == retTy)
1307 return call;
1308
1309 // Predicate results must be converted to svbool_t.
1310 if (isa<mlir::VectorType>(retTy) &&
1311 cast<mlir::VectorType>(retTy).isScalable())
1312 cgm.errorNYI(expr->getSourceRange(),
1313 std::string("unimplemented AArch64 builtin call: ") +
1314 getContext().BuiltinInfo.getName(builtinID));
1315 // TODO Handle struct types, e.g. svint8x2_t (update the converter first).
1316
1317 llvm_unreachable("unsupported element count!");
1318 }
1319
1320 // Handle the remaining built-ins.
1321 // -------------------------------
1322 switch (builtinID) {
1323 default:
1324 return std::nullopt;
1325
1326 case SVE::BI__builtin_sve_svreinterpret_b:
1327 case SVE::BI__builtin_sve_svreinterpret_c:
1328 case SVE::BI__builtin_sve_svpsel_lane_b8:
1329 case SVE::BI__builtin_sve_svpsel_lane_b16:
1330 case SVE::BI__builtin_sve_svpsel_lane_b32:
1331 case SVE::BI__builtin_sve_svpsel_lane_b64:
1332 case SVE::BI__builtin_sve_svpsel_lane_c8:
1333 case SVE::BI__builtin_sve_svpsel_lane_c16:
1334 case SVE::BI__builtin_sve_svpsel_lane_c32:
1335 case SVE::BI__builtin_sve_svpsel_lane_c64:
1336 case SVE::BI__builtin_sve_svmov_b_z:
1337 case SVE::BI__builtin_sve_svnot_b_z:
1338 case SVE::BI__builtin_sve_svmovlb_u16:
1339 case SVE::BI__builtin_sve_svmovlb_u32:
1340 case SVE::BI__builtin_sve_svmovlb_u64:
1341 case SVE::BI__builtin_sve_svmovlb_s16:
1342 case SVE::BI__builtin_sve_svmovlb_s32:
1343 case SVE::BI__builtin_sve_svmovlb_s64:
1344 case SVE::BI__builtin_sve_svmovlt_u16:
1345 case SVE::BI__builtin_sve_svmovlt_u32:
1346 case SVE::BI__builtin_sve_svmovlt_u64:
1347 case SVE::BI__builtin_sve_svmovlt_s16:
1348 case SVE::BI__builtin_sve_svmovlt_s32:
1349 case SVE::BI__builtin_sve_svmovlt_s64:
1350 case SVE::BI__builtin_sve_svpmullt_u16:
1351 case SVE::BI__builtin_sve_svpmullt_u64:
1352 case SVE::BI__builtin_sve_svpmullt_n_u16:
1353 case SVE::BI__builtin_sve_svpmullt_n_u64:
1354 case SVE::BI__builtin_sve_svpmullb_u16:
1355 case SVE::BI__builtin_sve_svpmullb_u64:
1356 case SVE::BI__builtin_sve_svpmullb_n_u16:
1357 case SVE::BI__builtin_sve_svpmullb_n_u64:
1358
1359 case SVE::BI__builtin_sve_svdup_n_b8:
1360 case SVE::BI__builtin_sve_svdup_n_b16:
1361 case SVE::BI__builtin_sve_svdup_n_b32:
1362 case SVE::BI__builtin_sve_svdup_n_b64:
1363
1364 case SVE::BI__builtin_sve_svdupq_n_b8:
1365 case SVE::BI__builtin_sve_svdupq_n_b16:
1366 case SVE::BI__builtin_sve_svdupq_n_b32:
1367 case SVE::BI__builtin_sve_svdupq_n_b64:
1368 case SVE::BI__builtin_sve_svdupq_n_u8:
1369 case SVE::BI__builtin_sve_svdupq_n_s8:
1370 case SVE::BI__builtin_sve_svdupq_n_u64:
1371 case SVE::BI__builtin_sve_svdupq_n_f64:
1372 case SVE::BI__builtin_sve_svdupq_n_s64:
1373 case SVE::BI__builtin_sve_svdupq_n_u16:
1374 case SVE::BI__builtin_sve_svdupq_n_f16:
1375 case SVE::BI__builtin_sve_svdupq_n_bf16:
1376 case SVE::BI__builtin_sve_svdupq_n_s16:
1377 case SVE::BI__builtin_sve_svdupq_n_u32:
1378 case SVE::BI__builtin_sve_svdupq_n_f32:
1379 case SVE::BI__builtin_sve_svdupq_n_s32:
1380 case SVE::BI__builtin_sve_svpfalse_b:
1381 case SVE::BI__builtin_sve_svpfalse_c:
1382 cgm.errorNYI(expr->getSourceRange(),
1383 std::string("unimplemented AArch64 builtin call: ") +
1384 getContext().BuiltinInfo.getName(builtinID));
1385 return mlir::Value{};
1386
1387 case SVE::BI__builtin_sve_svlen_u8:
1388 case SVE::BI__builtin_sve_svlen_s8:
1389 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 16);
1390
1391 case SVE::BI__builtin_sve_svlen_u16:
1392 case SVE::BI__builtin_sve_svlen_s16:
1393 case SVE::BI__builtin_sve_svlen_f16:
1394 case SVE::BI__builtin_sve_svlen_bf16:
1395 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 8);
1396
1397 case SVE::BI__builtin_sve_svlen_u32:
1398 case SVE::BI__builtin_sve_svlen_s32:
1399 case SVE::BI__builtin_sve_svlen_f32:
1400 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 4);
1401
1402 case SVE::BI__builtin_sve_svlen_u64:
1403 case SVE::BI__builtin_sve_svlen_s64:
1404 case SVE::BI__builtin_sve_svlen_f64:
1405 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 2);
1406
1407 case SVE::BI__builtin_sve_svtbl2_u8:
1408 case SVE::BI__builtin_sve_svtbl2_s8:
1409 case SVE::BI__builtin_sve_svtbl2_u16:
1410 case SVE::BI__builtin_sve_svtbl2_s16:
1411 case SVE::BI__builtin_sve_svtbl2_u32:
1412 case SVE::BI__builtin_sve_svtbl2_s32:
1413 case SVE::BI__builtin_sve_svtbl2_u64:
1414 case SVE::BI__builtin_sve_svtbl2_s64:
1415 case SVE::BI__builtin_sve_svtbl2_f16:
1416 case SVE::BI__builtin_sve_svtbl2_bf16:
1417 case SVE::BI__builtin_sve_svtbl2_f32:
1418 case SVE::BI__builtin_sve_svtbl2_f64:
1419 case SVE::BI__builtin_sve_svset_neonq_s8:
1420 case SVE::BI__builtin_sve_svset_neonq_s16:
1421 case SVE::BI__builtin_sve_svset_neonq_s32:
1422 case SVE::BI__builtin_sve_svset_neonq_s64:
1423 case SVE::BI__builtin_sve_svset_neonq_u8:
1424 case SVE::BI__builtin_sve_svset_neonq_u16:
1425 case SVE::BI__builtin_sve_svset_neonq_u32:
1426 case SVE::BI__builtin_sve_svset_neonq_u64:
1427 case SVE::BI__builtin_sve_svset_neonq_f16:
1428 case SVE::BI__builtin_sve_svset_neonq_f32:
1429 case SVE::BI__builtin_sve_svset_neonq_f64:
1430 case SVE::BI__builtin_sve_svset_neonq_bf16:
1431 case SVE::BI__builtin_sve_svget_neonq_s8:
1432 case SVE::BI__builtin_sve_svget_neonq_s16:
1433 case SVE::BI__builtin_sve_svget_neonq_s32:
1434 case SVE::BI__builtin_sve_svget_neonq_s64:
1435 case SVE::BI__builtin_sve_svget_neonq_u8:
1436 case SVE::BI__builtin_sve_svget_neonq_u16:
1437 case SVE::BI__builtin_sve_svget_neonq_u32:
1438 case SVE::BI__builtin_sve_svget_neonq_u64:
1439 case SVE::BI__builtin_sve_svget_neonq_f16:
1440 case SVE::BI__builtin_sve_svget_neonq_f32:
1441 case SVE::BI__builtin_sve_svget_neonq_f64:
1442 case SVE::BI__builtin_sve_svget_neonq_bf16:
1443 case SVE::BI__builtin_sve_svdup_neonq_s8:
1444 case SVE::BI__builtin_sve_svdup_neonq_s16:
1445 case SVE::BI__builtin_sve_svdup_neonq_s32:
1446 case SVE::BI__builtin_sve_svdup_neonq_s64:
1447 case SVE::BI__builtin_sve_svdup_neonq_u8:
1448 case SVE::BI__builtin_sve_svdup_neonq_u16:
1449 case SVE::BI__builtin_sve_svdup_neonq_u32:
1450 case SVE::BI__builtin_sve_svdup_neonq_u64:
1451 case SVE::BI__builtin_sve_svdup_neonq_f16:
1452 case SVE::BI__builtin_sve_svdup_neonq_f32:
1453 case SVE::BI__builtin_sve_svdup_neonq_f64:
1454 case SVE::BI__builtin_sve_svdup_neonq_bf16:
1455 cgm.errorNYI(expr->getSourceRange(),
1456 std::string("unimplemented AArch64 builtin call: ") +
1457 getContext().BuiltinInfo.getName(builtinID));
1458 return mlir::Value{};
1459 }
1460
1461 // Unreachable: All cases in the switch above return.
1462}
1463
1464std::optional<mlir::Value>
1466 const CallExpr *expr) {
1468
1469 cgm.errorNYI(expr->getSourceRange(),
1470 std::string("unimplemented AArch64 builtin call: ") +
1471 getContext().BuiltinInfo.getName(builtinID));
1472 return mlir::Value{};
1473}
1474
1475// Some intrinsics are equivalent for codegen.
1476static const std::pair<unsigned, unsigned> neonEquivalentIntrinsicMap[] = {
1477 {
1478 NEON::BI__builtin_neon_splat_lane_bf16,
1479 NEON::BI__builtin_neon_splat_lane_v,
1480 },
1481 {
1482 NEON::BI__builtin_neon_splat_laneq_bf16,
1483 NEON::BI__builtin_neon_splat_laneq_v,
1484 },
1485 {
1486 NEON::BI__builtin_neon_splatq_lane_bf16,
1487 NEON::BI__builtin_neon_splatq_lane_v,
1488 },
1489 {
1490 NEON::BI__builtin_neon_splatq_laneq_bf16,
1491 NEON::BI__builtin_neon_splatq_laneq_v,
1492 },
1493 {
1494 NEON::BI__builtin_neon_vabd_f16,
1495 NEON::BI__builtin_neon_vabd_v,
1496 },
1497 {
1498 NEON::BI__builtin_neon_vabdq_f16,
1499 NEON::BI__builtin_neon_vabdq_v,
1500 },
1501 {
1502 NEON::BI__builtin_neon_vabs_f16,
1503 NEON::BI__builtin_neon_vabs_v,
1504 },
1505 {
1506 NEON::BI__builtin_neon_vabsq_f16,
1507 NEON::BI__builtin_neon_vabsq_v,
1508 },
1509 {
1510 NEON::BI__builtin_neon_vcage_f16,
1511 NEON::BI__builtin_neon_vcage_v,
1512 },
1513 {
1514 NEON::BI__builtin_neon_vcageq_f16,
1515 NEON::BI__builtin_neon_vcageq_v,
1516 },
1517 {
1518 NEON::BI__builtin_neon_vcagt_f16,
1519 NEON::BI__builtin_neon_vcagt_v,
1520 },
1521 {
1522 NEON::BI__builtin_neon_vcagtq_f16,
1523 NEON::BI__builtin_neon_vcagtq_v,
1524 },
1525 {
1526 NEON::BI__builtin_neon_vcale_f16,
1527 NEON::BI__builtin_neon_vcale_v,
1528 },
1529 {
1530 NEON::BI__builtin_neon_vcaleq_f16,
1531 NEON::BI__builtin_neon_vcaleq_v,
1532 },
1533 {
1534 NEON::BI__builtin_neon_vcalt_f16,
1535 NEON::BI__builtin_neon_vcalt_v,
1536 },
1537 {
1538 NEON::BI__builtin_neon_vcaltq_f16,
1539 NEON::BI__builtin_neon_vcaltq_v,
1540 },
1541 {
1542 NEON::BI__builtin_neon_vceqz_f16,
1543 NEON::BI__builtin_neon_vceqz_v,
1544 },
1545 {
1546 NEON::BI__builtin_neon_vceqzq_f16,
1547 NEON::BI__builtin_neon_vceqzq_v,
1548 },
1549 {
1550 NEON::BI__builtin_neon_vcgez_f16,
1551 NEON::BI__builtin_neon_vcgez_v,
1552 },
1553 {
1554 NEON::BI__builtin_neon_vcgezq_f16,
1555 NEON::BI__builtin_neon_vcgezq_v,
1556 },
1557 {
1558 NEON::BI__builtin_neon_vcgtz_f16,
1559 NEON::BI__builtin_neon_vcgtz_v,
1560 },
1561 {
1562 NEON::BI__builtin_neon_vcgtzq_f16,
1563 NEON::BI__builtin_neon_vcgtzq_v,
1564 },
1565 {
1566 NEON::BI__builtin_neon_vclez_f16,
1567 NEON::BI__builtin_neon_vclez_v,
1568 },
1569 {
1570 NEON::BI__builtin_neon_vclezq_f16,
1571 NEON::BI__builtin_neon_vclezq_v,
1572 },
1573 {
1574 NEON::BI__builtin_neon_vcltz_f16,
1575 NEON::BI__builtin_neon_vcltz_v,
1576 },
1577 {
1578 NEON::BI__builtin_neon_vcltzq_f16,
1579 NEON::BI__builtin_neon_vcltzq_v,
1580 },
1581 {
1582 NEON::BI__builtin_neon_vfma_f16,
1583 NEON::BI__builtin_neon_vfma_v,
1584 },
1585 {
1586 NEON::BI__builtin_neon_vfma_lane_f16,
1587 NEON::BI__builtin_neon_vfma_lane_v,
1588 },
1589 {
1590 NEON::BI__builtin_neon_vfma_laneq_f16,
1591 NEON::BI__builtin_neon_vfma_laneq_v,
1592 },
1593 {
1594 NEON::BI__builtin_neon_vfmaq_f16,
1595 NEON::BI__builtin_neon_vfmaq_v,
1596 },
1597 {
1598 NEON::BI__builtin_neon_vfmaq_lane_f16,
1599 NEON::BI__builtin_neon_vfmaq_lane_v,
1600 },
1601 {
1602 NEON::BI__builtin_neon_vfmaq_laneq_f16,
1603 NEON::BI__builtin_neon_vfmaq_laneq_v,
1604 },
1605 {NEON::BI__builtin_neon_vld1_bf16_x2, NEON::BI__builtin_neon_vld1_x2_v},
1606 {NEON::BI__builtin_neon_vld1_bf16_x3, NEON::BI__builtin_neon_vld1_x3_v},
1607 {NEON::BI__builtin_neon_vld1_bf16_x4, NEON::BI__builtin_neon_vld1_x4_v},
1608 {NEON::BI__builtin_neon_vld1_bf16, NEON::BI__builtin_neon_vld1_v},
1609 {NEON::BI__builtin_neon_vld1_dup_bf16, NEON::BI__builtin_neon_vld1_dup_v},
1610 {NEON::BI__builtin_neon_vld1_lane_bf16, NEON::BI__builtin_neon_vld1_lane_v},
1611 {NEON::BI__builtin_neon_vld1q_bf16_x2, NEON::BI__builtin_neon_vld1q_x2_v},
1612 {NEON::BI__builtin_neon_vld1q_bf16_x3, NEON::BI__builtin_neon_vld1q_x3_v},
1613 {NEON::BI__builtin_neon_vld1q_bf16_x4, NEON::BI__builtin_neon_vld1q_x4_v},
1614 {NEON::BI__builtin_neon_vld1q_bf16, NEON::BI__builtin_neon_vld1q_v},
1615 {NEON::BI__builtin_neon_vld1q_dup_bf16, NEON::BI__builtin_neon_vld1q_dup_v},
1616 {NEON::BI__builtin_neon_vld1q_lane_bf16,
1617 NEON::BI__builtin_neon_vld1q_lane_v},
1618 {NEON::BI__builtin_neon_vld2_bf16, NEON::BI__builtin_neon_vld2_v},
1619 {NEON::BI__builtin_neon_vld2_dup_bf16, NEON::BI__builtin_neon_vld2_dup_v},
1620 {NEON::BI__builtin_neon_vld2_lane_bf16, NEON::BI__builtin_neon_vld2_lane_v},
1621 {NEON::BI__builtin_neon_vld2q_bf16, NEON::BI__builtin_neon_vld2q_v},
1622 {NEON::BI__builtin_neon_vld2q_dup_bf16, NEON::BI__builtin_neon_vld2q_dup_v},
1623 {NEON::BI__builtin_neon_vld2q_lane_bf16,
1624 NEON::BI__builtin_neon_vld2q_lane_v},
1625 {NEON::BI__builtin_neon_vld3_bf16, NEON::BI__builtin_neon_vld3_v},
1626 {NEON::BI__builtin_neon_vld3_dup_bf16, NEON::BI__builtin_neon_vld3_dup_v},
1627 {NEON::BI__builtin_neon_vld3_lane_bf16, NEON::BI__builtin_neon_vld3_lane_v},
1628 {NEON::BI__builtin_neon_vld3q_bf16, NEON::BI__builtin_neon_vld3q_v},
1629 {NEON::BI__builtin_neon_vld3q_dup_bf16, NEON::BI__builtin_neon_vld3q_dup_v},
1630 {NEON::BI__builtin_neon_vld3q_lane_bf16,
1631 NEON::BI__builtin_neon_vld3q_lane_v},
1632 {NEON::BI__builtin_neon_vld4_bf16, NEON::BI__builtin_neon_vld4_v},
1633 {NEON::BI__builtin_neon_vld4_dup_bf16, NEON::BI__builtin_neon_vld4_dup_v},
1634 {NEON::BI__builtin_neon_vld4_lane_bf16, NEON::BI__builtin_neon_vld4_lane_v},
1635 {NEON::BI__builtin_neon_vld4q_bf16, NEON::BI__builtin_neon_vld4q_v},
1636 {NEON::BI__builtin_neon_vld4q_dup_bf16, NEON::BI__builtin_neon_vld4q_dup_v},
1637 {NEON::BI__builtin_neon_vld4q_lane_bf16,
1638 NEON::BI__builtin_neon_vld4q_lane_v},
1639 {
1640 NEON::BI__builtin_neon_vmax_f16,
1641 NEON::BI__builtin_neon_vmax_v,
1642 },
1643 {
1644 NEON::BI__builtin_neon_vmaxnm_f16,
1645 NEON::BI__builtin_neon_vmaxnm_v,
1646 },
1647 {
1648 NEON::BI__builtin_neon_vmaxnmq_f16,
1649 NEON::BI__builtin_neon_vmaxnmq_v,
1650 },
1651 {
1652 NEON::BI__builtin_neon_vmaxq_f16,
1653 NEON::BI__builtin_neon_vmaxq_v,
1654 },
1655 {
1656 NEON::BI__builtin_neon_vmin_f16,
1657 NEON::BI__builtin_neon_vmin_v,
1658 },
1659 {
1660 NEON::BI__builtin_neon_vminnm_f16,
1661 NEON::BI__builtin_neon_vminnm_v,
1662 },
1663 {
1664 NEON::BI__builtin_neon_vminnmq_f16,
1665 NEON::BI__builtin_neon_vminnmq_v,
1666 },
1667 {
1668 NEON::BI__builtin_neon_vminq_f16,
1669 NEON::BI__builtin_neon_vminq_v,
1670 },
1671 {
1672 NEON::BI__builtin_neon_vmulx_f16,
1673 NEON::BI__builtin_neon_vmulx_v,
1674 },
1675 {
1676 NEON::BI__builtin_neon_vmulxq_f16,
1677 NEON::BI__builtin_neon_vmulxq_v,
1678 },
1679 {
1680 NEON::BI__builtin_neon_vpadd_f16,
1681 NEON::BI__builtin_neon_vpadd_v,
1682 },
1683 {
1684 NEON::BI__builtin_neon_vpaddq_f16,
1685 NEON::BI__builtin_neon_vpaddq_v,
1686 },
1687 {
1688 NEON::BI__builtin_neon_vpmax_f16,
1689 NEON::BI__builtin_neon_vpmax_v,
1690 },
1691 {
1692 NEON::BI__builtin_neon_vpmaxnm_f16,
1693 NEON::BI__builtin_neon_vpmaxnm_v,
1694 },
1695 {
1696 NEON::BI__builtin_neon_vpmaxnmq_f16,
1697 NEON::BI__builtin_neon_vpmaxnmq_v,
1698 },
1699 {
1700 NEON::BI__builtin_neon_vpmaxq_f16,
1701 NEON::BI__builtin_neon_vpmaxq_v,
1702 },
1703 {
1704 NEON::BI__builtin_neon_vpmin_f16,
1705 NEON::BI__builtin_neon_vpmin_v,
1706 },
1707 {
1708 NEON::BI__builtin_neon_vpminnm_f16,
1709 NEON::BI__builtin_neon_vpminnm_v,
1710 },
1711 {
1712 NEON::BI__builtin_neon_vpminnmq_f16,
1713 NEON::BI__builtin_neon_vpminnmq_v,
1714 },
1715 {
1716 NEON::BI__builtin_neon_vpminq_f16,
1717 NEON::BI__builtin_neon_vpminq_v,
1718 },
1719 {
1720 NEON::BI__builtin_neon_vrecpe_f16,
1721 NEON::BI__builtin_neon_vrecpe_v,
1722 },
1723 {
1724 NEON::BI__builtin_neon_vrecpeq_f16,
1725 NEON::BI__builtin_neon_vrecpeq_v,
1726 },
1727 {
1728 NEON::BI__builtin_neon_vrecps_f16,
1729 NEON::BI__builtin_neon_vrecps_v,
1730 },
1731 {
1732 NEON::BI__builtin_neon_vrecpsq_f16,
1733 NEON::BI__builtin_neon_vrecpsq_v,
1734 },
1735 {
1736 NEON::BI__builtin_neon_vrnd_f16,
1737 NEON::BI__builtin_neon_vrnd_v,
1738 },
1739 {
1740 NEON::BI__builtin_neon_vrnda_f16,
1741 NEON::BI__builtin_neon_vrnda_v,
1742 },
1743 {
1744 NEON::BI__builtin_neon_vrndaq_f16,
1745 NEON::BI__builtin_neon_vrndaq_v,
1746 },
1747 {
1748 NEON::BI__builtin_neon_vrndi_f16,
1749 NEON::BI__builtin_neon_vrndi_v,
1750 },
1751 {
1752 NEON::BI__builtin_neon_vrndiq_f16,
1753 NEON::BI__builtin_neon_vrndiq_v,
1754 },
1755 {
1756 NEON::BI__builtin_neon_vrndm_f16,
1757 NEON::BI__builtin_neon_vrndm_v,
1758 },
1759 {
1760 NEON::BI__builtin_neon_vrndmq_f16,
1761 NEON::BI__builtin_neon_vrndmq_v,
1762 },
1763 {
1764 NEON::BI__builtin_neon_vrndn_f16,
1765 NEON::BI__builtin_neon_vrndn_v,
1766 },
1767 {
1768 NEON::BI__builtin_neon_vrndnq_f16,
1769 NEON::BI__builtin_neon_vrndnq_v,
1770 },
1771 {
1772 NEON::BI__builtin_neon_vrndp_f16,
1773 NEON::BI__builtin_neon_vrndp_v,
1774 },
1775 {
1776 NEON::BI__builtin_neon_vrndpq_f16,
1777 NEON::BI__builtin_neon_vrndpq_v,
1778 },
1779 {
1780 NEON::BI__builtin_neon_vrndq_f16,
1781 NEON::BI__builtin_neon_vrndq_v,
1782 },
1783 {
1784 NEON::BI__builtin_neon_vrndx_f16,
1785 NEON::BI__builtin_neon_vrndx_v,
1786 },
1787 {
1788 NEON::BI__builtin_neon_vrndxq_f16,
1789 NEON::BI__builtin_neon_vrndxq_v,
1790 },
1791 {
1792 NEON::BI__builtin_neon_vrsqrte_f16,
1793 NEON::BI__builtin_neon_vrsqrte_v,
1794 },
1795 {
1796 NEON::BI__builtin_neon_vrsqrteq_f16,
1797 NEON::BI__builtin_neon_vrsqrteq_v,
1798 },
1799 {
1800 NEON::BI__builtin_neon_vrsqrts_f16,
1801 NEON::BI__builtin_neon_vrsqrts_v,
1802 },
1803 {
1804 NEON::BI__builtin_neon_vrsqrtsq_f16,
1805 NEON::BI__builtin_neon_vrsqrtsq_v,
1806 },
1807 {
1808 NEON::BI__builtin_neon_vsqrt_f16,
1809 NEON::BI__builtin_neon_vsqrt_v,
1810 },
1811 {
1812 NEON::BI__builtin_neon_vsqrtq_f16,
1813 NEON::BI__builtin_neon_vsqrtq_v,
1814 },
1815 {NEON::BI__builtin_neon_vst1_bf16_x2, NEON::BI__builtin_neon_vst1_x2_v},
1816 {NEON::BI__builtin_neon_vst1_bf16_x3, NEON::BI__builtin_neon_vst1_x3_v},
1817 {NEON::BI__builtin_neon_vst1_bf16_x4, NEON::BI__builtin_neon_vst1_x4_v},
1818 {NEON::BI__builtin_neon_vst1_bf16, NEON::BI__builtin_neon_vst1_v},
1819 {NEON::BI__builtin_neon_vst1_lane_bf16, NEON::BI__builtin_neon_vst1_lane_v},
1820 {NEON::BI__builtin_neon_vst1q_bf16_x2, NEON::BI__builtin_neon_vst1q_x2_v},
1821 {NEON::BI__builtin_neon_vst1q_bf16_x3, NEON::BI__builtin_neon_vst1q_x3_v},
1822 {NEON::BI__builtin_neon_vst1q_bf16_x4, NEON::BI__builtin_neon_vst1q_x4_v},
1823 {NEON::BI__builtin_neon_vst1q_bf16, NEON::BI__builtin_neon_vst1q_v},
1824 {NEON::BI__builtin_neon_vst1q_lane_bf16,
1825 NEON::BI__builtin_neon_vst1q_lane_v},
1826 {NEON::BI__builtin_neon_vst2_bf16, NEON::BI__builtin_neon_vst2_v},
1827 {NEON::BI__builtin_neon_vst2_lane_bf16, NEON::BI__builtin_neon_vst2_lane_v},
1828 {NEON::BI__builtin_neon_vst2q_bf16, NEON::BI__builtin_neon_vst2q_v},
1829 {NEON::BI__builtin_neon_vst2q_lane_bf16,
1830 NEON::BI__builtin_neon_vst2q_lane_v},
1831 {NEON::BI__builtin_neon_vst3_bf16, NEON::BI__builtin_neon_vst3_v},
1832 {NEON::BI__builtin_neon_vst3_lane_bf16, NEON::BI__builtin_neon_vst3_lane_v},
1833 {NEON::BI__builtin_neon_vst3q_bf16, NEON::BI__builtin_neon_vst3q_v},
1834 {NEON::BI__builtin_neon_vst3q_lane_bf16,
1835 NEON::BI__builtin_neon_vst3q_lane_v},
1836 {NEON::BI__builtin_neon_vst4_bf16, NEON::BI__builtin_neon_vst4_v},
1837 {NEON::BI__builtin_neon_vst4_lane_bf16, NEON::BI__builtin_neon_vst4_lane_v},
1838 {NEON::BI__builtin_neon_vst4q_bf16, NEON::BI__builtin_neon_vst4q_v},
1839 {NEON::BI__builtin_neon_vst4q_lane_bf16,
1840 NEON::BI__builtin_neon_vst4q_lane_v},
1841 // The mangling rules cause us to have one ID for each type for
1842 // vldap1(q)_lane and vstl1(q)_lane, but codegen is equivalent for all of
1843 // them. Choose an arbitrary one to be handled as tha canonical variation.
1844 {NEON::BI__builtin_neon_vldap1_lane_u64,
1845 NEON::BI__builtin_neon_vldap1_lane_s64},
1846 {NEON::BI__builtin_neon_vldap1_lane_f64,
1847 NEON::BI__builtin_neon_vldap1_lane_s64},
1848 {NEON::BI__builtin_neon_vldap1_lane_p64,
1849 NEON::BI__builtin_neon_vldap1_lane_s64},
1850 {NEON::BI__builtin_neon_vldap1q_lane_u64,
1851 NEON::BI__builtin_neon_vldap1q_lane_s64},
1852 {NEON::BI__builtin_neon_vldap1q_lane_f64,
1853 NEON::BI__builtin_neon_vldap1q_lane_s64},
1854 {NEON::BI__builtin_neon_vldap1q_lane_p64,
1855 NEON::BI__builtin_neon_vldap1q_lane_s64},
1856 {NEON::BI__builtin_neon_vstl1_lane_u64,
1857 NEON::BI__builtin_neon_vstl1_lane_s64},
1858 {NEON::BI__builtin_neon_vstl1_lane_f64,
1859 NEON::BI__builtin_neon_vstl1_lane_s64},
1860 {NEON::BI__builtin_neon_vstl1_lane_p64,
1861 NEON::BI__builtin_neon_vstl1_lane_s64},
1862 {NEON::BI__builtin_neon_vstl1q_lane_u64,
1863 NEON::BI__builtin_neon_vstl1q_lane_s64},
1864 {NEON::BI__builtin_neon_vstl1q_lane_f64,
1865 NEON::BI__builtin_neon_vstl1q_lane_s64},
1866 {NEON::BI__builtin_neon_vstl1q_lane_p64,
1867 NEON::BI__builtin_neon_vstl1q_lane_s64},
1868};
1869
1870std::optional<mlir::Value>
1873 llvm::Triple::ArchType arch) {
1874 if (builtinID >= clang::AArch64::FirstSVEBuiltin &&
1875 builtinID <= clang::AArch64::LastSVEBuiltin)
1876 return emitAArch64SVEBuiltinExpr(builtinID, expr);
1877
1878 if (builtinID >= clang::AArch64::FirstSMEBuiltin &&
1879 builtinID <= clang::AArch64::LastSMEBuiltin)
1880 return emitAArch64SMEBuiltinExpr(builtinID, expr);
1881
1882 if (builtinID == Builtin::BI__builtin_cpu_supports) {
1883 cgm.errorNYI(expr->getSourceRange(),
1884 std::string("unimplemented AArch64 builtin call: ") +
1885 getContext().BuiltinInfo.getName(builtinID));
1886 return mlir::Value{};
1887 }
1888
1889 switch (builtinID) {
1890 default:
1891 break;
1892 case clang::AArch64::BI__builtin_arm_nop:
1893 case clang::AArch64::BI__builtin_arm_yield:
1894 case clang::AArch64::BI__yield:
1895 case clang::AArch64::BI__builtin_arm_wfe:
1896 case clang::AArch64::BI__wfe:
1897 case clang::AArch64::BI__builtin_arm_wfi:
1898 case clang::AArch64::BI__wfi:
1899 case clang::AArch64::BI__builtin_arm_sev:
1900 case clang::AArch64::BI__sev:
1901 case clang::AArch64::BI__builtin_arm_sevl:
1902 case clang::AArch64::BI__sevl:
1903 cgm.errorNYI(expr->getSourceRange(),
1904 std::string("unimplemented AArch64 builtin call: ") +
1905 getContext().BuiltinInfo.getName(builtinID));
1906 return mlir::Value{};
1907 }
1908
1909 if (builtinID == clang::AArch64::BI__builtin_arm_trap) {
1910 cgm.errorNYI(expr->getSourceRange(),
1911 std::string("unimplemented AArch64 builtin call: ") +
1912 getContext().BuiltinInfo.getName(builtinID));
1913 return mlir::Value{};
1914 }
1915
1916 if (builtinID == clang::AArch64::BI__builtin_arm_get_sme_state) {
1917 cgm.errorNYI(expr->getSourceRange(),
1918 std::string("unimplemented AArch64 builtin call: ") +
1919 getContext().BuiltinInfo.getName(builtinID));
1920 return mlir::Value{};
1921 }
1922
1923 if (builtinID == clang::AArch64::BI__builtin_arm_rbit) {
1924 cgm.errorNYI(expr->getSourceRange(),
1925 std::string("unimplemented AArch64 builtin call: ") +
1926 getContext().BuiltinInfo.getName(builtinID));
1927 return mlir::Value{};
1928 }
1929 if (builtinID == clang::AArch64::BI__builtin_arm_rbit64) {
1930 cgm.errorNYI(expr->getSourceRange(),
1931 std::string("unimplemented AArch64 builtin call: ") +
1932 getContext().BuiltinInfo.getName(builtinID));
1933 return mlir::Value{};
1934 }
1935
1936 if (builtinID == clang::AArch64::BI__builtin_arm_clz ||
1937 builtinID == clang::AArch64::BI__builtin_arm_clz64) {
1938 cgm.errorNYI(expr->getSourceRange(),
1939 std::string("unimplemented AArch64 builtin call: ") +
1940 getContext().BuiltinInfo.getName(builtinID));
1941 return mlir::Value{};
1942 }
1943
1944 if (builtinID == clang::AArch64::BI__builtin_arm_cls) {
1945 cgm.errorNYI(expr->getSourceRange(),
1946 std::string("unimplemented AArch64 builtin call: ") +
1947 getContext().BuiltinInfo.getName(builtinID));
1948 return mlir::Value{};
1949 }
1950 if (builtinID == clang::AArch64::BI__builtin_arm_cls64) {
1951 cgm.errorNYI(expr->getSourceRange(),
1952 std::string("unimplemented AArch64 builtin call: ") +
1953 getContext().BuiltinInfo.getName(builtinID));
1954 return mlir::Value{};
1955 }
1956
1957 if (builtinID == clang::AArch64::BI__builtin_arm_rint32zf ||
1958 builtinID == clang::AArch64::BI__builtin_arm_rint32z) {
1959 cgm.errorNYI(expr->getSourceRange(),
1960 std::string("unimplemented AArch64 builtin call: ") +
1961 getContext().BuiltinInfo.getName(builtinID));
1962 return mlir::Value{};
1963 }
1964
1965 if (builtinID == clang::AArch64::BI__builtin_arm_rint64zf ||
1966 builtinID == clang::AArch64::BI__builtin_arm_rint64z) {
1967 cgm.errorNYI(expr->getSourceRange(),
1968 std::string("unimplemented AArch64 builtin call: ") +
1969 getContext().BuiltinInfo.getName(builtinID));
1970 return mlir::Value{};
1971 }
1972
1973 if (builtinID == clang::AArch64::BI__builtin_arm_rint32xf ||
1974 builtinID == clang::AArch64::BI__builtin_arm_rint32x) {
1975 cgm.errorNYI(expr->getSourceRange(),
1976 std::string("unimplemented AArch64 builtin call: ") +
1977 getContext().BuiltinInfo.getName(builtinID));
1978 return mlir::Value{};
1979 }
1980
1981 if (builtinID == clang::AArch64::BI__builtin_arm_rint64xf ||
1982 builtinID == clang::AArch64::BI__builtin_arm_rint64x) {
1983 cgm.errorNYI(expr->getSourceRange(),
1984 std::string("unimplemented AArch64 builtin call: ") +
1985 getContext().BuiltinInfo.getName(builtinID));
1986 return mlir::Value{};
1987 }
1988
1989 if (builtinID == clang::AArch64::BI__builtin_arm_jcvt) {
1990 cgm.errorNYI(expr->getSourceRange(),
1991 std::string("unimplemented AArch64 builtin call: ") +
1992 getContext().BuiltinInfo.getName(builtinID));
1993 return mlir::Value{};
1994 }
1995
1996 if (builtinID == clang::AArch64::BI__builtin_arm_ld64b ||
1997 builtinID == clang::AArch64::BI__builtin_arm_st64b ||
1998 builtinID == clang::AArch64::BI__builtin_arm_st64bv ||
1999 builtinID == clang::AArch64::BI__builtin_arm_st64bv0) {
2000 cgm.errorNYI(expr->getSourceRange(),
2001 std::string("unimplemented AArch64 builtin call: ") +
2002 getContext().BuiltinInfo.getName(builtinID));
2003 return mlir::Value{};
2004 }
2005
2006 if (builtinID == clang::AArch64::BI__builtin_arm_rndr ||
2007 builtinID == clang::AArch64::BI__builtin_arm_rndrrs) {
2008 cgm.errorNYI(expr->getSourceRange(),
2009 std::string("unimplemented AArch64 builtin call: ") +
2010 getContext().BuiltinInfo.getName(builtinID));
2011 return mlir::Value{};
2012 }
2013
2014 if (builtinID == clang::AArch64::BI__clear_cache) {
2015 cgm.errorNYI(expr->getSourceRange(),
2016 std::string("unimplemented AArch64 builtin call: ") +
2017 getContext().BuiltinInfo.getName(builtinID));
2018 return mlir::Value{};
2019 }
2020
2021 if ((builtinID == clang::AArch64::BI__builtin_arm_ldrex ||
2022 builtinID == clang::AArch64::BI__builtin_arm_ldaex) &&
2023 getContext().getTypeSize(expr->getType()) == 128) {
2024 cgm.errorNYI(expr->getSourceRange(),
2025 std::string("unimplemented AArch64 builtin call: ") +
2026 getContext().BuiltinInfo.getName(builtinID));
2027 return mlir::Value{};
2028 }
2029 if (builtinID == clang::AArch64::BI__builtin_arm_ldrex ||
2030 builtinID == clang::AArch64::BI__builtin_arm_ldaex) {
2031 cgm.errorNYI(expr->getSourceRange(),
2032 std::string("unimplemented AArch64 builtin call: ") +
2033 getContext().BuiltinInfo.getName(builtinID));
2034 return mlir::Value{};
2035 }
2036
2037 if ((builtinID == clang::AArch64::BI__builtin_arm_strex ||
2038 builtinID == clang::AArch64::BI__builtin_arm_stlex) &&
2039 getContext().getTypeSize(expr->getArg(0)->getType()) == 128) {
2040 cgm.errorNYI(expr->getSourceRange(),
2041 std::string("unimplemented AArch64 builtin call: ") +
2042 getContext().BuiltinInfo.getName(builtinID));
2043 return mlir::Value{};
2044 }
2045
2046 if (builtinID == clang::AArch64::BI__builtin_arm_strex ||
2047 builtinID == clang::AArch64::BI__builtin_arm_stlex) {
2048 cgm.errorNYI(expr->getSourceRange(),
2049 std::string("unimplemented AArch64 builtin call: ") +
2050 getContext().BuiltinInfo.getName(builtinID));
2051 return mlir::Value{};
2052 }
2053
2054 if (builtinID == clang::AArch64::BI__getReg ||
2055 builtinID == clang::AArch64::BI__setReg ||
2056 builtinID == clang::AArch64::BI__getRegFp ||
2057 builtinID == clang::AArch64::BI__setRegFp) {
2058 cgm.errorNYI(expr->getSourceRange(),
2059 std::string("unimplemented AArch64 builtin call: ") +
2060 getContext().BuiltinInfo.getName(builtinID));
2061 return mlir::Value{};
2062 }
2063
2064 if (builtinID == clang::AArch64::BI__break) {
2065 cgm.errorNYI(expr->getSourceRange(),
2066 std::string("unimplemented AArch64 builtin call: ") +
2067 getContext().BuiltinInfo.getName(builtinID));
2068 return mlir::Value{};
2069 }
2070
2071 if (builtinID == clang::AArch64::BI__builtin_arm_clrex) {
2072 cgm.errorNYI(expr->getSourceRange(),
2073 std::string("unimplemented AArch64 builtin call: ") +
2074 getContext().BuiltinInfo.getName(builtinID));
2075 return mlir::Value{};
2076 }
2077
2078 if (builtinID == clang::AArch64::BI_ReadWriteBarrier) {
2079 cgm.errorNYI(expr->getSourceRange(),
2080 std::string("unimplemented AArch64 builtin call: ") +
2081 getContext().BuiltinInfo.getName(builtinID));
2082 return mlir::Value{};
2083 }
2084
2085 // CRC32
2086 Intrinsic::ID crcIntrinsicID = Intrinsic::not_intrinsic;
2087 switch (builtinID) {
2088 case clang::AArch64::BI__builtin_arm_crc32b:
2089 crcIntrinsicID = Intrinsic::aarch64_crc32b;
2090 break;
2091 case clang::AArch64::BI__builtin_arm_crc32cb:
2092 crcIntrinsicID = Intrinsic::aarch64_crc32cb;
2093 break;
2094 case clang::AArch64::BI__builtin_arm_crc32h:
2095 crcIntrinsicID = Intrinsic::aarch64_crc32h;
2096 break;
2097 case clang::AArch64::BI__builtin_arm_crc32ch:
2098 crcIntrinsicID = Intrinsic::aarch64_crc32ch;
2099 break;
2100 case clang::AArch64::BI__builtin_arm_crc32w:
2101 crcIntrinsicID = Intrinsic::aarch64_crc32w;
2102 break;
2103 case clang::AArch64::BI__builtin_arm_crc32cw:
2104 crcIntrinsicID = Intrinsic::aarch64_crc32cw;
2105 break;
2106 case clang::AArch64::BI__builtin_arm_crc32d:
2107 crcIntrinsicID = Intrinsic::aarch64_crc32x;
2108 break;
2109 case clang::AArch64::BI__builtin_arm_crc32cd:
2110 crcIntrinsicID = Intrinsic::aarch64_crc32cx;
2111 break;
2112 }
2113
2114 if (crcIntrinsicID != Intrinsic::not_intrinsic) {
2115 cgm.errorNYI(expr->getSourceRange(),
2116 std::string("unimplemented AArch64 builtin call: ") +
2117 getContext().BuiltinInfo.getName(builtinID));
2118 return mlir::Value{};
2119 }
2120
2121 // Memory Operations (MOPS)
2122 if (builtinID == AArch64::BI__builtin_arm_mops_memset_tag) {
2123 cgm.errorNYI(expr->getSourceRange(),
2124 std::string("unimplemented AArch64 builtin call: ") +
2125 getContext().BuiltinInfo.getName(builtinID));
2126 return mlir::Value{};
2127 }
2128
2129 // Memory Tagging Extensions (MTE) Intrinsics
2130 Intrinsic::ID mteIntrinsicID = Intrinsic::not_intrinsic;
2131 switch (builtinID) {
2132 case clang::AArch64::BI__builtin_arm_irg:
2133 mteIntrinsicID = Intrinsic::aarch64_irg;
2134 break;
2135 case clang::AArch64::BI__builtin_arm_addg:
2136 mteIntrinsicID = Intrinsic::aarch64_addg;
2137 break;
2138 case clang::AArch64::BI__builtin_arm_gmi:
2139 mteIntrinsicID = Intrinsic::aarch64_gmi;
2140 break;
2141 case clang::AArch64::BI__builtin_arm_ldg:
2142 mteIntrinsicID = Intrinsic::aarch64_ldg;
2143 break;
2144 case clang::AArch64::BI__builtin_arm_stg:
2145 mteIntrinsicID = Intrinsic::aarch64_stg;
2146 break;
2147 case clang::AArch64::BI__builtin_arm_subp:
2148 mteIntrinsicID = Intrinsic::aarch64_subp;
2149 break;
2150 }
2151
2152 if (mteIntrinsicID != Intrinsic::not_intrinsic) {
2153 cgm.errorNYI(expr->getSourceRange(),
2154 std::string("unimplemented AArch64 builtin call: ") +
2155 getContext().BuiltinInfo.getName(builtinID));
2156 return mlir::Value{};
2157 }
2158
2159 if (builtinID == clang::AArch64::BI__builtin_arm_rsr ||
2160 builtinID == clang::AArch64::BI__builtin_arm_rsr64 ||
2161 builtinID == clang::AArch64::BI__builtin_arm_rsr128 ||
2162 builtinID == clang::AArch64::BI__builtin_arm_rsrp ||
2163 builtinID == clang::AArch64::BI__builtin_arm_wsr ||
2164 builtinID == clang::AArch64::BI__builtin_arm_wsr64 ||
2165 builtinID == clang::AArch64::BI__builtin_arm_wsr128 ||
2166 builtinID == clang::AArch64::BI__builtin_arm_wsrp) {
2167 cgm.errorNYI(expr->getSourceRange(),
2168 std::string("unimplemented AArch64 builtin call: ") +
2169 getContext().BuiltinInfo.getName(builtinID));
2170 return mlir::Value{};
2171 }
2172
2173 if (builtinID == clang::AArch64::BI_ReadStatusReg ||
2174 builtinID == clang::AArch64::BI_WriteStatusReg ||
2175 builtinID == clang::AArch64::BI__sys) {
2176 cgm.errorNYI(expr->getSourceRange(),
2177 std::string("unimplemented AArch64 builtin call: ") +
2178 getContext().BuiltinInfo.getName(builtinID));
2179 return mlir::Value{};
2180 }
2181
2182 if (builtinID == clang::AArch64::BI_AddressOfReturnAddress) {
2183 cgm.errorNYI(expr->getSourceRange(),
2184 std::string("unimplemented AArch64 builtin call: ") +
2185 getContext().BuiltinInfo.getName(builtinID));
2186 return mlir::Value{};
2187 }
2188
2189 if (builtinID == clang::AArch64::BI__builtin_sponentry) {
2190 cgm.errorNYI(expr->getSourceRange(),
2191 std::string("unimplemented AArch64 builtin call: ") +
2192 getContext().BuiltinInfo.getName(builtinID));
2193 return mlir::Value{};
2194 }
2195
2196 if (builtinID == clang::AArch64::BI__mulh ||
2197 builtinID == clang::AArch64::BI__umulh) {
2198 cgm.errorNYI(expr->getSourceRange(),
2199 std::string("unimplemented AArch64 builtin call: ") +
2200 getContext().BuiltinInfo.getName(builtinID));
2201 return mlir::Value{};
2202 }
2203
2204 if (builtinID == AArch64::BI__writex18byte ||
2205 builtinID == AArch64::BI__writex18word ||
2206 builtinID == AArch64::BI__writex18dword ||
2207 builtinID == AArch64::BI__writex18qword) {
2208 cgm.errorNYI(expr->getSourceRange(),
2209 std::string("unimplemented AArch64 builtin call: ") +
2210 getContext().BuiltinInfo.getName(builtinID));
2211 return mlir::Value{};
2212 }
2213
2214 if (builtinID == AArch64::BI__readx18byte ||
2215 builtinID == AArch64::BI__readx18word ||
2216 builtinID == AArch64::BI__readx18dword ||
2217 builtinID == AArch64::BI__readx18qword) {
2218 cgm.errorNYI(expr->getSourceRange(),
2219 std::string("unimplemented AArch64 builtin call: ") +
2220 getContext().BuiltinInfo.getName(builtinID));
2221 return mlir::Value{};
2222 }
2223
2224 if (builtinID == AArch64::BI__addx18byte ||
2225 builtinID == AArch64::BI__addx18word ||
2226 builtinID == AArch64::BI__addx18dword ||
2227 builtinID == AArch64::BI__addx18qword ||
2228 builtinID == AArch64::BI__incx18byte ||
2229 builtinID == AArch64::BI__incx18word ||
2230 builtinID == AArch64::BI__incx18dword ||
2231 builtinID == AArch64::BI__incx18qword) {
2232 cgm.errorNYI(expr->getSourceRange(),
2233 std::string("unimplemented AArch64 builtin call: ") +
2234 getContext().BuiltinInfo.getName(builtinID));
2235 return mlir::Value{};
2236 }
2237
2238 if (builtinID == AArch64::BI_CopyDoubleFromInt64 ||
2239 builtinID == AArch64::BI_CopyFloatFromInt32 ||
2240 builtinID == AArch64::BI_CopyInt32FromFloat ||
2241 builtinID == AArch64::BI_CopyInt64FromDouble) {
2242 cgm.errorNYI(expr->getSourceRange(),
2243 std::string("unimplemented AArch64 builtin call: ") +
2244 getContext().BuiltinInfo.getName(builtinID));
2245 return mlir::Value{};
2246 }
2247
2248 if (builtinID == AArch64::BI_CountLeadingOnes ||
2249 builtinID == AArch64::BI_CountLeadingOnes64 ||
2250 builtinID == AArch64::BI_CountLeadingZeros ||
2251 builtinID == AArch64::BI_CountLeadingZeros64) {
2252 cgm.errorNYI(expr->getSourceRange(),
2253 std::string("unimplemented AArch64 builtin call: ") +
2254 getContext().BuiltinInfo.getName(builtinID));
2255 return mlir::Value{};
2256 }
2257
2258 if (builtinID == AArch64::BI_CountLeadingSigns ||
2259 builtinID == AArch64::BI_CountLeadingSigns64) {
2260 cgm.errorNYI(expr->getSourceRange(),
2261 std::string("unimplemented AArch64 builtin call: ") +
2262 getContext().BuiltinInfo.getName(builtinID));
2263 return mlir::Value{};
2264 }
2265
2266 if (builtinID == AArch64::BI_CountOneBits ||
2267 builtinID == AArch64::BI_CountOneBits64 ||
2268 builtinID == AArch64::BI_CountTrailingZeros ||
2269 builtinID == AArch64::BI_CountTrailingZeros64) {
2270 cgm.errorNYI(expr->getSourceRange(),
2271 std::string("unimplemented AArch64 builtin call: ") +
2272 getContext().BuiltinInfo.getName(builtinID));
2273 return mlir::Value{};
2274 }
2275
2276 if (builtinID == AArch64::BI__prefetch ||
2277 builtinID == AArch64::BI__prefetch2) {
2278 cgm.errorNYI(expr->getSourceRange(),
2279 std::string("unimplemented AArch64 builtin call: ") +
2280 getContext().BuiltinInfo.getName(builtinID));
2281 return mlir::Value{};
2282 }
2283
2284 if (builtinID == AArch64::BI__hlt) {
2285 cgm.errorNYI(expr->getSourceRange(),
2286 std::string("unimplemented AArch64 builtin call: ") +
2287 getContext().BuiltinInfo.getName(builtinID));
2288 return mlir::Value{};
2289 }
2290
2291 if (builtinID == NEON::BI__builtin_neon_vcvth_bf16_f32) {
2292 cgm.errorNYI(expr->getSourceRange(),
2293 std::string("unimplemented AArch64 builtin call: ") +
2294 getContext().BuiltinInfo.getName(builtinID));
2295 return mlir::Value{};
2296 }
2297
2298 // Handle MSVC intrinsics before argument evaluation to prevent double
2299 // evaluation.
2301
2302 // Some intrinsics are equivalent - if they are use the base intrinsic ID.
2303 auto it = llvm::find_if(neonEquivalentIntrinsicMap, [builtinID](auto &p) {
2304 return p.first == builtinID;
2305 });
2306 if (it != end(neonEquivalentIntrinsicMap))
2307 builtinID = it->second;
2308
2309 // Find out if any arguments are required to be integer constant
2310 // expressions.
2312 unsigned iceArguments = 0;
2314 getContext().GetBuiltinType(builtinID, error, &iceArguments);
2315 assert(error == ASTContext::GE_None && "Should not codegen an error");
2317
2318 // Skip extra arguments used to discriminate vector types and that are
2319 // intended for Sema checking.
2320 bool hasExtraArg = hasExtraNeonArgument(builtinID);
2321 unsigned numArgs = expr->getNumArgs() - (hasExtraArg ? 1 : 0);
2322 for (unsigned i = 0, e = numArgs; i != e; i++) {
2323 if (i == 0) {
2324 switch (builtinID) {
2325 case NEON::BI__builtin_neon_vld1_v:
2326 case NEON::BI__builtin_neon_vld1q_v:
2327 case NEON::BI__builtin_neon_vld1_dup_v:
2328 case NEON::BI__builtin_neon_vld1q_dup_v:
2329 case NEON::BI__builtin_neon_vld1_lane_v:
2330 case NEON::BI__builtin_neon_vld1q_lane_v:
2331 case NEON::BI__builtin_neon_vst1_v:
2332 case NEON::BI__builtin_neon_vst1q_v:
2333 case NEON::BI__builtin_neon_vst1_lane_v:
2334 case NEON::BI__builtin_neon_vst1q_lane_v:
2335 case NEON::BI__builtin_neon_vldap1_lane_s64:
2336 case NEON::BI__builtin_neon_vldap1q_lane_s64:
2337 case NEON::BI__builtin_neon_vstl1_lane_s64:
2338 case NEON::BI__builtin_neon_vstl1q_lane_s64:
2339 // Get the alignment for the argument in addition to the value;
2340 // we'll use it later.
2341 cgm.errorNYI(
2342 expr->getSourceRange(),
2343 std::string("unimplemented AArch64 builtin argument handling ") +
2344 getContext().BuiltinInfo.getName(builtinID));
2345 }
2346 }
2347 ops.push_back(
2348 emitScalarOrConstFoldImmArg(iceArguments, i, expr->getArg(i)));
2349 }
2350
2351 const ARMNeonVectorIntrinsicInfo *builtin =
2354 if (builtin)
2355 return emitCommonNeonSISDBuiltinExpr(*this, *builtin, ops, expr);
2356
2357 // Not all intrinsics handled by the common case work for AArch64 yet, so only
2358 // defer to common code if it's been added to our special map.
2360
2362
2363 const Expr *arg = expr->getArg(expr->getNumArgs() - 1);
2365 // A trailing constant integer is used for discriminating overloaded builtin
2366 // calls. Use it to determine the type of this overloaded NEON intrinsic.
2367 if (std::optional<llvm::APSInt> result =
2368 arg->getIntegerConstantExpr(getContext()))
2369 type = NeonTypeFlags(result->getZExtValue());
2370
2371 bool usgn = type.isUnsigned();
2372
2373 mlir::Location loc = getLoc(expr->getExprLoc());
2374
2375 // Not all intrinsics handled by the common case work for AArch64 yet, so only
2376 // defer to common code if it's been added to our special map.
2377 builtin =
2380 if (builtin)
2382 *this, builtin->BuiltinID, builtin->LLVMIntrinsic,
2383 builtin->AltLLVMIntrinsic, builtin->NameHint, builtin->TypeModifier,
2384 expr, ops);
2385
2386 // Handle non-overloaded intrinsics first.
2387 switch (builtinID) {
2388 default:
2389 break;
2390 case NEON::BI__builtin_neon_vabsh_f16: {
2391 return cir::FAbsOp::create(builder, loc, ops);
2392 }
2393 case NEON::BI__builtin_neon_vaddq_p128: {
2394 cir::VectorType byteTy = cir::VectorType::get(builder.getUInt8Ty(), 16);
2395 ops[0] = builder.createBitcast(ops[0], byteTy);
2396 ops[1] = builder.createBitcast(ops[1], byteTy);
2397 mlir::Value result = builder.createXor(loc, ops[0], ops[1]);
2398 return builder.createBitcast(result, convertType(expr->getType()));
2399 }
2400 case NEON::BI__builtin_neon_vldrq_p128:
2401 case NEON::BI__builtin_neon_vstrq_p128:
2402 case NEON::BI__builtin_neon_vcvts_f32_u32:
2403 case NEON::BI__builtin_neon_vcvtd_f64_u64:
2404 case NEON::BI__builtin_neon_vcvts_f32_s32:
2405 case NEON::BI__builtin_neon_vcvtd_f64_s64:
2406 case NEON::BI__builtin_neon_vcvth_f16_u16:
2407 case NEON::BI__builtin_neon_vcvth_f16_u32:
2408 case NEON::BI__builtin_neon_vcvth_f16_u64:
2409 case NEON::BI__builtin_neon_vcvth_f16_s16:
2410 case NEON::BI__builtin_neon_vcvth_f16_s32:
2411 case NEON::BI__builtin_neon_vcvth_f16_s64:
2412 case NEON::BI__builtin_neon_vcvtah_u16_f16:
2413 case NEON::BI__builtin_neon_vcvtmh_u16_f16:
2414 case NEON::BI__builtin_neon_vcvtnh_u16_f16:
2415 case NEON::BI__builtin_neon_vcvtph_u16_f16:
2416 case NEON::BI__builtin_neon_vcvth_u16_f16:
2417 case NEON::BI__builtin_neon_vcvtah_s16_f16:
2418 case NEON::BI__builtin_neon_vcvtmh_s16_f16:
2419 case NEON::BI__builtin_neon_vcvtnh_s16_f16:
2420 case NEON::BI__builtin_neon_vcvtph_s16_f16:
2421 case NEON::BI__builtin_neon_vcvth_s16_f16:
2422 case NEON::BI__builtin_neon_vcaleh_f16:
2423 case NEON::BI__builtin_neon_vcalth_f16:
2424 case NEON::BI__builtin_neon_vcageh_f16:
2425 case NEON::BI__builtin_neon_vcagth_f16:
2426 case NEON::BI__builtin_neon_vcvth_n_s16_f16:
2427 case NEON::BI__builtin_neon_vcvth_n_u16_f16:
2428 case NEON::BI__builtin_neon_vcvth_n_f16_s16:
2429 case NEON::BI__builtin_neon_vcvth_n_f16_u16:
2430 case NEON::BI__builtin_neon_vpaddd_s64:
2431 case NEON::BI__builtin_neon_vpaddd_f64:
2432 case NEON::BI__builtin_neon_vpadds_f32:
2433 cgm.errorNYI(expr->getSourceRange(),
2434 std::string("unimplemented AArch64 builtin call: ") +
2435 getContext().BuiltinInfo.getName(builtinID));
2436 return mlir::Value{};
2437 case NEON::BI__builtin_neon_vceqzd_s64:
2438 case NEON::BI__builtin_neon_vceqzd_f64:
2439 case NEON::BI__builtin_neon_vceqzs_f32:
2440 case NEON::BI__builtin_neon_vceqzh_f16:
2442 *this, builder, loc, ops[0],
2443 convertType(expr->getCallReturnType(getContext())), cir::CmpOpKind::eq);
2444 case NEON::BI__builtin_neon_vcgezd_s64:
2445 case NEON::BI__builtin_neon_vcgezd_f64:
2446 case NEON::BI__builtin_neon_vcgezs_f32:
2447 case NEON::BI__builtin_neon_vcgezh_f16:
2448 case NEON::BI__builtin_neon_vclezd_s64:
2449 case NEON::BI__builtin_neon_vclezd_f64:
2450 case NEON::BI__builtin_neon_vclezs_f32:
2451 case NEON::BI__builtin_neon_vclezh_f16:
2452 case NEON::BI__builtin_neon_vcgtzd_s64:
2453 case NEON::BI__builtin_neon_vcgtzd_f64:
2454 case NEON::BI__builtin_neon_vcgtzs_f32:
2455 case NEON::BI__builtin_neon_vcgtzh_f16:
2456 case NEON::BI__builtin_neon_vcltzd_s64:
2457 case NEON::BI__builtin_neon_vcltzd_f64:
2458 case NEON::BI__builtin_neon_vcltzs_f32:
2459 case NEON::BI__builtin_neon_vcltzh_f16:
2460 case NEON::BI__builtin_neon_vceqzd_u64: {
2462 *this, builder, loc, ops[0],
2463 convertType(expr->getCallReturnType(getContext())), cir::CmpOpKind::eq);
2464 }
2465 case NEON::BI__builtin_neon_vceqd_f64:
2466 case NEON::BI__builtin_neon_vcled_f64:
2467 case NEON::BI__builtin_neon_vcltd_f64:
2468 case NEON::BI__builtin_neon_vcged_f64:
2469 case NEON::BI__builtin_neon_vcgtd_f64:
2470 case NEON::BI__builtin_neon_vceqs_f32:
2471 case NEON::BI__builtin_neon_vcles_f32:
2472 case NEON::BI__builtin_neon_vclts_f32:
2473 case NEON::BI__builtin_neon_vcges_f32:
2474 case NEON::BI__builtin_neon_vcgts_f32:
2475 case NEON::BI__builtin_neon_vceqh_f16:
2476 case NEON::BI__builtin_neon_vcleh_f16:
2477 case NEON::BI__builtin_neon_vclth_f16:
2478 case NEON::BI__builtin_neon_vcgeh_f16:
2479 case NEON::BI__builtin_neon_vcgth_f16:
2480 case NEON::BI__builtin_neon_vceqd_s64:
2481 case NEON::BI__builtin_neon_vceqd_u64:
2482 case NEON::BI__builtin_neon_vcgtd_s64:
2483 case NEON::BI__builtin_neon_vcgtd_u64:
2484 case NEON::BI__builtin_neon_vcltd_s64:
2485 case NEON::BI__builtin_neon_vcltd_u64:
2486 case NEON::BI__builtin_neon_vcged_u64:
2487 case NEON::BI__builtin_neon_vcged_s64:
2488 case NEON::BI__builtin_neon_vcled_u64:
2489 case NEON::BI__builtin_neon_vcled_s64:
2490 cgm.errorNYI(expr->getSourceRange(),
2491 std::string("unimplemented AArch64 builtin call: ") +
2492 getContext().BuiltinInfo.getName(builtinID));
2493 return mlir::Value{};
2494 case NEON::BI__builtin_neon_vnegd_s64: {
2495 return builder.createNeg(loc, ops[0]);
2496 }
2497 case NEON::BI__builtin_neon_vnegh_f16: {
2498 return builder.createFNeg(loc, ops[0]);
2499 }
2500 case NEON::BI__builtin_neon_vtstd_s64:
2501 case NEON::BI__builtin_neon_vtstd_u64:
2502 case NEON::BI__builtin_neon_vset_lane_i8:
2503 case NEON::BI__builtin_neon_vset_lane_i16:
2504 case NEON::BI__builtin_neon_vset_lane_i32:
2505 case NEON::BI__builtin_neon_vset_lane_i64:
2506 case NEON::BI__builtin_neon_vset_lane_bf16:
2507 case NEON::BI__builtin_neon_vset_lane_f32:
2508 case NEON::BI__builtin_neon_vsetq_lane_i8:
2509 case NEON::BI__builtin_neon_vsetq_lane_i16:
2510 case NEON::BI__builtin_neon_vsetq_lane_i32:
2511 case NEON::BI__builtin_neon_vsetq_lane_i64:
2512 case NEON::BI__builtin_neon_vsetq_lane_bf16:
2513 case NEON::BI__builtin_neon_vsetq_lane_f32:
2514 case NEON::BI__builtin_neon_vset_lane_f64:
2515 case NEON::BI__builtin_neon_vset_lane_mf8:
2516 case NEON::BI__builtin_neon_vsetq_lane_mf8:
2517 case NEON::BI__builtin_neon_vsetq_lane_f64:
2518 cgm.errorNYI(expr->getSourceRange(),
2519 std::string("unimplemented AArch64 builtin call: ") +
2520 getContext().BuiltinInfo.getName(builtinID));
2521 return mlir::Value{};
2522
2523 case NEON::BI__builtin_neon_vget_lane_i8:
2524 case NEON::BI__builtin_neon_vdupb_lane_i8:
2525 case NEON::BI__builtin_neon_vgetq_lane_i8:
2526 case NEON::BI__builtin_neon_vdupb_laneq_i8:
2527 case NEON::BI__builtin_neon_vget_lane_mf8:
2528 case NEON::BI__builtin_neon_vdupb_lane_mf8:
2529 case NEON::BI__builtin_neon_vgetq_lane_mf8:
2530 case NEON::BI__builtin_neon_vdupb_laneq_mf8:
2531 case NEON::BI__builtin_neon_vget_lane_i16:
2532 case NEON::BI__builtin_neon_vduph_lane_i16:
2533 case NEON::BI__builtin_neon_vgetq_lane_i16:
2534 case NEON::BI__builtin_neon_vduph_laneq_i16:
2535 case NEON::BI__builtin_neon_vget_lane_i32:
2536 case NEON::BI__builtin_neon_vdups_lane_i32:
2537 case NEON::BI__builtin_neon_vdups_lane_f32:
2538 case NEON::BI__builtin_neon_vgetq_lane_i32:
2539 case NEON::BI__builtin_neon_vdups_laneq_i32:
2540 case NEON::BI__builtin_neon_vget_lane_i64:
2541 case NEON::BI__builtin_neon_vdupd_lane_i64:
2542 case NEON::BI__builtin_neon_vdupd_lane_f64:
2543 case NEON::BI__builtin_neon_vgetq_lane_i64:
2544 case NEON::BI__builtin_neon_vdupd_laneq_i64:
2545 case NEON::BI__builtin_neon_vget_lane_f32:
2546 case NEON::BI__builtin_neon_vget_lane_f64:
2547 case NEON::BI__builtin_neon_vgetq_lane_f32:
2548 case NEON::BI__builtin_neon_vdups_laneq_f32:
2549 case NEON::BI__builtin_neon_vgetq_lane_f64:
2550 case NEON::BI__builtin_neon_vdupd_laneq_f64:
2551 return cir::VecExtractOp::create(builder, loc, ops[0],
2552 emitScalarExpr(expr->getArg(1)));
2553 case NEON::BI__builtin_neon_vaddh_f16:
2554 return builder.createFAdd(loc, ops[0], ops[1]);
2555 case NEON::BI__builtin_neon_vsubh_f16:
2556 return builder.createFSub(loc, ops[0], ops[1]);
2557 case NEON::BI__builtin_neon_vmulh_f16:
2558 return builder.createFMul(loc, ops[0], ops[1]);
2559 case NEON::BI__builtin_neon_vdivh_f16:
2560 return builder.createFDiv(loc, ops[0], ops[1]);
2561 case NEON::BI__builtin_neon_vfmah_f16:
2562 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
2563 std::rotate(ops.begin(), ops.begin() + 1, ops.end());
2564 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma",
2565 convertType(expr->getType()), ops);
2566 break;
2567 case NEON::BI__builtin_neon_vfmsh_f16:
2568 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
2569 std::rotate(ops.begin(), ops.begin() + 1, ops.end());
2570 ops[0] = builder.createFNeg(loc, ops[0]);
2571 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma",
2572 convertType(expr->getType()), ops);
2573 case NEON::BI__builtin_neon_vaddd_s64:
2574 case NEON::BI__builtin_neon_vaddd_u64:
2575 return builder.createAdd(loc, ops[0], ops[1]);
2576 case NEON::BI__builtin_neon_vsubd_s64:
2577 case NEON::BI__builtin_neon_vsubd_u64:
2578 return builder.createSub(loc, ops[0], ops[1]);
2579 case NEON::BI__builtin_neon_vqdmlalh_s16:
2580 case NEON::BI__builtin_neon_vqdmlslh_s16:
2581 cgm.errorNYI(expr->getSourceRange(),
2582 std::string("unimplemented AArch64 builtin call: ") +
2583 getContext().BuiltinInfo.getName(builtinID));
2584 return mlir::Value{};
2585 case NEON::BI__builtin_neon_vqshlud_n_s64: {
2586 cir::IntType int64Type = builder.getSInt64Ty();
2587 ops[1] = builder.getSInt64(getZExtIntValueFromConstOp(ops[1]), loc);
2588 return emitNeonCall(cgm, builder, {int64Type, int64Type}, ops,
2589 "aarch64.neon.sqshlu", convertType(expr->getType()),
2590 loc);
2591 }
2592 case NEON::BI__builtin_neon_vqshld_n_u64:
2593 case NEON::BI__builtin_neon_vqshld_n_s64: {
2594 cir::IntType int64Type = builtinID == NEON::BI__builtin_neon_vqshld_n_u64
2595 ? builder.getUInt64Ty()
2596 : builder.getSInt64Ty();
2597 llvm::StringRef intrinsicName =
2598 builtinID == NEON::BI__builtin_neon_vqshld_n_u64 ? "aarch64.neon.uqshl"
2599 : "aarch64.neon.sqshl";
2600 ops[1] = builder.getSInt64(getZExtIntValueFromConstOp(ops[1]), loc);
2601 return emitNeonCall(cgm, builder, {int64Type, int64Type}, ops,
2602 intrinsicName, convertType(expr->getType()), loc);
2603 }
2604 case NEON::BI__builtin_neon_vrshrd_n_u64:
2605 case NEON::BI__builtin_neon_vrshrd_n_s64: {
2606 llvm::StringRef intrName = builtinID == NEON::BI__builtin_neon_vrshrd_n_s64
2607 ? "aarch64.neon.srshl"
2608 : "aarch64.neon.urshl";
2609 cir::IntType int64Ty = builtinID == NEON::BI__builtin_neon_vqshld_n_u64
2610 ? builder.getUInt64Ty()
2611 : builder.getSInt64Ty();
2612 int64_t sv = -cast<cir::IntAttr>(
2613 cast<cir::ConstantOp>(ops[1].getDefiningOp()).getValue())
2614 .getSInt();
2615 ops[1] = builder.getSInt64(sv, loc);
2616 return emitNeonCall(cgm, builder, {int64Ty, builder.getSInt64Ty()}, ops,
2617 intrName, int64Ty, loc);
2618 }
2619 case NEON::BI__builtin_neon_vrsrad_n_u64:
2620 case NEON::BI__builtin_neon_vrsrad_n_s64: {
2621 cir::IntType int64Type = builtinID == NEON::BI__builtin_neon_vrsrad_n_u64
2622 ? builder.getUInt64Ty()
2623 : builder.getSInt64Ty();
2624 ops[2] = builder.createNeg(loc, ops[2]);
2625 const StringRef intrName = builtinID == NEON::BI__builtin_neon_vrsrad_n_u64
2626 ? "aarch64.neon.urshl"
2627 : "aarch64.neon.srshl";
2628
2630 ops[1], builder.createIntCast(ops[2], builder.getSInt64Ty())};
2631 ops[1] = builder.emitIntrinsicCallOp(loc, intrName, int64Type, args);
2632 return builder.createAdd(loc, ops[0],
2633 builder.createBitcast(ops[1], int64Type));
2634 }
2635 case NEON::BI__builtin_neon_vshld_n_s64:
2636 case NEON::BI__builtin_neon_vshld_n_u64: {
2637 auto loc = getLoc(expr->getExprLoc());
2638 std::optional<llvm::APSInt> amt =
2639 expr->getArg(1)->getIntegerConstantExpr(getContext());
2640 assert(amt && "Expected argument to be a constant");
2641 return builder.createShiftLeft(loc, ops[0], amt->getZExtValue());
2642 }
2643 case NEON::BI__builtin_neon_vshrd_n_s64: {
2644 std::optional<llvm::APSInt> amt =
2645 expr->getArg(1)->getIntegerConstantExpr(getContext());
2646 assert(amt && "Expected argument to be a constant");
2647 return builder.createShiftRight(
2648 loc, ops[0], std::min(static_cast<uint64_t>(63), amt->getZExtValue()));
2649 }
2650 case NEON::BI__builtin_neon_vshrd_n_u64: {
2651 std::optional<llvm::APSInt> amt =
2652 expr->getArg(1)->getIntegerConstantExpr(getContext());
2653 assert(amt && "Expected argument to be a constant");
2654 uint64_t shiftAmt = amt->getZExtValue();
2655 // Right-shifting an unsigned value by its size yields 0.
2656 if (shiftAmt == 64)
2657 return builder.getConstInt(loc, builder.getUInt64Ty(), 0);
2658 return builder.createShiftRight(loc, ops[0], shiftAmt);
2659 }
2660 case NEON::BI__builtin_neon_vsrad_n_s64: {
2661 std::optional<llvm::APSInt> amt =
2662 expr->getArg(2)->getIntegerConstantExpr(getContext());
2663 assert(amt && "Expected argument to be a constant");
2664 uint64_t shiftAmt =
2665 std::min(static_cast<uint64_t>(63), amt->getZExtValue());
2666 mlir::Value shifted =
2667 builder.createShiftRight(loc, ops[1], static_cast<unsigned>(shiftAmt));
2668 return builder.createAdd(loc, ops[0], shifted);
2669 }
2670 case NEON::BI__builtin_neon_vsrad_n_u64: {
2671 std::optional<llvm::APSInt> amt =
2672 expr->getArg(2)->getIntegerConstantExpr(getContext());
2673 assert(amt && "Expected argument to be a constant");
2674 uint64_t shiftAmt = amt->getZExtValue();
2675 // Right-shifting an unsigned value by its size yields 0, so a + 0 = a.
2676 if (shiftAmt == 64)
2677 return ops[0];
2678 mlir::Value shifted =
2679 builder.createShiftRight(loc, ops[1], static_cast<unsigned>(shiftAmt));
2680 return builder.createAdd(loc, ops[0], shifted);
2681 }
2682 case NEON::BI__builtin_neon_vqdmlalh_lane_s16:
2683 case NEON::BI__builtin_neon_vqdmlalh_laneq_s16:
2684 case NEON::BI__builtin_neon_vqdmlslh_lane_s16:
2685 case NEON::BI__builtin_neon_vqdmlslh_laneq_s16:
2686 case NEON::BI__builtin_neon_vqdmlals_s32:
2687 case NEON::BI__builtin_neon_vqdmlsls_s32:
2688 case NEON::BI__builtin_neon_vqdmlals_lane_s32:
2689 case NEON::BI__builtin_neon_vqdmlals_laneq_s32:
2690 case NEON::BI__builtin_neon_vqdmlsls_lane_s32:
2691 case NEON::BI__builtin_neon_vqdmlsls_laneq_s32: {
2692 cgm.errorNYI(expr->getSourceRange(),
2693 std::string("unimplemented AArch64 builtin call: ") +
2694 getContext().BuiltinInfo.getName(builtinID));
2695 return mlir::Value{};
2696 }
2697 case NEON::BI__builtin_neon_vget_lane_bf16:
2698 case NEON::BI__builtin_neon_vduph_lane_bf16:
2699 case NEON::BI__builtin_neon_vduph_lane_f16:
2700 case NEON::BI__builtin_neon_vgetq_lane_bf16:
2701 case NEON::BI__builtin_neon_vduph_laneq_bf16:
2702 case NEON::BI__builtin_neon_vduph_laneq_f16: {
2703 return cir::VecExtractOp::create(builder, loc, ops[0], ops[1]);
2704 }
2705 case NEON::BI__builtin_neon_vcvt_bf16_f32:
2706 case NEON::BI__builtin_neon_vcvtq_low_bf16_f32:
2707 case NEON::BI__builtin_neon_vcvtq_high_bf16_f32:
2708 case NEON::BI__builtin_neon_vcvt_f16_f32:
2709 case NEON::BI__builtin_neon_vcvt_f32_f16:
2710 case clang::AArch64::BI_InterlockedAdd:
2711 case clang::AArch64::BI_InterlockedAdd_acq:
2712 case clang::AArch64::BI_InterlockedAdd_rel:
2713 case clang::AArch64::BI_InterlockedAdd_nf:
2714 case clang::AArch64::BI_InterlockedAdd64:
2715 case clang::AArch64::BI_InterlockedAdd64_acq:
2716 case clang::AArch64::BI_InterlockedAdd64_rel:
2717 case clang::AArch64::BI_InterlockedAdd64_nf:
2718 cgm.errorNYI(expr->getSourceRange(),
2719 std::string("unimplemented AArch64 builtin call: ") +
2720 getContext().BuiltinInfo.getName(builtinID));
2721 return mlir::Value{};
2722 }
2723
2724 cir::VectorType ty = getNeonType(this, type, loc);
2725 if (!ty)
2726 return nullptr;
2727
2728 llvm::StringRef intrName;
2729
2730 switch (builtinID) {
2731 default:
2732 return std::nullopt;
2733 case NEON::BI__builtin_neon_vbsl_v:
2734 case NEON::BI__builtin_neon_vbslq_v: {
2735
2736 cir::VectorType bitTy = getIntVecFromVecTy(builder, ty);
2737 ops[0] = builder.createBitcast(ops[0], bitTy);
2738 ops[1] = builder.createBitcast(ops[1], bitTy);
2739 ops[2] = builder.createBitcast(ops[2], bitTy);
2740
2741 ops[1] = builder.createAnd(loc, ops[0], ops[1]);
2742 ops[2] = builder.createAnd(loc, builder.createNot(ops[0]), ops[2]);
2743 ops[0] = builder.createOr(loc, ops[1], ops[2]);
2744 return builder.createBitcast(ops[0], ty);
2745 }
2746 case NEON::BI__builtin_neon_vfma_lane_v:
2747 cgm.errorNYI(expr->getSourceRange(),
2748 std::string("unimplemented AArch64 builtin call: ") +
2749 getContext().BuiltinInfo.getName(builtinID));
2750 return mlir::Value{};
2751 case NEON::BI__builtin_neon_vfmaq_lane_v: {
2752 mlir::Value addend = builder.createBitcast(ops[0], ty);
2753 mlir::Value multiplicand = builder.createBitcast(ops[1], ty);
2754 // The lane source operand is the non-quad vector, so it has half as many
2755 // lanes as the quad result vector.
2756 cir::VectorType sourceTy =
2757 cir::VectorType::get(ty.getElementType(), ty.getSize() / 2);
2758 mlir::Value laneSource = builder.createBitcast(ops[2], sourceTy);
2759 laneSource = emitNeonSplat(builder, loc, laneSource, ops[3], ty.getSize());
2760
2761 llvm::SmallVector<mlir::Value> fmaOps = {multiplicand, laneSource, addend};
2762 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma", ty, fmaOps);
2763 }
2764 case NEON::BI__builtin_neon_vfma_laneq_v: {
2765 // v1f64 fma should be mapped to Neon scalar f64 fma.
2766 if (ty.getElementType() == cgm.doubleTy) {
2767 mlir::Value addend = builder.createBitcast(ops[0], cgm.doubleTy);
2768 mlir::Value multiplicand = builder.createBitcast(ops[1], cgm.doubleTy);
2769 // The laneq source operand is float64x2_t, so the source vector has two
2770 // double lanes.
2771 cir::VectorType sourceTy = cir::VectorType::get(cgm.doubleTy, 2);
2772 mlir::Value laneSource = builder.createBitcast(ops[2], sourceTy);
2773 laneSource = builder.createExtractElement(
2774 loc, laneSource,
2775 static_cast<uint64_t>(getIntValueFromConstOp(ops[3])));
2776
2777 llvm::SmallVector<mlir::Value> fmaOps = {multiplicand, laneSource,
2778 addend};
2779 return builder.createBitcast(
2780 emitCallMaybeConstrainedBuiltin(builder, loc, "fma", cgm.doubleTy,
2781 fmaOps),
2782 ty);
2783 }
2784
2785 mlir::Value addend = builder.createBitcast(ops[0], ty);
2786 mlir::Value multiplicand = builder.createBitcast(ops[1], ty);
2787 // The laneq source operand is the quad vector, so it has twice as many
2788 // lanes as the non-quad result vector.
2789 cir::VectorType sourceTy =
2790 cir::VectorType::get(ty.getElementType(), ty.getSize() * 2);
2791 mlir::Value laneSource = builder.createBitcast(ops[2], sourceTy);
2792 laneSource = emitNeonSplat(builder, loc, laneSource, ops[3], ty.getSize());
2793
2794 llvm::SmallVector<mlir::Value> fmaOps = {laneSource, multiplicand, addend};
2795 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma", ty, fmaOps);
2796 }
2797 case NEON::BI__builtin_neon_vfmaq_laneq_v: {
2798 mlir::Value addend = builder.createBitcast(ops[0], ty);
2799 mlir::Value multiplicand = builder.createBitcast(ops[1], ty);
2800 mlir::Value laneSource = builder.createBitcast(ops[2], ty);
2801 laneSource = emitNeonSplat(builder, loc, laneSource, ops[3], ty.getSize());
2802
2803 llvm::SmallVector<mlir::Value> fmaOps = {laneSource, multiplicand, addend};
2804 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma", ty, fmaOps);
2805 }
2806 case NEON::BI__builtin_neon_vfmah_lane_f16:
2807 case NEON::BI__builtin_neon_vfmas_lane_f32:
2808 case NEON::BI__builtin_neon_vfmah_laneq_f16:
2809 case NEON::BI__builtin_neon_vfmas_laneq_f32:
2810 case NEON::BI__builtin_neon_vfmad_lane_f64:
2811 cgm.errorNYI(expr->getSourceRange(),
2812 std::string("unimplemented AArch64 builtin call: ") +
2813 getContext().BuiltinInfo.getName(builtinID));
2814 return mlir::Value{};
2815 case NEON::BI__builtin_neon_vfmad_laneq_f64: {
2816 // The laneq source operand is float64x2_t, so the source vector has two
2817 // double lanes.
2818 mlir::Value laneSource = builder.createExtractElement(
2819 loc, ops[2], static_cast<uint64_t>(getIntValueFromConstOp(ops[3])));
2820
2821 llvm::SmallVector<mlir::Value> fmaOps = {ops[1], laneSource, ops[0]};
2822 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma", cgm.doubleTy,
2823 fmaOps);
2824 }
2825 case NEON::BI__builtin_neon_vmull_v: {
2826 intrName = usgn ? "aarch64.neon.umull" : "aarch64.neon.smull";
2827 if (type.isPoly())
2828 intrName = "aarch64.neon.pmull";
2829 cir::VectorType argTy = builder.getExtendedOrTruncatedElementVectorType(
2830 ty, /*isExtended*/ false, !usgn);
2831 return emitNeonCall(cgm, builder, {argTy, argTy}, ops, intrName, ty, loc);
2832 }
2833 case NEON::BI__builtin_neon_vmax_v:
2834 case NEON::BI__builtin_neon_vmaxq_v:
2835 intrName = usgn ? "aarch64.neon.umax" : "aarch64.neon.smax";
2836 if (cir::isFPOrVectorOfFPType(ty))
2837 intrName = "aarch64.neon.fmax";
2838 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2839 case NEON::BI__builtin_neon_vmaxh_f16:
2840 cgm.errorNYI(expr->getSourceRange(),
2841 std::string("unimplemented AArch64 builtin call: ") +
2842 getContext().BuiltinInfo.getName(builtinID));
2843 return mlir::Value{};
2844 case NEON::BI__builtin_neon_vmin_v:
2845 case NEON::BI__builtin_neon_vminq_v:
2846 intrName = usgn ? "aarch64.neon.umin" : "aarch64.neon.smin";
2847 if (cir::isFPOrVectorOfFPType(ty))
2848 intrName = "aarch64.neon.fmin";
2849 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2850 case NEON::BI__builtin_neon_vminh_f16:
2851 cgm.errorNYI(expr->getSourceRange(),
2852 std::string("unimplemented AArch64 builtin call: ") +
2853 getContext().BuiltinInfo.getName(builtinID));
2854 return mlir::Value{};
2855 case NEON::BI__builtin_neon_vabd_v:
2856 case NEON::BI__builtin_neon_vabdq_v:
2857 intrName = usgn ? "aarch64.neon.uabd" : "aarch64.neon.sabd";
2858 if (cir::isFPOrVectorOfFPType(ty))
2859 intrName = "aarch64.neon.fabd";
2860 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2861 case NEON::BI__builtin_neon_vpadal_v:
2862 case NEON::BI__builtin_neon_vpadalq_v: {
2863 intrName = usgn ? "aarch64.neon.uaddlp" : "aarch64.neon.saddlp";
2864 llvm::SmallVector<mlir::Value> inputs{ops[1]};
2865 mlir::Value pairwiseSum =
2866 emitNeonCall(cgm, builder, {getNeonPairwiseWidenInputType(ty, usgn)},
2867 inputs, intrName, ty, loc);
2868 mlir::Value accumValue = builder.createBitcast(loc, ops[0], ty);
2869 return cir::AddOp::create(builder, loc, ty, pairwiseSum, accumValue);
2870 }
2871 case NEON::BI__builtin_neon_vpmin_v:
2872 case NEON::BI__builtin_neon_vpminq_v:
2873 intrName = usgn ? "aarch64.neon.uminp" : "aarch64.neon.sminp";
2874 if (cir::isFPOrVectorOfFPType(ty))
2875 intrName = "aarch64.neon.fminp";
2876 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2877 case NEON::BI__builtin_neon_vpmax_v:
2878 case NEON::BI__builtin_neon_vpmaxq_v:
2879 intrName = usgn ? "aarch64.neon.umaxp" : "aarch64.neon.smaxp";
2880 if (cir::isFPOrVectorOfFPType(ty))
2881 intrName = "aarch64.neon.fmaxp";
2882 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2883 case NEON::BI__builtin_neon_vminnm_v:
2884 case NEON::BI__builtin_neon_vminnmq_v:
2885 intrName = "aarch64.neon.fminnm";
2886 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2887 case NEON::BI__builtin_neon_vminnmh_f16:
2888 cgm.errorNYI(expr->getSourceRange(),
2889 std::string("unimplemented AArch64 builtin call: ") +
2890 getContext().BuiltinInfo.getName(builtinID));
2891 return mlir::Value{};
2892 case NEON::BI__builtin_neon_vmaxnm_v:
2893 case NEON::BI__builtin_neon_vmaxnmq_v:
2894 intrName = "aarch64.neon.fmaxnm";
2895 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2896 case NEON::BI__builtin_neon_vmaxnmh_f16:
2897 case NEON::BI__builtin_neon_vrecpss_f32:
2898 case NEON::BI__builtin_neon_vrecpsd_f64:
2899 case NEON::BI__builtin_neon_vrecpsh_f16:
2900 case NEON::BI__builtin_neon_vqshrun_n_v:
2901 cgm.errorNYI(expr->getSourceRange(),
2902 std::string("unimplemented AArch64 builtin call: ") +
2903 getContext().BuiltinInfo.getName(builtinID));
2904 return mlir::Value{};
2905 case NEON::BI__builtin_neon_vqrshrun_n_v: {
2906 cir::VectorType argTy = builder.getExtendedOrTruncatedElementVectorType(
2907 ty, /*isExtended=*/true, /*isSigned=*/true);
2908 return emitNeonCall(cgm, builder, {argTy, sInt32Ty}, ops,
2909 "aarch64.neon.sqrshrun", ty, loc);
2910 }
2911 case NEON::BI__builtin_neon_vqshrn_n_v:
2912 cgm.errorNYI(expr->getSourceRange(),
2913 std::string("unimplemented AArch64 builtin call: ") +
2914 getContext().BuiltinInfo.getName(builtinID));
2915 return mlir::Value{};
2916 case NEON::BI__builtin_neon_vrshrn_n_v:
2917 cgm.errorNYI(expr->getSourceRange(),
2918 std::string("unimplemented AArch64 builtin call: ") +
2919 getContext().BuiltinInfo.getName(builtinID));
2920 return mlir::Value{};
2921 case NEON::BI__builtin_neon_vqrshrn_n_v: {
2922 cir::VectorType argTy = builder.getExtendedOrTruncatedElementVectorType(
2923 ty, /*isExtended=*/true, /*isSigned=*/!usgn);
2924 llvm::StringRef intrName =
2925 usgn ? "aarch64.neon.uqrshrn" : "aarch64.neon.sqrshrn";
2926 return emitNeonCall(cgm, builder, {argTy, sInt32Ty}, ops, intrName, ty,
2927 loc);
2928 }
2929 case NEON::BI__builtin_neon_vrndah_f16:
2930 case NEON::BI__builtin_neon_vrnda_v:
2931 case NEON::BI__builtin_neon_vrndaq_v:
2932 case NEON::BI__builtin_neon_vrndih_f16:
2933 case NEON::BI__builtin_neon_vrndmh_f16:
2934 case NEON::BI__builtin_neon_vrndm_v:
2935 case NEON::BI__builtin_neon_vrndmq_v:
2936 case NEON::BI__builtin_neon_vrndnh_f16:
2937 case NEON::BI__builtin_neon_vrndn_v:
2938 case NEON::BI__builtin_neon_vrndnq_v:
2939 case NEON::BI__builtin_neon_vrndns_f32:
2940 case NEON::BI__builtin_neon_vrndph_f16:
2941 case NEON::BI__builtin_neon_vrndp_v:
2942 case NEON::BI__builtin_neon_vrndpq_v:
2943 case NEON::BI__builtin_neon_vrndxh_f16:
2944 case NEON::BI__builtin_neon_vrndx_v:
2945 case NEON::BI__builtin_neon_vrndxq_v:
2946 case NEON::BI__builtin_neon_vrndh_f16:
2947 case NEON::BI__builtin_neon_vrnd32x_f32:
2948 case NEON::BI__builtin_neon_vrnd32xq_f32:
2949 case NEON::BI__builtin_neon_vrnd32x_f64:
2950 case NEON::BI__builtin_neon_vrnd32xq_f64:
2951 case NEON::BI__builtin_neon_vrnd32z_f32:
2952 case NEON::BI__builtin_neon_vrnd32zq_f32:
2953 case NEON::BI__builtin_neon_vrnd32z_f64:
2954 case NEON::BI__builtin_neon_vrnd32zq_f64:
2955 case NEON::BI__builtin_neon_vrnd64x_f32:
2956 case NEON::BI__builtin_neon_vrnd64xq_f32:
2957 case NEON::BI__builtin_neon_vrnd64x_f64:
2958 case NEON::BI__builtin_neon_vrnd64xq_f64:
2959 case NEON::BI__builtin_neon_vrnd64z_f32:
2960 case NEON::BI__builtin_neon_vrnd64zq_f32:
2961 case NEON::BI__builtin_neon_vrnd64z_f64:
2962 case NEON::BI__builtin_neon_vrnd64zq_f64:
2963 case NEON::BI__builtin_neon_vrnd_v:
2964 case NEON::BI__builtin_neon_vrndq_v:
2965 cgm.errorNYI(expr->getSourceRange(),
2966 std::string("unimplemented AArch64 builtin call: ") +
2967 getContext().BuiltinInfo.getName(builtinID));
2968 return mlir::Value{};
2969 case NEON::BI__builtin_neon_vcvt_f64_v:
2970 case NEON::BI__builtin_neon_vcvtq_f64_v:
2971 ops[0] = builder.createBitcast(ops[0], ty);
2972 ty = getNeonType(
2973 this, NeonTypeFlags(NeonTypeFlags::Float64, false, type.isQuad()), loc);
2974 return builder.createCast(loc, cir::CastKind::int_to_float, ops[0], ty);
2975 case NEON::BI__builtin_neon_vcvt_f64_f32:
2976 case NEON::BI__builtin_neon_vcvt_f32_f64:
2977 case NEON::BI__builtin_neon_vcvt_s32_v:
2978 case NEON::BI__builtin_neon_vcvt_u32_v:
2979 case NEON::BI__builtin_neon_vcvt_s64_v:
2980 case NEON::BI__builtin_neon_vcvt_u64_v:
2981 case NEON::BI__builtin_neon_vcvt_s16_f16:
2982 case NEON::BI__builtin_neon_vcvt_u16_f16:
2983 case NEON::BI__builtin_neon_vcvtq_s32_v:
2984 case NEON::BI__builtin_neon_vcvtq_u32_v:
2985 case NEON::BI__builtin_neon_vcvtq_s64_v:
2986 case NEON::BI__builtin_neon_vcvtq_u64_v:
2987 case NEON::BI__builtin_neon_vcvtq_s16_f16:
2988 case NEON::BI__builtin_neon_vcvtq_u16_f16:
2989 case NEON::BI__builtin_neon_vcvta_s16_f16:
2990 case NEON::BI__builtin_neon_vcvta_u16_f16:
2991 case NEON::BI__builtin_neon_vcvta_s32_v:
2992 case NEON::BI__builtin_neon_vcvtaq_s16_f16:
2993 case NEON::BI__builtin_neon_vcvtaq_s32_v:
2994 case NEON::BI__builtin_neon_vcvta_u32_v:
2995 case NEON::BI__builtin_neon_vcvtaq_u16_f16:
2996 case NEON::BI__builtin_neon_vcvtaq_u32_v:
2997 case NEON::BI__builtin_neon_vcvta_s64_v:
2998 case NEON::BI__builtin_neon_vcvtaq_s64_v:
2999 case NEON::BI__builtin_neon_vcvta_u64_v:
3000 case NEON::BI__builtin_neon_vcvtaq_u64_v:
3001 case NEON::BI__builtin_neon_vcvtm_s16_f16:
3002 case NEON::BI__builtin_neon_vcvtm_s32_v:
3003 case NEON::BI__builtin_neon_vcvtmq_s16_f16:
3004 case NEON::BI__builtin_neon_vcvtmq_s32_v:
3005 case NEON::BI__builtin_neon_vcvtm_u16_f16:
3006 case NEON::BI__builtin_neon_vcvtm_u32_v:
3007 case NEON::BI__builtin_neon_vcvtmq_u16_f16:
3008 case NEON::BI__builtin_neon_vcvtmq_u32_v:
3009 case NEON::BI__builtin_neon_vcvtm_s64_v:
3010 case NEON::BI__builtin_neon_vcvtmq_s64_v:
3011 case NEON::BI__builtin_neon_vcvtm_u64_v:
3012 case NEON::BI__builtin_neon_vcvtmq_u64_v:
3013 case NEON::BI__builtin_neon_vcvtn_s16_f16:
3014 case NEON::BI__builtin_neon_vcvtn_s32_v:
3015 case NEON::BI__builtin_neon_vcvtnq_s16_f16:
3016 case NEON::BI__builtin_neon_vcvtnq_s32_v:
3017 case NEON::BI__builtin_neon_vcvtn_u16_f16:
3018 case NEON::BI__builtin_neon_vcvtn_u32_v:
3019 case NEON::BI__builtin_neon_vcvtnq_u16_f16:
3020 case NEON::BI__builtin_neon_vcvtnq_u32_v:
3021 case NEON::BI__builtin_neon_vcvtn_s64_v:
3022 case NEON::BI__builtin_neon_vcvtnq_s64_v:
3023 case NEON::BI__builtin_neon_vcvtn_u64_v:
3024 case NEON::BI__builtin_neon_vcvtnq_u64_v:
3025 case NEON::BI__builtin_neon_vcvtp_s16_f16:
3026 case NEON::BI__builtin_neon_vcvtp_s32_v:
3027 case NEON::BI__builtin_neon_vcvtpq_s16_f16:
3028 case NEON::BI__builtin_neon_vcvtpq_s32_v:
3029 case NEON::BI__builtin_neon_vcvtp_u16_f16:
3030 case NEON::BI__builtin_neon_vcvtp_u32_v:
3031 case NEON::BI__builtin_neon_vcvtpq_u16_f16:
3032 case NEON::BI__builtin_neon_vcvtpq_u32_v:
3033 case NEON::BI__builtin_neon_vcvtp_s64_v:
3034 case NEON::BI__builtin_neon_vcvtpq_s64_v:
3035 case NEON::BI__builtin_neon_vcvtp_u64_v:
3036 case NEON::BI__builtin_neon_vcvtpq_u64_v:
3037 case NEON::BI__builtin_neon_vmulx_v:
3038 case NEON::BI__builtin_neon_vmulxq_v:
3039 case NEON::BI__builtin_neon_vmulxh_lane_f16:
3040 case NEON::BI__builtin_neon_vmulxh_laneq_f16:
3041 case NEON::BI__builtin_neon_vmul_lane_v:
3042 case NEON::BI__builtin_neon_vmul_laneq_v:
3043 case NEON::BI__builtin_neon_vpmaxnm_v:
3044 case NEON::BI__builtin_neon_vpmaxnmq_v:
3045 cgm.errorNYI(expr->getSourceRange(),
3046 std::string("unimplemented AArch64 builtin call: ") +
3047 getContext().BuiltinInfo.getName(builtinID));
3048 return mlir::Value{};
3049 case NEON::BI__builtin_neon_vpminnm_v:
3050 case NEON::BI__builtin_neon_vpminnmq_v:
3051 intrName = "aarch64.neon.fminnmp";
3052 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
3053 case NEON::BI__builtin_neon_vsqrth_f16:
3054 cgm.errorNYI(expr->getSourceRange(),
3055 std::string("unimplemented AArch64 builtin call: ") +
3056 getContext().BuiltinInfo.getName(builtinID));
3057 return mlir::Value{};
3058 case NEON::BI__builtin_neon_vsqrt_v:
3059 case NEON::BI__builtin_neon_vsqrtq_v:
3061 return emitNeonCall(cgm, builder, {ty}, ops, "sqrt", ty, loc);
3062 case NEON::BI__builtin_neon_vrbit_v:
3063 case NEON::BI__builtin_neon_vrbitq_v:
3064 case NEON::BI__builtin_neon_vmaxv_f16:
3065 case NEON::BI__builtin_neon_vmaxvq_f16:
3066 case NEON::BI__builtin_neon_vminv_f16:
3067 case NEON::BI__builtin_neon_vminvq_f16:
3068 case NEON::BI__builtin_neon_vmaxnmv_f16:
3069 case NEON::BI__builtin_neon_vmaxnmvq_f16:
3070 case NEON::BI__builtin_neon_vminnmv_f16:
3071 case NEON::BI__builtin_neon_vminnmvq_f16:
3072 case NEON::BI__builtin_neon_vmul_n_f64:
3073 cgm.errorNYI(expr->getSourceRange(),
3074 std::string("unimplemented AArch64 builtin call: ") +
3075 getContext().BuiltinInfo.getName(builtinID));
3076 return mlir::Value{};
3077 case NEON::BI__builtin_neon_vaddlv_u8:
3078 case NEON::BI__builtin_neon_vaddlvq_u8:
3079 case NEON::BI__builtin_neon_vaddlv_u16:
3080 case NEON::BI__builtin_neon_vaddlvq_u16:
3081 case NEON::BI__builtin_neon_vaddlv_s8:
3082 case NEON::BI__builtin_neon_vaddlvq_s8:
3083 case NEON::BI__builtin_neon_vaddlv_s16:
3084 case NEON::BI__builtin_neon_vaddlvq_s16: {
3085 mlir::Type argTy = convertType(expr->getArg(0)->getType());
3086 mlir::Type userRetTy = convertType(expr->getType());
3087 auto eltTy = mlir::cast<cir::IntType>(
3088 mlir::cast<cir::VectorType>(argTy).getElementType());
3089 bool isUnsigned = !eltTy.isSigned();
3090 // These builtins only use 8 and 16-bit element vectors; the intrinsic
3091 // always produces i32. The C result is i32 for 16-bit elements, but i16
3092 // for 8-bit elements, so we emit at i32 and narrow only in that case.
3093 bool needsTrunc = eltTy.getWidth() == 8;
3094 intrName = isUnsigned ? "aarch64.neon.uaddlv" : "aarch64.neon.saddlv";
3095 mlir::Type intrRetTy = userRetTy;
3096 if (needsTrunc)
3097 intrRetTy = isUnsigned ? builder.getUInt32Ty() : builder.getSInt32Ty();
3098 mlir::Value result =
3099 emitNeonCall(cgm, builder, {argTy}, ops, intrName, intrRetTy, loc);
3100 if (needsTrunc)
3101 result = builder.createIntCast(result, userRetTy);
3102 return result;
3103 }
3104 case NEON::BI__builtin_neon_vsri_n_v:
3105 case NEON::BI__builtin_neon_vsriq_n_v: {
3107 ops[0], ops[1], builder.createIntCast(ops[2], builder.getUInt32Ty())};
3108 return emitNeonCall(cgm, builder, {ty, ty, builder.getUInt32Ty()}, vsriArgs,
3109 "aarch64.neon.vsri", ty, loc);
3110 }
3111 case NEON::BI__builtin_neon_vsli_n_v:
3112 case NEON::BI__builtin_neon_vsliq_n_v: {
3113
3114 intrName = "aarch64.neon.vsli";
3115
3116 llvm::SmallVector<mlir::Type> argTypes = {ty, ty, ops[2].getType()};
3117
3118 return emitNeonCall(cgm, builder, argTypes, ops, intrName, ty, loc,
3119 /*isConstrainedFPIntrinsic=*/false,
3120 /*shift=*/0, /*rightshift=*/false);
3121 }
3122 case NEON::BI__builtin_neon_vsra_n_v:
3123 case NEON::BI__builtin_neon_vsraq_n_v: {
3124 ops[0] = builder.createBitcast(ops[0], ty);
3125 ops[1] = emitNeonRShiftImm(*this, ops[1], ops[2], ty, usgn, loc);
3126 return builder.createAdd(loc, ops[0], ops[1]);
3127 }
3128 case NEON::BI__builtin_neon_vrsra_n_v:
3129 case NEON::BI__builtin_neon_vrsraq_n_v: {
3130 intrName = usgn ? "aarch64.neon.urshl" : "aarch64.neon.srshl";
3131 // The llvm intrinsic is expecting negative shift amount for right shift.
3132 // Thus we have to make shift amount vec type to be signed.
3133 cir::VectorType shiftAmtVecTy =
3134 usgn ? getSignChangedVectorType(builder, ty) : ty;
3135 llvm::SmallVector<mlir::Value, 2> tmpOps = {ops[1], ops[2]};
3136 mlir::Value tmp = emitNeonCall(cgm, builder, {ty, shiftAmtVecTy}, tmpOps,
3137 intrName, ty, loc,
3138 /*isConstrainedFPIntrinsic=*/false,
3139 /*shift=*/1, /*rightshift=*/true);
3140 ops[0] = builder.createBitcast(ops[0], ty);
3141 return builder.createAdd(loc, ops[0], tmp);
3142 }
3143 case NEON::BI__builtin_neon_vld1_v:
3144 case NEON::BI__builtin_neon_vld1q_v:
3145 case NEON::BI__builtin_neon_vst1_v:
3146 case NEON::BI__builtin_neon_vst1q_v:
3147 case NEON::BI__builtin_neon_vld1_lane_v:
3148 case NEON::BI__builtin_neon_vld1q_lane_v:
3149 case NEON::BI__builtin_neon_vldap1_lane_s64:
3150 case NEON::BI__builtin_neon_vldap1q_lane_s64:
3151 case NEON::BI__builtin_neon_vld1_dup_v:
3152 case NEON::BI__builtin_neon_vld1q_dup_v:
3153 case NEON::BI__builtin_neon_vst1_lane_v:
3154 case NEON::BI__builtin_neon_vst1q_lane_v:
3155 case NEON::BI__builtin_neon_vstl1_lane_s64:
3156 case NEON::BI__builtin_neon_vstl1q_lane_s64:
3157 case NEON::BI__builtin_neon_vld2_v:
3158 case NEON::BI__builtin_neon_vld2q_v:
3159 case NEON::BI__builtin_neon_vld3_v:
3160 case NEON::BI__builtin_neon_vld3q_v:
3161 case NEON::BI__builtin_neon_vld4_v:
3162 case NEON::BI__builtin_neon_vld4q_v:
3163 case NEON::BI__builtin_neon_vld2_dup_v:
3164 case NEON::BI__builtin_neon_vld2q_dup_v:
3165 case NEON::BI__builtin_neon_vld3_dup_v:
3166 case NEON::BI__builtin_neon_vld3q_dup_v:
3167 case NEON::BI__builtin_neon_vld4_dup_v:
3168 case NEON::BI__builtin_neon_vld4q_dup_v:
3169 case NEON::BI__builtin_neon_vld2_lane_v:
3170 case NEON::BI__builtin_neon_vld2q_lane_v:
3171 case NEON::BI__builtin_neon_vld3_lane_v:
3172 case NEON::BI__builtin_neon_vld3q_lane_v:
3173 case NEON::BI__builtin_neon_vld4_lane_v:
3174 case NEON::BI__builtin_neon_vld4q_lane_v:
3175 case NEON::BI__builtin_neon_vst2_v:
3176 case NEON::BI__builtin_neon_vst2q_v:
3177 case NEON::BI__builtin_neon_vst2_lane_v:
3178 case NEON::BI__builtin_neon_vst2q_lane_v:
3179 case NEON::BI__builtin_neon_vst3_v:
3180 case NEON::BI__builtin_neon_vst3q_v:
3181 case NEON::BI__builtin_neon_vst3_lane_v:
3182 case NEON::BI__builtin_neon_vst3q_lane_v:
3183 case NEON::BI__builtin_neon_vst4_v:
3184 case NEON::BI__builtin_neon_vst4q_v:
3185 case NEON::BI__builtin_neon_vst4_lane_v:
3186 case NEON::BI__builtin_neon_vst4q_lane_v:
3187 cgm.errorNYI(expr->getSourceRange(),
3188 std::string("unimplemented AArch64 builtin call: ") +
3189 getContext().BuiltinInfo.getName(builtinID));
3190 return mlir::Value{};
3191 case NEON::BI__builtin_neon_vtrn_v:
3192 case NEON::BI__builtin_neon_vtrnq_v: {
3193 ops[1] = builder.createBitcast(ops[1], ty);
3194 ops[2] = builder.createBitcast(ops[2], ty);
3195 // Adding a bitcast here as Ops[0] might be a void pointer.
3196 mlir::Value baseAddr =
3197 builder.createBitcast(ops[0], builder.getPointerTo(ty));
3198 mlir::Value sv;
3199
3200 for (unsigned vi = 0; vi != 2; ++vi) {
3202 for (unsigned i = 0, e = ty.getSize(); i != e; i += 2) {
3203 indices.push_back(i + vi);
3204 indices.push_back(i + e + vi);
3205 }
3206 cir::ConstantOp idx = builder.getConstInt(loc, builder.getSInt32Ty(), vi);
3207 mlir::Value addr = builder.createPtrStride(loc, baseAddr, idx);
3208 sv = builder.createVecShuffle(loc, ops[1], ops[2], indices);
3209 (void)builder.CIRBaseBuilderTy::createStore(loc, sv, addr);
3210 }
3211 return sv;
3212 }
3213 case NEON::BI__builtin_neon_vuzp_v:
3214 case NEON::BI__builtin_neon_vuzpq_v: {
3215 ops[1] = builder.createBitcast(ops[1], ty);
3216 ops[2] = builder.createBitcast(ops[2], ty);
3217 // Adding a bitcast here as Ops[0] might be a void pointer.
3218 mlir::Value baseAddr =
3219 builder.createBitcast(ops[0], builder.getPointerTo(ty));
3220 mlir::Value sv;
3221 for (unsigned vi = 0; vi != 2; ++vi) {
3223 for (unsigned i = 0, e = ty.getSize(); i != e; ++i) {
3224 indices.push_back(2 * i + vi);
3225 }
3226 cir::ConstantOp idx = builder.getConstInt(loc, builder.getSInt32Ty(), vi);
3227 mlir::Value addr = builder.createPtrStride(loc, baseAddr, idx);
3228 sv = builder.createVecShuffle(loc, ops[1], ops[2], indices);
3229 (void)builder.CIRBaseBuilderTy::createStore(loc, sv, addr);
3230 }
3231 return sv;
3232 }
3233 case NEON::BI__builtin_neon_vzip_v:
3234 case NEON::BI__builtin_neon_vzipq_v: {
3235 ops[1] = builder.createBitcast(ops[1], ty);
3236 ops[2] = builder.createBitcast(ops[2], ty);
3237 // Adding a bitcast here as Ops[0] might be a void pointer.
3238 mlir::Value baseAddr =
3239 builder.createBitcast(ops[0], builder.getPointerTo(ty));
3240 mlir::Value sv;
3241 for (unsigned vi = 0; vi != 2; ++vi) {
3243 for (unsigned i = 0, e = ty.getSize(); i != e; i += 2) {
3244 indices.push_back((i + vi * e) >> 1);
3245 indices.push_back(((i + vi * e) >> 1) + e);
3246 }
3247 cir::ConstantOp idx = builder.getConstInt(loc, builder.getSInt32Ty(), vi);
3248 mlir::Value addr = builder.createPtrStride(loc, baseAddr, idx);
3249 sv = builder.createVecShuffle(loc, ops[1], ops[2], indices);
3250 (void)builder.CIRBaseBuilderTy::createStore(loc, sv, addr);
3251 }
3252 return sv;
3253 }
3254 case NEON::BI__builtin_neon_vqtbl1q_v:
3255 case NEON::BI__builtin_neon_vqtbl2q_v:
3256 case NEON::BI__builtin_neon_vqtbl3q_v:
3257 case NEON::BI__builtin_neon_vqtbl4q_v:
3258 case NEON::BI__builtin_neon_vqtbx1q_v:
3259 case NEON::BI__builtin_neon_vqtbx2q_v:
3260 case NEON::BI__builtin_neon_vqtbx3q_v:
3261 case NEON::BI__builtin_neon_vqtbx4q_v:
3262 case NEON::BI__builtin_neon_vsqadd_v:
3263 case NEON::BI__builtin_neon_vsqaddq_v:
3264 case NEON::BI__builtin_neon_vuqadd_v:
3265 case NEON::BI__builtin_neon_vuqaddq_v:
3266 case NEON::BI__builtin_neon_vluti2_laneq_mf8:
3267 case NEON::BI__builtin_neon_vluti2_laneq_bf16:
3268 case NEON::BI__builtin_neon_vluti2_laneq_f16:
3269 case NEON::BI__builtin_neon_vluti2_laneq_p16:
3270 case NEON::BI__builtin_neon_vluti2_laneq_p8:
3271 case NEON::BI__builtin_neon_vluti2_laneq_s16:
3272 case NEON::BI__builtin_neon_vluti2_laneq_s8:
3273 case NEON::BI__builtin_neon_vluti2_laneq_u16:
3274 case NEON::BI__builtin_neon_vluti2_laneq_u8:
3275 case NEON::BI__builtin_neon_vluti2q_laneq_mf8:
3276 case NEON::BI__builtin_neon_vluti2q_laneq_bf16:
3277 case NEON::BI__builtin_neon_vluti2q_laneq_f16:
3278 case NEON::BI__builtin_neon_vluti2q_laneq_p16:
3279 case NEON::BI__builtin_neon_vluti2q_laneq_p8:
3280 case NEON::BI__builtin_neon_vluti2q_laneq_s16:
3281 case NEON::BI__builtin_neon_vluti2q_laneq_s8:
3282 case NEON::BI__builtin_neon_vluti2q_laneq_u16:
3283 case NEON::BI__builtin_neon_vluti2q_laneq_u8:
3284 case NEON::BI__builtin_neon_vluti2_lane_mf8:
3285 case NEON::BI__builtin_neon_vluti2_lane_bf16:
3286 case NEON::BI__builtin_neon_vluti2_lane_f16:
3287 case NEON::BI__builtin_neon_vluti2_lane_p16:
3288 case NEON::BI__builtin_neon_vluti2_lane_p8:
3289 case NEON::BI__builtin_neon_vluti2_lane_s16:
3290 case NEON::BI__builtin_neon_vluti2_lane_s8:
3291 case NEON::BI__builtin_neon_vluti2_lane_u16:
3292 case NEON::BI__builtin_neon_vluti2_lane_u8:
3293 case NEON::BI__builtin_neon_vluti2q_lane_mf8:
3294 case NEON::BI__builtin_neon_vluti2q_lane_bf16:
3295 case NEON::BI__builtin_neon_vluti2q_lane_f16:
3296 case NEON::BI__builtin_neon_vluti2q_lane_p16:
3297 case NEON::BI__builtin_neon_vluti2q_lane_p8:
3298 case NEON::BI__builtin_neon_vluti2q_lane_s16:
3299 case NEON::BI__builtin_neon_vluti2q_lane_s8:
3300 case NEON::BI__builtin_neon_vluti2q_lane_u16:
3301 case NEON::BI__builtin_neon_vluti2q_lane_u8:
3302 case NEON::BI__builtin_neon_vluti4q_lane_mf8:
3303 case NEON::BI__builtin_neon_vluti4q_lane_p8:
3304 case NEON::BI__builtin_neon_vluti4q_lane_s8:
3305 case NEON::BI__builtin_neon_vluti4q_lane_u8:
3306 case NEON::BI__builtin_neon_vluti4q_laneq_mf8:
3307 case NEON::BI__builtin_neon_vluti4q_laneq_p8:
3308 case NEON::BI__builtin_neon_vluti4q_laneq_s8:
3309 case NEON::BI__builtin_neon_vluti4q_laneq_u8:
3310 case NEON::BI__builtin_neon_vluti4q_lane_bf16_x2:
3311 case NEON::BI__builtin_neon_vluti4q_lane_f16_x2:
3312 case NEON::BI__builtin_neon_vluti4q_lane_p16_x2:
3313 case NEON::BI__builtin_neon_vluti4q_lane_s16_x2:
3314 case NEON::BI__builtin_neon_vluti4q_lane_u16_x2:
3315 case NEON::BI__builtin_neon_vluti4q_laneq_bf16_x2:
3316 case NEON::BI__builtin_neon_vluti4q_laneq_f16_x2:
3317 case NEON::BI__builtin_neon_vluti4q_laneq_p16_x2:
3318 case NEON::BI__builtin_neon_vluti4q_laneq_s16_x2:
3319 case NEON::BI__builtin_neon_vluti4q_laneq_u16_x2:
3320 case NEON::BI__builtin_neon_vmmlaq_f16_mf8_fpm:
3321 case NEON::BI__builtin_neon_vmmlaq_f32_mf8_fpm:
3322 case NEON::BI__builtin_neon_vcvt1_low_bf16_mf8_fpm:
3323 case NEON::BI__builtin_neon_vcvt1_bf16_mf8_fpm:
3324 case NEON::BI__builtin_neon_vcvt1_high_bf16_mf8_fpm:
3325 case NEON::BI__builtin_neon_vcvt2_low_bf16_mf8_fpm:
3326 case NEON::BI__builtin_neon_vcvt2_bf16_mf8_fpm:
3327 case NEON::BI__builtin_neon_vcvt2_high_bf16_mf8_fpm:
3328 case NEON::BI__builtin_neon_vcvt1_low_f16_mf8_fpm:
3329 case NEON::BI__builtin_neon_vcvt1_f16_mf8_fpm:
3330 case NEON::BI__builtin_neon_vcvt1_high_f16_mf8_fpm:
3331 case NEON::BI__builtin_neon_vcvt2_low_f16_mf8_fpm:
3332 case NEON::BI__builtin_neon_vcvt2_f16_mf8_fpm:
3333 case NEON::BI__builtin_neon_vcvt2_high_f16_mf8_fpm:
3334 case NEON::BI__builtin_neon_vcvt_mf8_f32_fpm:
3335 case NEON::BI__builtin_neon_vcvt_mf8_f16_fpm:
3336 case NEON::BI__builtin_neon_vcvtq_mf8_f16_fpm:
3337 case NEON::BI__builtin_neon_vcvt_high_mf8_f32_fpm:
3338 case NEON::BI__builtin_neon_vdot_f16_mf8_fpm:
3339 case NEON::BI__builtin_neon_vdotq_f16_mf8_fpm:
3340 case NEON::BI__builtin_neon_vdot_lane_f16_mf8_fpm:
3341 case NEON::BI__builtin_neon_vdotq_lane_f16_mf8_fpm:
3342 case NEON::BI__builtin_neon_vdot_laneq_f16_mf8_fpm:
3343 case NEON::BI__builtin_neon_vdotq_laneq_f16_mf8_fpm:
3344 case NEON::BI__builtin_neon_vdot_f32_mf8_fpm:
3345 case NEON::BI__builtin_neon_vdotq_f32_mf8_fpm:
3346 case NEON::BI__builtin_neon_vdot_lane_f32_mf8_fpm:
3347 case NEON::BI__builtin_neon_vdotq_lane_f32_mf8_fpm:
3348 case NEON::BI__builtin_neon_vdot_laneq_f32_mf8_fpm:
3349 case NEON::BI__builtin_neon_vdotq_laneq_f32_mf8_fpm:
3350 case NEON::BI__builtin_neon_vmlalbq_f16_mf8_fpm:
3351 case NEON::BI__builtin_neon_vmlaltq_f16_mf8_fpm:
3352 case NEON::BI__builtin_neon_vmlallbbq_f32_mf8_fpm:
3353 case NEON::BI__builtin_neon_vmlallbtq_f32_mf8_fpm:
3354 case NEON::BI__builtin_neon_vmlalltbq_f32_mf8_fpm:
3355 case NEON::BI__builtin_neon_vmlallttq_f32_mf8_fpm:
3356 case NEON::BI__builtin_neon_vmlalbq_lane_f16_mf8_fpm:
3357 case NEON::BI__builtin_neon_vmlalbq_laneq_f16_mf8_fpm:
3358 case NEON::BI__builtin_neon_vmlaltq_lane_f16_mf8_fpm:
3359 case NEON::BI__builtin_neon_vmlaltq_laneq_f16_mf8_fpm:
3360 case NEON::BI__builtin_neon_vmlallbbq_lane_f32_mf8_fpm:
3361 case NEON::BI__builtin_neon_vmlallbbq_laneq_f32_mf8_fpm:
3362 case NEON::BI__builtin_neon_vmlallbtq_lane_f32_mf8_fpm:
3363 case NEON::BI__builtin_neon_vmlallbtq_laneq_f32_mf8_fpm:
3364 case NEON::BI__builtin_neon_vmlalltbq_lane_f32_mf8_fpm:
3365 case NEON::BI__builtin_neon_vmlalltbq_laneq_f32_mf8_fpm:
3366 case NEON::BI__builtin_neon_vmlallttq_lane_f32_mf8_fpm:
3367 case NEON::BI__builtin_neon_vmlallttq_laneq_f32_mf8_fpm:
3368 case NEON::BI__builtin_neon_vamin_f16:
3369 case NEON::BI__builtin_neon_vaminq_f16:
3370 case NEON::BI__builtin_neon_vamin_f32:
3371 case NEON::BI__builtin_neon_vaminq_f32:
3372 case NEON::BI__builtin_neon_vaminq_f64:
3373 case NEON::BI__builtin_neon_vamax_f16:
3374 case NEON::BI__builtin_neon_vamaxq_f16:
3375 case NEON::BI__builtin_neon_vamax_f32:
3376 case NEON::BI__builtin_neon_vamaxq_f32:
3377 case NEON::BI__builtin_neon_vamaxq_f64:
3378 case NEON::BI__builtin_neon_vscale_f16:
3379 case NEON::BI__builtin_neon_vscaleq_f16:
3380 case NEON::BI__builtin_neon_vscale_f32:
3381 case NEON::BI__builtin_neon_vscaleq_f32:
3382 case NEON::BI__builtin_neon_vscaleq_f64:
3383 cgm.errorNYI(expr->getSourceRange(),
3384 std::string("unimplemented AArch64 builtin call: ") +
3385 getContext().BuiltinInfo.getName(builtinID));
3386 return mlir::Value{};
3387 }
3388
3389 // Unreachable: All cases in the switch above return.
3390}
Utilities used for generating code for AArch64 that are shared between the classic and ClangIR code-g...
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
Defines enum values for all the target-independent builtin functions.
static bool hasExtraNeonArgument(unsigned builtinID)
Return true if BuiltinID is an overloaded Neon intrinsic with an extra argument that specifies the ve...
static bool aarch64SVEIntrinsicsProvenSorted
static const std::pair< unsigned, unsigned > neonEquivalentIntrinsicMap[]
static mlir::Value emitCommonNeonSISDBuiltinExpr(CIRGenFunction &cgf, const ARMNeonVectorIntrinsicInfo &info, llvm::SmallVectorImpl< mlir::Value > &ops, const CallExpr *expr)
static std::pair< mlir::Type, llvm::SmallVector< mlir::Type > > deriveNeonSISDIntrinsicOperandTypes(CIRGenFunction &cgf, unsigned modifier, mlir::Type arg0Ty, mlir::Type resultTy, llvm::ArrayRef< mlir::Value > ops)
static mlir::Value emitNeonSplat(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value v, mlir::Value lane, unsigned int resEltCnt)
static mlir::Value emitNeonCallToOp(CIRGenModule &cgm, CIRGenBuilderTy &builder, llvm::SmallVector< mlir::Type > argTypes, llvm::SmallVectorImpl< mlir::Value > &args, std::optional< llvm::StringRef > intrinsicName, mlir::Type funcResTy, mlir::Location loc, bool isConstrainedFPIntrinsic=false, unsigned shift=0, bool rightshift=false)
static cir::VectorType getSVEVectorForElementType(CIRGenModule &cgm, mlir::Type eltTy)
static unsigned getSVEMinEltCount(clang::SVETypeFlags::EltType sveType)
static mlir::Value genVscaleTimesFactor(mlir::Location loc, CIRGenBuilderTy builder, mlir::Type cirTy, int32_t scalingFactor)
static cir::VectorType getFloatNeonType(CIRGenFunction &cgf, NeonTypeFlags intTypeFlags)
static llvm::StringRef getLLVMIntrNameNoPrefix(llvm::Intrinsic::ID intrID)
static int64_t getIntValueFromConstOp(mlir::Value val)
static const AArch64SVEAndSMEVectorIntrinsicInfo aarch64SVEIntrinsicMap[]
static mlir::Value emitCallMaybeConstrainedBuiltin(CIRGenBuilderTy &builder, mlir::Location loc, StringRef intrName, mlir::Type retTy, llvm::SmallVector< mlir::Value > &ops)
static mlir::Value emitCommonNeonBuiltinExpr(CIRGenFunction &cgf, unsigned builtinID, unsigned llvmIntrinsic, unsigned altLLVMIntrinsic, const char *nameHint, unsigned modifier, const CallExpr *expr, llvm::SmallVectorImpl< mlir::Value > &ops)
static mlir::Value emitNeonCall(CIRGenModule &cgm, CIRGenBuilderTy &builder, llvm::SmallVector< mlir::Type > argTypes, llvm::SmallVectorImpl< mlir::Value > &args, llvm::StringRef intrinsicName, mlir::Type funcResTy, mlir::Location loc, bool isConstrainedFPIntrinsic=false, unsigned shift=0, bool rightshift=false)
static cir::VectorType getSignChangedVectorType(CIRGenBuilderTy &builder, cir::VectorType vecTy)
Flip the signedness of vecTy's element type, keeping the width and number of lanes the same.
static cir::VectorType getNeonPairwiseWidenInputType(cir::VectorType resType, bool usgn)
static mlir::Value emitCommonNeonShift(CIRGenBuilderTy &builder, mlir::Location loc, cir::VectorType resTy, mlir::Value shifTgt, mlir::Value shiftAmt, bool shiftLeft)
static bool aarch64SIMDIntrinsicsProvenSorted
static cir::VectorType getIntVecFromVecTy(CIRGenBuilderTy &builder, cir::VectorType vecTy)
constexpr unsigned sveBitsPerBlock
static mlir::Value emitNeonShiftVector(CIRGenBuilderTy &builder, mlir::Value shiftVal, cir::VectorType vecTy, mlir::Location loc, bool neg)
Build a constant shift amount vector of vecTy to shift a vector Here shiftVal is a constant integer t...
static const IntrinsicInfo * findARMVectorIntrinsicInMap(ArrayRef< IntrinsicInfo > intrinsicMap, unsigned builtinID, bool &mapProvenSorted)
static mlir::Value emitAArch64CompareBuiltinExpr(CIRGenFunction &cgf, CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value src, mlir::Type retTy, const cir::CmpOpKind kind)
static mlir::Value emitNeonRShiftImm(CIRGenFunction &cgf, mlir::Value shiftVec, mlir::Value shiftVal, cir::VectorType vecTy, bool usgn, mlir::Location loc)
static cir::VectorType getNeonType(CIRGenFunction *cgf, NeonTypeFlags typeFlags, mlir::Location loc, bool hasLegalHalfType=true, bool v1Ty=false, bool allowBFloatArgsAndRet=true)
static bool aarch64SISDIntrinsicsProvenSorted
TokenType getType() const
Returns the token's type, e.g.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Enumerates target-specific builtins in their own namespaces within namespace clang.
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
Builtin::Context & BuiltinInfo
Definition ASTContext.h:804
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs=nullptr) const
Return the type for the specified builtin.
@ GE_None
No error.
std::string getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
Definition Builtins.cpp:80
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc)
mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str, const mlir::Type &resTy, Operands &&...op)
cir::IntType getSIntNTy(int n)
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef< mlir::Attribute > maskAttrs)
cir::ConstantOp getZero(mlir::Location loc, mlir::Type ty)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::VectorType getExtendedOrTruncatedElementVectorType(cir::VectorType vt, bool isExtended, bool isSigned=false)
cir::IntType getUIntNTy(int n)
mlir::Type convertType(clang::QualType t)
const TargetInfo & getTarget() const
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
static int64_t getZExtIntValueFromConstOp(mlir::Value val)
Get zero-extended integer from a mlir::Value that is an int constant or a constant op.
mlir::Value emitSVEPredicateCast(mlir::Value pred, unsigned minNumElts, mlir::Location loc)
bool getAArch64SVEProcessedOperands(unsigned builtinID, const CallExpr *expr, SmallVectorImpl< mlir::Value > &ops, clang::SVETypeFlags typeFlags)
Address returnValue
The temporary alloca to hold the return value.
std::optional< mlir::Value > emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, ReturnValueSlot returnValue, llvm::Triple::ArchType arch)
std::optional< mlir::Value > emitAArch64SMEBuiltinExpr(unsigned builtinID, const CallExpr *expr)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
CIRGenBuilderTy & getBuilder()
clang::ASTContext & getContext() const
std::optional< mlir::Value > emitAArch64SVEBuiltinExpr(unsigned builtinID, const CallExpr *expr)
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx, const Expr *argExpr)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
const cir::CIRDataLayout getDataLayout() const
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:260
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
This represents one expression.
Definition Expr.h:112
Flags to identify the types for overloaded Neon builtins.
EltType getEltType() const
Flags to identify the types for overloaded SVE builtins.
bool isReverseUSDOT() const
bool isGatherLoad() const
EltType getEltType() const
bool isPrefetch() const
bool isTupleSet() const
bool isReverseMergeAnyAccOp() const
bool isTupleGet() const
bool isInsertOp1SVALL() const
bool isAppendSVALL() const
bool isReverseMergeAnyBinOp() const
bool isStructStore() const
bool isTupleCreate() const
bool isGatherPrefetch() const
bool hasSplatOperand() const
MergeType getMergeType() const
bool isStructLoad() const
unsigned getSplatOperand() const
bool isScatterStore() const
bool isReverseCompare() const
virtual bool hasFastHalfType() const
Determine whether the target has fast native support for operations on half types.
Definition TargetInfo.h:712
const ARMNeonVectorIntrinsicInfo AArch64SISDIntrinsicMap[]
const ARMNeonVectorIntrinsicInfo AArch64SIMDIntrinsicMap[]
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
static bool msvcBuiltins()
static bool handleBuiltinICEArguments()
static bool aarch64SIMDIntrinsics()
static bool aarch64SVEIntrinsics()
static bool emitConstrainedFPCall()
static bool aarch64SMEIntrinsics()
static bool aarch64TblBuiltinExpr()
Describes an AArch64 SVE or SME intrinsic.
Describes an ARM or AArch64 NEON intrinsic, or an AArch64 SISD intrinsic.