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