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 {#NameBase, SVE::BI__builtin_sve_##NameBase, Intrinsic::LLVMIntrinsic, 0, \
49 TypeModifier}
50
51#define SVEMAP2(NameBase, TypeModifier) \
52 {#NameBase, SVE::BI__builtin_sve_##NameBase, 0, 0, TypeModifier}
54#define GET_SVE_LLVM_INTRINSIC_MAP
55#include "clang/Basic/arm_sve_builtin_cg.inc"
56#undef GET_SVE_LLVM_INTRINSIC_MAP
57};
58
62
63// Check if Builtin `builtinId` is present in `intrinsicMap`. If yes, returns
64// the corresponding info struct.
65static const ARMVectorIntrinsicInfo *
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 ARMVectorIntrinsicInfo *info =
77 llvm::lower_bound(intrinsicMap, builtinID);
78
79 if (info != intrinsicMap.end() && info->BuiltinID == builtinID)
80 return info;
81
82 return nullptr;
83}
84
85//===----------------------------------------------------------------------===//
86// Generic helpers
87//===----------------------------------------------------------------------===//
88static llvm::StringRef getLLVMIntrNameNoPrefix(llvm::Intrinsic::ID intrID) {
89 llvm::StringRef llvmIntrName = llvm::Intrinsic::getBaseName(intrID);
90 assert(llvmIntrName.starts_with("llvm.") && "Not an LLVM intrinsic!");
91 return llvmIntrName.drop_front(/*strlen("llvm.")=*/5);
92}
93
94//===----------------------------------------------------------------------===//
95// NEON helpers
96//===----------------------------------------------------------------------===//
97/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
98/// argument that specifies the vector type. The additional argument is meant
99/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function
100/// should be kept consistent with the logic in Sema.
101/// TODO: Make this return false for SISD builtins.
102/// TODO(cir): Share this with ARM.cpp
103static bool hasExtraNeonArgument(unsigned builtinID) {
104 // Required by the headers included below, but not in this particular
105 // function.
106 [[maybe_unused]] int PtrArgNum = -1;
107 [[maybe_unused]] bool HasConstPtr = false;
108
109 // The mask encodes the type. We don't care about the actual value. Instead,
110 // we just check whether its been set.
111 uint64_t mask = 0;
112 switch (builtinID) {
113#define GET_NEON_OVERLOAD_CHECK
114#include "clang/Basic/arm_fp16.inc"
115#include "clang/Basic/arm_neon.inc"
116#undef GET_NEON_OVERLOAD_CHECK
117 // Non-neon builtins for controling VFP that take extra argument for
118 // discriminating the type.
119 case ARM::BI__builtin_arm_vcvtr_f:
120 case ARM::BI__builtin_arm_vcvtr_d:
121 mask = 1;
122 }
123 switch (builtinID) {
124 default:
125 break;
126 }
127
128 return mask != 0;
129}
130
131static cir::VectorType getFloatNeonType(CIRGenFunction &cgf,
132 NeonTypeFlags intTypeFlags) {
133 int isQuad = intTypeFlags.isQuad();
134 switch (intTypeFlags.getEltType()) {
136 return cir::VectorType::get(cgf.fP16Ty, (4 << isQuad));
138 return cir::VectorType::get(cgf.floatTy, (2 << isQuad));
140 return cir::VectorType::get(cgf.doubleTy, (1 << isQuad));
141 default:
142 llvm_unreachable("Type can't be converted to floating-point!");
143 }
144}
145
146static int64_t getIntValueFromConstOp(mlir::Value val) {
147 return val.getDefiningOp<cir::ConstantOp>().getIntValue().getSExtValue();
148}
149
150/// Build a constant shift amount vector of `vecTy` to shift a vector
151/// Here `shiftVal` is a constant integer that will be broadcast into a
152/// a const vector of `vecTy` which is the return value of this function
153/// If `neg` is true, the shift amount is negated before splatting (used
154/// when encoding a right shift as a left shift by a negative amount for
155/// intrinsics like aarch64.neon.{s,u}rshl).
156static mlir::Value emitNeonShiftVector(CIRGenBuilderTy &builder,
157 mlir::Value shiftVal,
158 cir::VectorType vecTy,
159 mlir::Location loc, bool neg) {
160 if (neg) {
161 int64_t shiftAmt = -getIntValueFromConstOp(shiftVal);
162 shiftVal = builder.getConstantInt(loc, vecTy.getElementType(), shiftAmt);
163 }
164 mlir::Type eltTy = vecTy.getElementType();
165 if (shiftVal.getType() != eltTy) {
166 shiftVal = builder.createIntCast(shiftVal, eltTy);
167 }
168 return cir::VecSplatOp::create(builder, loc, vecTy, shiftVal);
169}
170
171// TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.
172template <typename Operation>
173static mlir::Value
177 std::optional<llvm::StringRef> intrinsicName,
178 mlir::Type funcResTy, mlir::Location loc,
179 bool isConstrainedFPIntrinsic = false, unsigned shift = 0,
180 bool rightshift = false) {
181 // TODO(cir): Consider removing the following unreachable when we have
182 // emitConstrainedFPCall feature implemented
184 if (isConstrainedFPIntrinsic)
185 cgm.errorNYI(loc, std::string("constrained FP intrinsic"));
186
187 for (unsigned j = 0; j < argTypes.size(); ++j) {
188 if (isConstrainedFPIntrinsic) {
190 }
191 if (shift > 0 && shift == j) {
192 args[j] = emitNeonShiftVector(builder, args[j],
193 mlir::cast<cir::VectorType>(argTypes[j]),
194 loc, rightshift);
195 } else {
196 args[j] = builder.createBitcast(args[j], argTypes[j]);
197 }
198 }
199 if (isConstrainedFPIntrinsic) {
201 return nullptr;
202 }
203 if constexpr (std::is_same_v<Operation, cir::LLVMIntrinsicCallOp>) {
204 return Operation::create(builder, loc,
205 builder.getStringAttr(intrinsicName.value()),
206 funcResTy, args)
207 .getResult();
208 } else {
209 return Operation::create(builder, loc, funcResTy, args).getResult();
210 }
211}
212
213// TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.
214static mlir::Value emitNeonCall(CIRGenModule &cgm, CIRGenBuilderTy &builder,
217 llvm::StringRef intrinsicName,
218 mlir::Type funcResTy, mlir::Location loc,
219 bool isConstrainedFPIntrinsic = false,
220 unsigned shift = 0, bool rightshift = false) {
222 cgm, builder, std::move(argTypes), args, intrinsicName, funcResTy, loc,
223 isConstrainedFPIntrinsic, shift, rightshift);
224}
225
227 CIRGenFunction &cgf, const ARMVectorIntrinsicInfo &info,
229 assert(info.LLVMIntrinsic && "Generic code assumes a valid intrinsic");
230
231 switch (info.BuiltinID) {
232 case NEON::BI__builtin_neon_vcled_s64:
233 case NEON::BI__builtin_neon_vcled_u64:
234 case NEON::BI__builtin_neon_vcles_f32:
235 case NEON::BI__builtin_neon_vcled_f64:
236 case NEON::BI__builtin_neon_vcltd_s64:
237 case NEON::BI__builtin_neon_vcltd_u64:
238 case NEON::BI__builtin_neon_vclts_f32:
239 case NEON::BI__builtin_neon_vcltd_f64:
240 case NEON::BI__builtin_neon_vcales_f32:
241 case NEON::BI__builtin_neon_vcaled_f64:
242 case NEON::BI__builtin_neon_vcalts_f32:
243 case NEON::BI__builtin_neon_vcaltd_f64:
244 cgf.cgm.errorNYI(expr->getSourceRange(),
245 std::string("unimplemented AArch64 builtin call: ") +
247 break;
248 }
249
250 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
251 static_cast<llvm::Intrinsic::ID>(info.LLVMIntrinsic));
252 mlir::Location loc = cgf.getLoc(expr->getExprLoc());
253
254 // The switch stmt is intended to help catch NYI cases and will be removed
255 // once the CIR implementation is complete. Avoid adding specialized
256 // code in cases - that should only be required for a handful of examples.
257 switch (info.BuiltinID) {
258 default:
259 cgf.cgm.errorNYI(expr->getSourceRange(),
260 std::string("unimplemented AArch64 builtin call: ") +
262 break;
263 case NEON::BI__builtin_neon_vabdd_f64:
264 case NEON::BI__builtin_neon_vabds_f32:
265 case NEON::BI__builtin_neon_vshld_s64:
266 case NEON::BI__builtin_neon_vshld_u64:
267 case NEON::BI__builtin_neon_vpmins_f32:
268 case NEON::BI__builtin_neon_vpminqd_f64:
269 case NEON::BI__builtin_neon_vpminnms_f32:
270 case NEON::BI__builtin_neon_vpminnmqd_f64:
271 return emitNeonCall(cgf.cgm, cgf.getBuilder(),
272 {cgf.convertType(expr->getArg(0)->getType())}, ops,
273 llvmIntrName, cgf.convertType(expr->getType()), loc);
274 }
275
276 return nullptr;
277}
278
279//===----------------------------------------------------------------------===//
280// Emit-helpers
281//===----------------------------------------------------------------------===//
282static mlir::Value
284 mlir::Location loc, mlir::Value src,
285 mlir::Type retTy, const cir::CmpOpKind kind) {
286
287 bool scalarCmp = !isa<cir::VectorType>(src.getType());
288 if (!scalarCmp) {
289 assert(!cast<cir::VectorType>(retTy).getIsScalable() &&
290 "This is only intended for fixed-width vectors");
291 // Vector types are cast to i8 vectors. Recover original type.
292 src = builder.createBitcast(src, retTy);
293 }
294
295 mlir::Value zero = builder.getNullValue(src.getType(), loc);
296
297 if (!scalarCmp)
298 return builder.createVecCompare(loc, kind, src, zero);
299
300 // For scalars, cast !cir.bool to !cir.int<s, 1> so that the compare
301 // result is sign- rather zero-extended when casting to the output
302 // retType.
303 mlir::Value cmp = builder.createCast(
304 loc, cir::CastKind::bool_to_int,
305 builder.createCompare(loc, kind, src, zero), builder.getSIntNTy(1));
306
307 return builder.createCast(loc, cir::CastKind::integral, cmp, retTy);
308}
309
310// TODO(cir): Remove `loc` from the list of arguments once all NYIs are gone.
311static cir::VectorType getNeonType(CIRGenFunction *cgf, NeonTypeFlags typeFlags,
312 mlir::Location loc,
313 bool hasLegalHalfType = true,
314 bool v1Ty = false,
315 bool allowBFloatArgsAndRet = true) {
316 int isQuad = typeFlags.isQuad();
317 switch (typeFlags.getEltType()) {
320 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt8Ty
321 : cgf->sInt8Ty,
322 v1Ty ? 1 : (8 << isQuad));
324 return cir::VectorType::get(cgf->uInt8Ty, v1Ty ? 1 : (8 << isQuad));
327 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt16Ty
328 : cgf->sInt16Ty,
329 v1Ty ? 1 : (4 << isQuad));
331 if (allowBFloatArgsAndRet)
332 return cir::VectorType::get(cgf->getCIRGenModule().bFloat16Ty,
333 v1Ty ? 1 : (4 << isQuad));
334 return cir::VectorType::get(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad));
336 if (hasLegalHalfType)
337 return cir::VectorType::get(cgf->getCIRGenModule().fP16Ty,
338 v1Ty ? 1 : (4 << isQuad));
339 return cir::VectorType::get(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad));
341 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt32Ty
342 : cgf->sInt32Ty,
343 v1Ty ? 1 : (2 << isQuad));
346 return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt64Ty
347 : cgf->sInt64Ty,
348 v1Ty ? 1 : (1 << isQuad));
350 // FIXME: i128 and f128 doesn't get fully support in Clang and llvm.
351 // There is a lot of i128 and f128 API missing.
352 // so we use v16i8 to represent poly128 and get pattern matched.
353 cgf->getCIRGenModule().errorNYI(loc, std::string("NEON type: Poly128"));
354 [[fallthrough]];
356 return cir::VectorType::get(cgf->getCIRGenModule().floatTy,
357 v1Ty ? 1 : (2 << isQuad));
359 return cir::VectorType::get(cgf->getCIRGenModule().doubleTy,
360 v1Ty ? 1 : (1 << isQuad));
361 }
362 llvm_unreachable("Unknown vector element type!");
363}
364
365static mlir::Value emitNeonSplat(CIRGenBuilderTy &builder, mlir::Location loc,
366 mlir::Value v, mlir::Value lane,
367 unsigned int resEltCnt) {
368 assert(isa<cir::ConstantOp>(lane.getDefiningOp()) &&
369 "lane number is not a constant!");
370 int64_t laneCst = getIntValueFromConstOp(lane);
371 llvm::SmallVector<int64_t, 4> shuffleMask(resEltCnt, laneCst);
372 return builder.createVecShuffle(loc, v, shuffleMask);
373}
374
375/// Flip the signedness of `vecTy`'s element type, keeping the width and
376/// number of lanes the same. Used when a NEON intrinsic takes a shift
377/// amount vector that must be signed (e.g. aarch64.neon.urshl takes a
378/// signed amount even though the data vector is unsigned).
379static cir::VectorType getSignChangedVectorType(CIRGenBuilderTy &builder,
380 cir::VectorType vecTy) {
381 auto elemTy = mlir::cast<cir::IntType>(vecTy.getElementType());
382 elemTy = elemTy.isSigned() ? builder.getUIntNTy(elemTy.getWidth())
383 : builder.getSIntNTy(elemTy.getWidth());
384 return cir::VectorType::get(elemTy, vecTy.getSize());
385}
386
387static mlir::Value emitCommonNeonShift(CIRGenBuilderTy &builder,
388 mlir::Location loc,
389 cir::VectorType resTy,
390 mlir::Value shifTgt,
391 mlir::Value shiftAmt, bool shiftLeft) {
392 shiftAmt = emitNeonShiftVector(builder, shiftAmt, resTy, loc, /*neg=*/false);
393 return cir::ShiftOp::create(builder, loc, resTy,
394 builder.createBitcast(shifTgt, resTy), shiftAmt,
395 shiftLeft);
396}
397
398// Right-shift a vector by a constant.
399static mlir::Value emitNeonRShiftImm(CIRGenFunction &cgf, mlir::Value shiftVec,
400 mlir::Value shiftVal,
401 cir::VectorType vecTy, bool usgn,
402 mlir::Location loc) {
403 CIRGenBuilderTy &builder = cgf.getBuilder();
404 int64_t shiftAmt = getIntValueFromConstOp(shiftVal);
405 int eltSize =
406 cgf.cgm.getDataLayout().getTypeSizeInBits(vecTy.getElementType());
407
408 shiftVec = builder.createBitcast(shiftVec, vecTy);
409 // lshr/ashr are undefined when the shift amount is equal to the vector
410 // element size.
411 if (shiftAmt == eltSize) {
412 if (usgn) {
413 // Right-shifting an unsigned value by its size yields 0.
414 return builder.getZero(loc, vecTy);
415 }
416 // Right-shifting a signed value by its size is equivalent
417 // to a shift of size-1.
418 --shiftAmt;
419 shiftVal = builder.getConstInt(loc, vecTy.getElementType(), shiftAmt);
420 }
421 return emitCommonNeonShift(builder, loc, vecTy, shiftVec, shiftVal,
422 /*shiftLeft=*/false);
423}
424
425static cir::VectorType getIntVecFromVecTy(CIRGenBuilderTy &builder,
426 cir::VectorType vecTy) {
427 if (!cir::isAnyFloatingPointType(vecTy.getElementType()))
428 return vecTy;
429
430 if (mlir::isa<cir::SingleType>(vecTy.getElementType()))
431 return cir::VectorType::get(builder.getSInt32Ty(), vecTy.getSize());
432 if (mlir::isa<cir::DoubleType>(vecTy.getElementType()))
433 return cir::VectorType::get(builder.getSInt64Ty(), vecTy.getSize());
434 llvm_unreachable(
435 "Unsupported element type in getVecOfIntTypeWithSameEltWidth");
436}
437
438static mlir::Value emitCommonNeonBuiltinExpr(
439 CIRGenFunction &cgf, unsigned builtinID, unsigned llvmIntrinsic,
440 unsigned altLLVMIntrinsic, const char *nameHint, unsigned modifier,
442
443 mlir::Location loc = cgf.getLoc(expr->getExprLoc());
444 clang::ASTContext &ctx = cgf.getContext();
445
446 // Extract the trailing immediate argument that encodes the type discriminator
447 // for this overloaded intrinsic.
448 // TODO: Move to the parent code that takes care of argument processing.
449 const clang::Expr *arg = expr->getArg(expr->getNumArgs() - 1);
450 std::optional<llvm::APSInt> neonTypeConst = arg->getIntegerConstantExpr(ctx);
451 if (!neonTypeConst)
452 return nullptr;
453
454 // Determine the type of this overloaded NEON intrinsic.
455 NeonTypeFlags neonType(neonTypeConst->getZExtValue());
456 const bool isUnsigned = neonType.isUnsigned();
457 const bool hasLegalHalfType = cgf.getTarget().hasFastHalfType();
458 const bool usgn = neonType.isUnsigned();
459
460 // The value of allowBFloatArgsAndRet is true for AArch64, but it should
461 // come from ABI info.
462 // TODO(cir): Use ABInfo to extract this information
463 const bool allowBFloatArgsAndRet = cgf.getTarget().hasFastHalfType();
464 // FIXME
465 // getTargetHooks().getABIInfo().allowBFloatArgsAndRet();
466
467 cir::VectorType vTy = getNeonType(&cgf, neonType, loc, hasLegalHalfType,
468 false, allowBFloatArgsAndRet);
469 mlir::Type ty = vTy;
470 if (!ty)
471 return nullptr;
472
473 switch (builtinID) {
474 case NEON::BI__builtin_neon_splat_lane_v:
475 case NEON::BI__builtin_neon_splat_laneq_v:
476 case NEON::BI__builtin_neon_splatq_lane_v:
477 case NEON::BI__builtin_neon_splatq_laneq_v: {
478 uint64_t numElements = vTy.getSize();
479 if (builtinID == NEON::BI__builtin_neon_splatq_lane_v)
480 numElements *= 2;
481 if (builtinID == NEON::BI__builtin_neon_splat_laneq_v)
482 numElements /= 2;
483 ops[0] = cgf.getBuilder().createBitcast(loc, ops[0], vTy);
484 return emitNeonSplat(cgf.getBuilder(), loc, ops[0], ops[1], numElements);
485 }
486 case NEON::BI__builtin_neon_vpadd_v:
487 case NEON::BI__builtin_neon_vpaddq_v:
488 case NEON::BI__builtin_neon_vabs_v:
489 case NEON::BI__builtin_neon_vabsq_v:
490 case NEON::BI__builtin_neon_vadd_v:
491 case NEON::BI__builtin_neon_vaddq_v:
492 case NEON::BI__builtin_neon_vaddhn_v:
493 case NEON::BI__builtin_neon_vcale_v:
494 case NEON::BI__builtin_neon_vcaleq_v:
495 case NEON::BI__builtin_neon_vcalt_v:
496 case NEON::BI__builtin_neon_vcaltq_v:
497 case NEON::BI__builtin_neon_vcage_v:
498 case NEON::BI__builtin_neon_vcageq_v:
499 case NEON::BI__builtin_neon_vcagt_v:
500 case NEON::BI__builtin_neon_vcagtq_v:
501 cgf.cgm.errorNYI(expr->getSourceRange(),
502 std::string("unimplemented AArch64 builtin call: ") +
503 ctx.BuiltinInfo.getName(builtinID));
504 return mlir::Value{};
505 case NEON::BI__builtin_neon_vceqz_v:
506 case NEON::BI__builtin_neon_vceqzq_v:
507 return emitAArch64CompareBuiltinExpr(cgf, cgf.getBuilder(), loc, ops[0],
508 vTy, cir::CmpOpKind::eq);
509 case NEON::BI__builtin_neon_vcgez_v:
510 case NEON::BI__builtin_neon_vcgezq_v:
511 case NEON::BI__builtin_neon_vclez_v:
512 case NEON::BI__builtin_neon_vclezq_v:
513 case NEON::BI__builtin_neon_vcgtz_v:
514 case NEON::BI__builtin_neon_vcgtzq_v:
515 case NEON::BI__builtin_neon_vcltz_v:
516 case NEON::BI__builtin_neon_vcltzq_v:
517 case NEON::BI__builtin_neon_vclz_v:
518 case NEON::BI__builtin_neon_vclzq_v:
519 case NEON::BI__builtin_neon_vcvt_f32_v:
520 case NEON::BI__builtin_neon_vcvtq_f32_v:
521 case NEON::BI__builtin_neon_vcvt_f16_s16:
522 case NEON::BI__builtin_neon_vcvt_f16_u16:
523 case NEON::BI__builtin_neon_vcvtq_f16_s16:
524 case NEON::BI__builtin_neon_vcvtq_f16_u16:
525 case NEON::BI__builtin_neon_vcvt_n_f16_s16:
526 case NEON::BI__builtin_neon_vcvt_n_f16_u16:
527 case NEON::BI__builtin_neon_vcvtq_n_f16_s16:
528 case NEON::BI__builtin_neon_vcvtq_n_f16_u16:
529 cgf.cgm.errorNYI(expr->getSourceRange(),
530 std::string("unimplemented AArch64 builtin call: ") +
531 ctx.BuiltinInfo.getName(builtinID));
532 return mlir::Value{};
533 case NEON::BI__builtin_neon_vcvt_n_f32_v:
534 case NEON::BI__builtin_neon_vcvt_n_f64_v:
535 case NEON::BI__builtin_neon_vcvtq_n_f32_v:
536 case NEON::BI__builtin_neon_vcvtq_n_f64_v: {
537 // The constant argument to an _n_ intrinsic always is Int32Ty.
538 mlir::Type cstIntTy = cgf.sInt32Ty;
539 llvm::StringRef llvmIntrName =
540 getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(
541 usgn ? llvmIntrinsic : altLLVMIntrinsic));
542 return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(),
543 /*argTypes=*/{vTy, cstIntTy}, ops, llvmIntrName,
544 /*funcResTy=*/getFloatNeonType(cgf, neonType), loc);
545 }
546 case NEON::BI__builtin_neon_vcvt_n_s16_f16:
547 case NEON::BI__builtin_neon_vcvt_n_s32_v:
548 case NEON::BI__builtin_neon_vcvt_n_u16_f16:
549 case NEON::BI__builtin_neon_vcvt_n_u32_v:
550 case NEON::BI__builtin_neon_vcvt_n_s64_v:
551 case NEON::BI__builtin_neon_vcvt_n_u64_v:
552 case NEON::BI__builtin_neon_vcvtq_n_s16_f16:
553 case NEON::BI__builtin_neon_vcvtq_n_s32_v:
554 case NEON::BI__builtin_neon_vcvtq_n_u16_f16:
555 case NEON::BI__builtin_neon_vcvtq_n_u32_v:
556 case NEON::BI__builtin_neon_vcvtq_n_s64_v:
557 case NEON::BI__builtin_neon_vcvtq_n_u64_v: {
558 // The constant argument to an _n_ intrinsic always is Int32Ty.
559 mlir::Type cstIntTy = cgf.sInt32Ty;
560 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
561 static_cast<llvm::Intrinsic::ID>(llvmIntrinsic));
562 return emitNeonCall(
563 cgf.getCIRGenModule(), cgf.getBuilder(),
564 /*argTypes=*/{getFloatNeonType(cgf, neonType), cstIntTy}, ops,
565 llvmIntrName,
566 /*funcResTy=*/vTy, loc);
567 }
568 case NEON::BI__builtin_neon_vcvt_s32_v:
569 case NEON::BI__builtin_neon_vcvt_u32_v:
570 case NEON::BI__builtin_neon_vcvt_s64_v:
571 case NEON::BI__builtin_neon_vcvt_u64_v:
572 case NEON::BI__builtin_neon_vcvt_s16_f16:
573 case NEON::BI__builtin_neon_vcvt_u16_f16:
574 case NEON::BI__builtin_neon_vcvtq_s32_v:
575 case NEON::BI__builtin_neon_vcvtq_u32_v:
576 case NEON::BI__builtin_neon_vcvtq_s64_v:
577 case NEON::BI__builtin_neon_vcvtq_u64_v:
578 case NEON::BI__builtin_neon_vcvtq_s16_f16:
579 case NEON::BI__builtin_neon_vcvtq_u16_f16:
580 case NEON::BI__builtin_neon_vcvta_s16_f16:
581 case NEON::BI__builtin_neon_vcvta_s32_v:
582 case NEON::BI__builtin_neon_vcvta_s64_v:
583 case NEON::BI__builtin_neon_vcvta_u16_f16:
584 case NEON::BI__builtin_neon_vcvta_u32_v:
585 case NEON::BI__builtin_neon_vcvta_u64_v:
586 case NEON::BI__builtin_neon_vcvtaq_s16_f16:
587 case NEON::BI__builtin_neon_vcvtaq_s32_v:
588 case NEON::BI__builtin_neon_vcvtaq_s64_v:
589 case NEON::BI__builtin_neon_vcvtaq_u16_f16:
590 case NEON::BI__builtin_neon_vcvtaq_u32_v:
591 case NEON::BI__builtin_neon_vcvtaq_u64_v:
592 case NEON::BI__builtin_neon_vcvtn_s16_f16:
593 case NEON::BI__builtin_neon_vcvtn_s32_v:
594 case NEON::BI__builtin_neon_vcvtn_s64_v:
595 case NEON::BI__builtin_neon_vcvtn_u16_f16:
596 case NEON::BI__builtin_neon_vcvtn_u32_v:
597 case NEON::BI__builtin_neon_vcvtn_u64_v:
598 case NEON::BI__builtin_neon_vcvtnq_s16_f16:
599 case NEON::BI__builtin_neon_vcvtnq_s32_v:
600 case NEON::BI__builtin_neon_vcvtnq_s64_v:
601 case NEON::BI__builtin_neon_vcvtnq_u16_f16:
602 case NEON::BI__builtin_neon_vcvtnq_u32_v:
603 case NEON::BI__builtin_neon_vcvtnq_u64_v:
604 case NEON::BI__builtin_neon_vcvtp_s16_f16:
605 case NEON::BI__builtin_neon_vcvtp_s32_v:
606 case NEON::BI__builtin_neon_vcvtp_s64_v:
607 case NEON::BI__builtin_neon_vcvtp_u16_f16:
608 case NEON::BI__builtin_neon_vcvtp_u32_v:
609 case NEON::BI__builtin_neon_vcvtp_u64_v:
610 case NEON::BI__builtin_neon_vcvtpq_s16_f16:
611 case NEON::BI__builtin_neon_vcvtpq_s32_v:
612 case NEON::BI__builtin_neon_vcvtpq_s64_v:
613 case NEON::BI__builtin_neon_vcvtpq_u16_f16:
614 case NEON::BI__builtin_neon_vcvtpq_u32_v:
615 case NEON::BI__builtin_neon_vcvtpq_u64_v:
616 case NEON::BI__builtin_neon_vcvtm_s16_f16:
617 case NEON::BI__builtin_neon_vcvtm_s32_v:
618 case NEON::BI__builtin_neon_vcvtm_s64_v:
619 case NEON::BI__builtin_neon_vcvtm_u16_f16:
620 case NEON::BI__builtin_neon_vcvtm_u32_v:
621 case NEON::BI__builtin_neon_vcvtm_u64_v:
622 case NEON::BI__builtin_neon_vcvtmq_s16_f16:
623 case NEON::BI__builtin_neon_vcvtmq_s32_v:
624 case NEON::BI__builtin_neon_vcvtmq_s64_v:
625 case NEON::BI__builtin_neon_vcvtmq_u16_f16:
626 case NEON::BI__builtin_neon_vcvtmq_u32_v:
627 case NEON::BI__builtin_neon_vcvtmq_u64_v:
628 case NEON::BI__builtin_neon_vcvtx_f32_v:
629 case NEON::BI__builtin_neon_vext_v:
630 case NEON::BI__builtin_neon_vextq_v:
631 case NEON::BI__builtin_neon_vfma_v:
632 case NEON::BI__builtin_neon_vfmaq_v:
633 case NEON::BI__builtin_neon_vld1_v:
634 case NEON::BI__builtin_neon_vld1q_v:
635 case NEON::BI__builtin_neon_vld1_x2_v:
636 case NEON::BI__builtin_neon_vld1q_x2_v:
637 case NEON::BI__builtin_neon_vld1_x3_v:
638 case NEON::BI__builtin_neon_vld1q_x3_v:
639 case NEON::BI__builtin_neon_vld1_x4_v:
640 case NEON::BI__builtin_neon_vld1q_x4_v:
641 case NEON::BI__builtin_neon_vld2_v:
642 case NEON::BI__builtin_neon_vld2q_v:
643 case NEON::BI__builtin_neon_vld3_v:
644 case NEON::BI__builtin_neon_vld3q_v:
645 case NEON::BI__builtin_neon_vld4_v:
646 case NEON::BI__builtin_neon_vld4q_v:
647 case NEON::BI__builtin_neon_vld2_dup_v:
648 case NEON::BI__builtin_neon_vld2q_dup_v:
649 case NEON::BI__builtin_neon_vld3_dup_v:
650 case NEON::BI__builtin_neon_vld3q_dup_v:
651 case NEON::BI__builtin_neon_vld4_dup_v:
652 case NEON::BI__builtin_neon_vld4q_dup_v:
653 case NEON::BI__builtin_neon_vld1_dup_v:
654 case NEON::BI__builtin_neon_vld1q_dup_v:
655 case NEON::BI__builtin_neon_vld2_lane_v:
656 case NEON::BI__builtin_neon_vld2q_lane_v:
657 case NEON::BI__builtin_neon_vld3_lane_v:
658 case NEON::BI__builtin_neon_vld3q_lane_v:
659 case NEON::BI__builtin_neon_vld4_lane_v:
660 case NEON::BI__builtin_neon_vld4q_lane_v:
661 case NEON::BI__builtin_neon_vmovl_v:
662 case NEON::BI__builtin_neon_vmovn_v:
663 case NEON::BI__builtin_neon_vmull_v:
664 case NEON::BI__builtin_neon_vpadal_v:
665 case NEON::BI__builtin_neon_vpadalq_v:
666 case NEON::BI__builtin_neon_vpaddl_v:
667 case NEON::BI__builtin_neon_vpaddlq_v:
668 case NEON::BI__builtin_neon_vqdmlal_v:
669 case NEON::BI__builtin_neon_vqdmlsl_v:
670 case NEON::BI__builtin_neon_vqdmulhq_lane_v:
671 case NEON::BI__builtin_neon_vqdmulh_lane_v:
672 case NEON::BI__builtin_neon_vqrdmulhq_lane_v:
673 case NEON::BI__builtin_neon_vqrdmulh_lane_v:
674 case NEON::BI__builtin_neon_vqdmulhq_laneq_v:
675 case NEON::BI__builtin_neon_vqdmulh_laneq_v:
676 case NEON::BI__builtin_neon_vqrdmulhq_laneq_v:
677 case NEON::BI__builtin_neon_vqrdmulh_laneq_v:
678 case NEON::BI__builtin_neon_vqshl_n_v:
679 case NEON::BI__builtin_neon_vqshlq_n_v:
680 case NEON::BI__builtin_neon_vqshlu_n_v:
681 case NEON::BI__builtin_neon_vqshluq_n_v:
682 case NEON::BI__builtin_neon_vrecpe_v:
683 case NEON::BI__builtin_neon_vrecpeq_v:
684 case NEON::BI__builtin_neon_vrsqrte_v:
685 case NEON::BI__builtin_neon_vrsqrteq_v:
686 case NEON::BI__builtin_neon_vrndi_v:
687 case NEON::BI__builtin_neon_vrndiq_v:
688 case NEON::BI__builtin_neon_vrshr_n_v:
689 case NEON::BI__builtin_neon_vrshrq_n_v:
690 case NEON::BI__builtin_neon_vsha512hq_u64:
691 case NEON::BI__builtin_neon_vsha512h2q_u64:
692 case NEON::BI__builtin_neon_vsha512su0q_u64:
693 case NEON::BI__builtin_neon_vsha512su1q_u64:
694 cgf.cgm.errorNYI(expr->getSourceRange(),
695 std::string("unimplemented AArch64 builtin call: ") +
696 ctx.BuiltinInfo.getName(builtinID));
697 return mlir::Value{};
698 case NEON::BI__builtin_neon_vshl_n_v:
699 case NEON::BI__builtin_neon_vshlq_n_v:
700 return emitCommonNeonShift(cgf.getBuilder(), loc, vTy, ops[0], ops[1],
701 /*shiftLeft=*/true);
702 case NEON::BI__builtin_neon_vshll_n_v:
703 case NEON::BI__builtin_neon_vshrn_n_v:
704 cgf.cgm.errorNYI(expr->getSourceRange(),
705 std::string("unimplemented AArch64 builtin call: ") +
706 ctx.BuiltinInfo.getName(builtinID));
707 return mlir::Value{};
708 case NEON::BI__builtin_neon_vshr_n_v:
709 case NEON::BI__builtin_neon_vshrq_n_v:
710 return emitNeonRShiftImm(cgf, ops[0], ops[1], vTy, isUnsigned, loc);
711 case NEON::BI__builtin_neon_vst1_v:
712 case NEON::BI__builtin_neon_vst1q_v:
713 case NEON::BI__builtin_neon_vst2_v:
714 case NEON::BI__builtin_neon_vst2q_v:
715 case NEON::BI__builtin_neon_vst3_v:
716 case NEON::BI__builtin_neon_vst3q_v:
717 case NEON::BI__builtin_neon_vst4_v:
718 case NEON::BI__builtin_neon_vst4q_v:
719 case NEON::BI__builtin_neon_vst2_lane_v:
720 case NEON::BI__builtin_neon_vst2q_lane_v:
721 case NEON::BI__builtin_neon_vst3_lane_v:
722 case NEON::BI__builtin_neon_vst3q_lane_v:
723 case NEON::BI__builtin_neon_vst4_lane_v:
724 case NEON::BI__builtin_neon_vst4q_lane_v:
725 case NEON::BI__builtin_neon_vsm3partw1q_u32:
726 case NEON::BI__builtin_neon_vsm3partw2q_u32:
727 case NEON::BI__builtin_neon_vsm3ss1q_u32:
728 case NEON::BI__builtin_neon_vsm4ekeyq_u32:
729 case NEON::BI__builtin_neon_vsm4eq_u32:
730 case NEON::BI__builtin_neon_vsm3tt1aq_u32:
731 case NEON::BI__builtin_neon_vsm3tt1bq_u32:
732 case NEON::BI__builtin_neon_vsm3tt2aq_u32:
733 case NEON::BI__builtin_neon_vsm3tt2bq_u32:
734 case NEON::BI__builtin_neon_vst1_x2_v:
735 case NEON::BI__builtin_neon_vst1q_x2_v:
736 case NEON::BI__builtin_neon_vst1_x3_v:
737 case NEON::BI__builtin_neon_vst1q_x3_v:
738 case NEON::BI__builtin_neon_vst1_x4_v:
739 case NEON::BI__builtin_neon_vst1q_x4_v:
740 case NEON::BI__builtin_neon_vsubhn_v:
741 case NEON::BI__builtin_neon_vtrn_v:
742 case NEON::BI__builtin_neon_vtrnq_v:
743 case NEON::BI__builtin_neon_vtst_v:
744 case NEON::BI__builtin_neon_vtstq_v:
745 case NEON::BI__builtin_neon_vuzp_v:
746 case NEON::BI__builtin_neon_vuzpq_v:
747 case NEON::BI__builtin_neon_vxarq_u64:
748 case NEON::BI__builtin_neon_vzip_v:
749 case NEON::BI__builtin_neon_vzipq_v:
750 case NEON::BI__builtin_neon_vdot_s32:
751 case NEON::BI__builtin_neon_vdot_u32:
752 case NEON::BI__builtin_neon_vdotq_s32:
753 case NEON::BI__builtin_neon_vdotq_u32:
754 case NEON::BI__builtin_neon_vfmlal_low_f16:
755 case NEON::BI__builtin_neon_vfmlalq_low_f16:
756 case NEON::BI__builtin_neon_vfmlsl_low_f16:
757 case NEON::BI__builtin_neon_vfmlslq_low_f16:
758 case NEON::BI__builtin_neon_vfmlal_high_f16:
759 case NEON::BI__builtin_neon_vfmlalq_high_f16:
760 case NEON::BI__builtin_neon_vfmlsl_high_f16:
761 case NEON::BI__builtin_neon_vfmlslq_high_f16:
762 case NEON::BI__builtin_neon_vmmlaq_s32:
763 case NEON::BI__builtin_neon_vmmlaq_u32:
764 cgf.cgm.errorNYI(expr->getSourceRange(),
765 std::string("unimplemented AArch64 builtin call: ") +
766 ctx.BuiltinInfo.getName(builtinID));
767 return mlir::Value{};
768 case NEON::BI__builtin_neon_vmul_v:
769 case NEON::BI__builtin_neon_vmulq_v:
770 return cgf.getBuilder().emitIntrinsicCallOp(loc, "aarch64.neon.pmul", vTy,
771 ops);
772 case NEON::BI__builtin_neon_vusmmlaq_s32:
773 case NEON::BI__builtin_neon_vusdot_s32:
774 case NEON::BI__builtin_neon_vusdotq_s32:
775 case NEON::BI__builtin_neon_vbfdot_f32:
776 case NEON::BI__builtin_neon_vbfdotq_f32:
777 case NEON::BI__builtin_neon___a32_vcvt_bf16_f32:
778 default:
779 cgf.cgm.errorNYI(expr->getSourceRange(),
780 std::string("unimplemented AArch64 builtin call: ") +
781 ctx.BuiltinInfo.getName(builtinID));
782 return mlir::Value{};
783
784 cgf.cgm.errorNYI(expr->getSourceRange(),
785 std::string("unimplemented AArch64 builtin call: ") +
786 ctx.BuiltinInfo.getName(builtinID));
787 return mlir::Value{};
788 }
789}
790
791// Emit an intrinsic where all operands are of the same type as the result.
792// Depending on mode, this may be a constrained floating-point intrinsic.
793static mlir::Value
795 StringRef intrName, mlir::Type retTy,
798
799 return builder.emitIntrinsicCallOp(loc, intrName, retTy, ops);
800}
801
803 unsigned builtinID, const CallExpr *expr, SmallVectorImpl<mlir::Value> &ops,
804 SVETypeFlags typeFlags) {
805 // Find out if any arguments are required to be integer constant expressions.
806 unsigned iceArguments = 0;
808 getContext().GetBuiltinType(builtinID, error, &iceArguments);
809 assert(error == ASTContext::GE_None && "Should not codegen an error");
810
811 for (unsigned i = 0, e = expr->getNumArgs(); i != e; i++) {
812 bool isIce = iceArguments & (1 << i);
813 mlir::Value arg = emitScalarExpr(expr->getArg(i));
814
815 if (isIce) {
816 cgm.errorNYI(expr->getSourceRange(),
817 std::string("unimplemented AArch64 builtin call: ") +
818 getContext().BuiltinInfo.getName(builtinID));
819 }
820
821 // FIXME: Handle types like svint16x2_t, which are currently incorrectly
822 // converted to i32. These should be treated as structs and unpacked.
823
824 ops.push_back(arg);
825 }
826 return true;
827}
828
829// Reinterpret the input predicate so that it can be used to correctly isolate
830// the elements of the specified datatype.
831mlir::Value CIRGenFunction::emitSVEPredicateCast(mlir::Value pred,
832 unsigned minNumElts,
833 mlir::Location loc) {
834
835 // TODO: Handle "aarch64.svcount" once we get round to supporting SME.
836
837 auto retTy = cir::VectorType::get(builder.getUIntNTy(1), minNumElts,
838 /*is_scalable=*/true);
839 if (pred.getType() == retTy)
840 return pred;
841
842 llvm::Intrinsic::ID intID;
843 switch (minNumElts) {
844 default:
845 llvm_unreachable("unsupported element count!");
846 case 1:
847 case 2:
848 case 4:
849 case 8:
850 intID = Intrinsic::aarch64_sve_convert_from_svbool;
851 break;
852 case 16:
853 intID = Intrinsic::aarch64_sve_convert_to_svbool;
854 break;
855 }
856
857 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(intID);
858 auto call = builder.emitIntrinsicCallOp(loc, llvmIntrName, retTy,
859 mlir::ValueRange{pred});
860 assert(call.getType() == retTy && "Unexpected return type!");
861 return call;
862}
863
864//===----------------------------------------------------------------------===//
865// SVE helpers
866//===----------------------------------------------------------------------===//
867// Get the minimum number of elements in an SVE vector for the given element
868// type. The actual number of elements in the vector would be an integer (power
869// of two) multiple of this value.
871 switch (sveType) {
872 default:
873 llvm_unreachable("Invalid SVETypeFlag!");
874
875 case SVETypeFlags::EltTyInt8:
876 return 16;
877 case SVETypeFlags::EltTyInt16:
878 return 8;
879 case SVETypeFlags::EltTyInt32:
880 return 4;
881 case SVETypeFlags::EltTyInt64:
882 return 2;
883
884 case SVETypeFlags::EltTyMFloat8:
885 return 16;
886 case SVETypeFlags::EltTyFloat16:
887 case SVETypeFlags::EltTyBFloat16:
888 return 8;
889 case SVETypeFlags::EltTyFloat32:
890 return 4;
891 case SVETypeFlags::EltTyFloat64:
892 return 2;
893
894 case SVETypeFlags::EltTyBool8:
895 return 16;
896 case SVETypeFlags::EltTyBool16:
897 return 8;
898 case SVETypeFlags::EltTyBool32:
899 return 4;
900 case SVETypeFlags::EltTyBool64:
901 return 2;
902 }
903}
904
905// TODO(cir): Share with OGCG
906constexpr unsigned sveBitsPerBlock = 128;
907
908static cir::VectorType getSVEVectorForElementType(CIRGenModule &cgm,
909 mlir::Type eltTy) {
910 unsigned numElts =
912 return cir::VectorType::get(eltTy, numElts, /*is_scalable=*/true);
913}
914
915//===----------------------------------------------------------------------===//
916// SVE helpers
917//===----------------------------------------------------------------------===//
918std::optional<mlir::Value>
920 const CallExpr *expr) {
921 mlir::Type ty = convertType(expr->getType());
922
923 if (builtinID >= SVE::BI__builtin_sve_reinterpret_s8_s8 &&
924 builtinID <= SVE::BI__builtin_sve_reinterpret_f64_f64_x4) {
925 cgm.errorNYI(expr->getSourceRange(),
926 std::string("unimplemented AArch64 builtin call: ") +
927 getContext().BuiltinInfo.getName(builtinID));
928 return mlir::Value{};
929 }
930
932
933 auto *builtinIntrInfo = findARMVectorIntrinsicInMap(
935
936 // The operands of the builtin call
938
939 SVETypeFlags typeFlags(builtinIntrInfo->TypeModifier);
941 typeFlags))
942 return mlir::Value{};
943
944 if (typeFlags.isLoad() || typeFlags.isStore() || typeFlags.isGatherLoad() ||
945 typeFlags.isScatterStore() || typeFlags.isPrefetch() ||
946 typeFlags.isGatherPrefetch() || typeFlags.isStructLoad() ||
947 typeFlags.isStructStore() || typeFlags.isTupleSet() ||
948 typeFlags.isTupleGet() || typeFlags.isTupleCreate() ||
949 typeFlags.isUndef())
950 cgm.errorNYI(expr->getSourceRange(),
951 std::string("unimplemented AArch64 builtin call: ") +
952 getContext().BuiltinInfo.getName(builtinID));
953
954 mlir::Location loc = getLoc(expr->getExprLoc());
955
956 // Handle built-ins for which there is a corresponding LLVM Intrinsic.
957 // -------------------------------------------------------------------
958 if (builtinIntrInfo->LLVMIntrinsic != 0) {
959 // Emit set FPMR for intrinsics that require it.
960 if (typeFlags.setsFPMR())
961 cgm.errorNYI(expr->getSourceRange(),
962 std::string("unimplemented AArch64 builtin call: ") +
963 getContext().BuiltinInfo.getName(builtinID));
964
965 // Zero-ing predication
966 if (typeFlags.getMergeType() == SVETypeFlags::MergeZeroExp) {
967 auto null = builder.getNullValue(convertType(expr->getType()),
968 getLoc(expr->getExprLoc()));
969 ops.insert(ops.begin(), null);
970 }
971
972 if (typeFlags.getMergeType() == SVETypeFlags::MergeAnyExp)
973 ops.insert(ops.begin(),
974 builder.getConstant(loc, cir::UndefAttr::get(ty)));
975
976 // Some ACLE builtins leave out the argument to specify the predicate
977 // pattern, which is expected to be expanded to an SV_ALL pattern.
978 if (typeFlags.isAppendSVALL())
979 cgm.errorNYI(expr->getSourceRange(),
980 std::string("unimplemented AArch64 builtin call: ") +
981 getContext().BuiltinInfo.getName(builtinID));
982 if (typeFlags.isInsertOp1SVALL())
983 cgm.errorNYI(expr->getSourceRange(),
984 std::string("unimplemented AArch64 builtin call: ") +
985 getContext().BuiltinInfo.getName(builtinID));
986
987 // Predicates must match the main datatype.
988 for (mlir::Value &op : ops)
989 if (auto predTy = dyn_cast<cir::VectorType>(op.getType()))
990 if (auto cirInt = dyn_cast<cir::IntType>(predTy.getElementType()))
991 if (cirInt.getWidth() == 1)
993 op, getSVEMinEltCount(typeFlags.getEltType()), loc);
994
995 // Splat scalar operand to vector (intrinsics with _n infix)
996 if (typeFlags.hasSplatOperand()) {
997 unsigned opNo = typeFlags.getSplatOperand();
998 ops[opNo] = cir::VecSplatOp::create(
999 builder, loc, getSVEVectorForElementType(cgm, ops[opNo].getType()),
1000 ops[opNo]);
1001 }
1002
1003 if (typeFlags.isReverseCompare())
1004 cgm.errorNYI(expr->getSourceRange(),
1005 std::string("unimplemented AArch64 builtin call: ") +
1006 getContext().BuiltinInfo.getName(builtinID));
1007 if (typeFlags.isReverseUSDOT())
1008 cgm.errorNYI(expr->getSourceRange(),
1009 std::string("unimplemented AArch64 builtin call: ") +
1010 getContext().BuiltinInfo.getName(builtinID));
1011 if (typeFlags.isReverseMergeAnyBinOp() &&
1012 typeFlags.getMergeType() == SVETypeFlags::MergeAny)
1013 cgm.errorNYI(expr->getSourceRange(),
1014 std::string("unimplemented AArch64 builtin call: ") +
1015 getContext().BuiltinInfo.getName(builtinID));
1016 if (typeFlags.isReverseMergeAnyAccOp() &&
1017 typeFlags.getMergeType() == SVETypeFlags::MergeAny)
1018 cgm.errorNYI(expr->getSourceRange(),
1019 std::string("unimplemented AArch64 builtin call: ") +
1020 getContext().BuiltinInfo.getName(builtinID));
1021
1022 // Predicated intrinsics with _z suffix.
1023 if (typeFlags.getMergeType() == SVETypeFlags::MergeZero) {
1024 cgm.errorNYI(expr->getSourceRange(),
1025 std::string("unimplemented AArch64 builtin call: ") +
1026 getContext().BuiltinInfo.getName(builtinID));
1027 }
1028
1029 llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
1030 static_cast<llvm::Intrinsic::ID>(builtinIntrInfo->LLVMIntrinsic));
1031 auto retTy = convertType(expr->getType());
1032
1033 auto call = builder.emitIntrinsicCallOp(loc, llvmIntrName, retTy,
1034 mlir::ValueRange{ops});
1035 if (call.getType() == retTy)
1036 return call;
1037
1038 // Predicate results must be converted to svbool_t.
1039 if (isa<mlir::VectorType>(retTy) &&
1040 cast<mlir::VectorType>(retTy).isScalable())
1041 cgm.errorNYI(expr->getSourceRange(),
1042 std::string("unimplemented AArch64 builtin call: ") +
1043 getContext().BuiltinInfo.getName(builtinID));
1044 // TODO Handle struct types, e.g. svint8x2_t (update the converter first).
1045
1046 llvm_unreachable("unsupported element count!");
1047 }
1048
1049 // Handle the remaining built-ins.
1050 // -------------------------------
1051 switch (builtinID) {
1052 default:
1053 return std::nullopt;
1054
1055 case SVE::BI__builtin_sve_svreinterpret_b:
1056 case SVE::BI__builtin_sve_svreinterpret_c:
1057 case SVE::BI__builtin_sve_svpsel_lane_b8:
1058 case SVE::BI__builtin_sve_svpsel_lane_b16:
1059 case SVE::BI__builtin_sve_svpsel_lane_b32:
1060 case SVE::BI__builtin_sve_svpsel_lane_b64:
1061 case SVE::BI__builtin_sve_svpsel_lane_c8:
1062 case SVE::BI__builtin_sve_svpsel_lane_c16:
1063 case SVE::BI__builtin_sve_svpsel_lane_c32:
1064 case SVE::BI__builtin_sve_svpsel_lane_c64:
1065 case SVE::BI__builtin_sve_svmov_b_z:
1066 case SVE::BI__builtin_sve_svnot_b_z:
1067 case SVE::BI__builtin_sve_svmovlb_u16:
1068 case SVE::BI__builtin_sve_svmovlb_u32:
1069 case SVE::BI__builtin_sve_svmovlb_u64:
1070 case SVE::BI__builtin_sve_svmovlb_s16:
1071 case SVE::BI__builtin_sve_svmovlb_s32:
1072 case SVE::BI__builtin_sve_svmovlb_s64:
1073 case SVE::BI__builtin_sve_svmovlt_u16:
1074 case SVE::BI__builtin_sve_svmovlt_u32:
1075 case SVE::BI__builtin_sve_svmovlt_u64:
1076 case SVE::BI__builtin_sve_svmovlt_s16:
1077 case SVE::BI__builtin_sve_svmovlt_s32:
1078 case SVE::BI__builtin_sve_svmovlt_s64:
1079 case SVE::BI__builtin_sve_svpmullt_u16:
1080 case SVE::BI__builtin_sve_svpmullt_u64:
1081 case SVE::BI__builtin_sve_svpmullt_n_u16:
1082 case SVE::BI__builtin_sve_svpmullt_n_u64:
1083 case SVE::BI__builtin_sve_svpmullb_u16:
1084 case SVE::BI__builtin_sve_svpmullb_u64:
1085 case SVE::BI__builtin_sve_svpmullb_n_u16:
1086 case SVE::BI__builtin_sve_svpmullb_n_u64:
1087
1088 case SVE::BI__builtin_sve_svdup_n_b8:
1089 case SVE::BI__builtin_sve_svdup_n_b16:
1090 case SVE::BI__builtin_sve_svdup_n_b32:
1091 case SVE::BI__builtin_sve_svdup_n_b64:
1092
1093 case SVE::BI__builtin_sve_svdupq_n_b8:
1094 case SVE::BI__builtin_sve_svdupq_n_b16:
1095 case SVE::BI__builtin_sve_svdupq_n_b32:
1096 case SVE::BI__builtin_sve_svdupq_n_b64:
1097 case SVE::BI__builtin_sve_svdupq_n_u8:
1098 case SVE::BI__builtin_sve_svdupq_n_s8:
1099 case SVE::BI__builtin_sve_svdupq_n_u64:
1100 case SVE::BI__builtin_sve_svdupq_n_f64:
1101 case SVE::BI__builtin_sve_svdupq_n_s64:
1102 case SVE::BI__builtin_sve_svdupq_n_u16:
1103 case SVE::BI__builtin_sve_svdupq_n_f16:
1104 case SVE::BI__builtin_sve_svdupq_n_bf16:
1105 case SVE::BI__builtin_sve_svdupq_n_s16:
1106 case SVE::BI__builtin_sve_svdupq_n_u32:
1107 case SVE::BI__builtin_sve_svdupq_n_f32:
1108 case SVE::BI__builtin_sve_svdupq_n_s32:
1109 case SVE::BI__builtin_sve_svpfalse_b:
1110 case SVE::BI__builtin_sve_svpfalse_c:
1111 cgm.errorNYI(expr->getSourceRange(),
1112 std::string("unimplemented AArch64 builtin call: ") +
1113 getContext().BuiltinInfo.getName(builtinID));
1114 return mlir::Value{};
1115
1116 case SVE::BI__builtin_sve_svlen_u8:
1117 case SVE::BI__builtin_sve_svlen_s8:
1118 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 16);
1119
1120 case SVE::BI__builtin_sve_svlen_u16:
1121 case SVE::BI__builtin_sve_svlen_s16:
1122 case SVE::BI__builtin_sve_svlen_f16:
1123 case SVE::BI__builtin_sve_svlen_bf16:
1124 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 8);
1125
1126 case SVE::BI__builtin_sve_svlen_u32:
1127 case SVE::BI__builtin_sve_svlen_s32:
1128 case SVE::BI__builtin_sve_svlen_f32:
1129 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 4);
1130
1131 case SVE::BI__builtin_sve_svlen_u64:
1132 case SVE::BI__builtin_sve_svlen_s64:
1133 case SVE::BI__builtin_sve_svlen_f64:
1134 return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 2);
1135
1136 case SVE::BI__builtin_sve_svtbl2_u8:
1137 case SVE::BI__builtin_sve_svtbl2_s8:
1138 case SVE::BI__builtin_sve_svtbl2_u16:
1139 case SVE::BI__builtin_sve_svtbl2_s16:
1140 case SVE::BI__builtin_sve_svtbl2_u32:
1141 case SVE::BI__builtin_sve_svtbl2_s32:
1142 case SVE::BI__builtin_sve_svtbl2_u64:
1143 case SVE::BI__builtin_sve_svtbl2_s64:
1144 case SVE::BI__builtin_sve_svtbl2_f16:
1145 case SVE::BI__builtin_sve_svtbl2_bf16:
1146 case SVE::BI__builtin_sve_svtbl2_f32:
1147 case SVE::BI__builtin_sve_svtbl2_f64:
1148 case SVE::BI__builtin_sve_svset_neonq_s8:
1149 case SVE::BI__builtin_sve_svset_neonq_s16:
1150 case SVE::BI__builtin_sve_svset_neonq_s32:
1151 case SVE::BI__builtin_sve_svset_neonq_s64:
1152 case SVE::BI__builtin_sve_svset_neonq_u8:
1153 case SVE::BI__builtin_sve_svset_neonq_u16:
1154 case SVE::BI__builtin_sve_svset_neonq_u32:
1155 case SVE::BI__builtin_sve_svset_neonq_u64:
1156 case SVE::BI__builtin_sve_svset_neonq_f16:
1157 case SVE::BI__builtin_sve_svset_neonq_f32:
1158 case SVE::BI__builtin_sve_svset_neonq_f64:
1159 case SVE::BI__builtin_sve_svset_neonq_bf16:
1160 case SVE::BI__builtin_sve_svget_neonq_s8:
1161 case SVE::BI__builtin_sve_svget_neonq_s16:
1162 case SVE::BI__builtin_sve_svget_neonq_s32:
1163 case SVE::BI__builtin_sve_svget_neonq_s64:
1164 case SVE::BI__builtin_sve_svget_neonq_u8:
1165 case SVE::BI__builtin_sve_svget_neonq_u16:
1166 case SVE::BI__builtin_sve_svget_neonq_u32:
1167 case SVE::BI__builtin_sve_svget_neonq_u64:
1168 case SVE::BI__builtin_sve_svget_neonq_f16:
1169 case SVE::BI__builtin_sve_svget_neonq_f32:
1170 case SVE::BI__builtin_sve_svget_neonq_f64:
1171 case SVE::BI__builtin_sve_svget_neonq_bf16:
1172 case SVE::BI__builtin_sve_svdup_neonq_s8:
1173 case SVE::BI__builtin_sve_svdup_neonq_s16:
1174 case SVE::BI__builtin_sve_svdup_neonq_s32:
1175 case SVE::BI__builtin_sve_svdup_neonq_s64:
1176 case SVE::BI__builtin_sve_svdup_neonq_u8:
1177 case SVE::BI__builtin_sve_svdup_neonq_u16:
1178 case SVE::BI__builtin_sve_svdup_neonq_u32:
1179 case SVE::BI__builtin_sve_svdup_neonq_u64:
1180 case SVE::BI__builtin_sve_svdup_neonq_f16:
1181 case SVE::BI__builtin_sve_svdup_neonq_f32:
1182 case SVE::BI__builtin_sve_svdup_neonq_f64:
1183 case SVE::BI__builtin_sve_svdup_neonq_bf16:
1184 cgm.errorNYI(expr->getSourceRange(),
1185 std::string("unimplemented AArch64 builtin call: ") +
1186 getContext().BuiltinInfo.getName(builtinID));
1187 return mlir::Value{};
1188 }
1189
1190 // Unreachable: All cases in the switch above return.
1191}
1192
1193std::optional<mlir::Value>
1195 const CallExpr *expr) {
1197
1198 cgm.errorNYI(expr->getSourceRange(),
1199 std::string("unimplemented AArch64 builtin call: ") +
1200 getContext().BuiltinInfo.getName(builtinID));
1201 return mlir::Value{};
1202}
1203
1204// Some intrinsics are equivalent for codegen.
1205static const std::pair<unsigned, unsigned> neonEquivalentIntrinsicMap[] = {
1206 {
1207 NEON::BI__builtin_neon_splat_lane_bf16,
1208 NEON::BI__builtin_neon_splat_lane_v,
1209 },
1210 {
1211 NEON::BI__builtin_neon_splat_laneq_bf16,
1212 NEON::BI__builtin_neon_splat_laneq_v,
1213 },
1214 {
1215 NEON::BI__builtin_neon_splatq_lane_bf16,
1216 NEON::BI__builtin_neon_splatq_lane_v,
1217 },
1218 {
1219 NEON::BI__builtin_neon_splatq_laneq_bf16,
1220 NEON::BI__builtin_neon_splatq_laneq_v,
1221 },
1222 {
1223 NEON::BI__builtin_neon_vabd_f16,
1224 NEON::BI__builtin_neon_vabd_v,
1225 },
1226 {
1227 NEON::BI__builtin_neon_vabdq_f16,
1228 NEON::BI__builtin_neon_vabdq_v,
1229 },
1230 {
1231 NEON::BI__builtin_neon_vabs_f16,
1232 NEON::BI__builtin_neon_vabs_v,
1233 },
1234 {
1235 NEON::BI__builtin_neon_vabsq_f16,
1236 NEON::BI__builtin_neon_vabsq_v,
1237 },
1238 {
1239 NEON::BI__builtin_neon_vcage_f16,
1240 NEON::BI__builtin_neon_vcage_v,
1241 },
1242 {
1243 NEON::BI__builtin_neon_vcageq_f16,
1244 NEON::BI__builtin_neon_vcageq_v,
1245 },
1246 {
1247 NEON::BI__builtin_neon_vcagt_f16,
1248 NEON::BI__builtin_neon_vcagt_v,
1249 },
1250 {
1251 NEON::BI__builtin_neon_vcagtq_f16,
1252 NEON::BI__builtin_neon_vcagtq_v,
1253 },
1254 {
1255 NEON::BI__builtin_neon_vcale_f16,
1256 NEON::BI__builtin_neon_vcale_v,
1257 },
1258 {
1259 NEON::BI__builtin_neon_vcaleq_f16,
1260 NEON::BI__builtin_neon_vcaleq_v,
1261 },
1262 {
1263 NEON::BI__builtin_neon_vcalt_f16,
1264 NEON::BI__builtin_neon_vcalt_v,
1265 },
1266 {
1267 NEON::BI__builtin_neon_vcaltq_f16,
1268 NEON::BI__builtin_neon_vcaltq_v,
1269 },
1270 {
1271 NEON::BI__builtin_neon_vceqz_f16,
1272 NEON::BI__builtin_neon_vceqz_v,
1273 },
1274 {
1275 NEON::BI__builtin_neon_vceqzq_f16,
1276 NEON::BI__builtin_neon_vceqzq_v,
1277 },
1278 {
1279 NEON::BI__builtin_neon_vcgez_f16,
1280 NEON::BI__builtin_neon_vcgez_v,
1281 },
1282 {
1283 NEON::BI__builtin_neon_vcgezq_f16,
1284 NEON::BI__builtin_neon_vcgezq_v,
1285 },
1286 {
1287 NEON::BI__builtin_neon_vcgtz_f16,
1288 NEON::BI__builtin_neon_vcgtz_v,
1289 },
1290 {
1291 NEON::BI__builtin_neon_vcgtzq_f16,
1292 NEON::BI__builtin_neon_vcgtzq_v,
1293 },
1294 {
1295 NEON::BI__builtin_neon_vclez_f16,
1296 NEON::BI__builtin_neon_vclez_v,
1297 },
1298 {
1299 NEON::BI__builtin_neon_vclezq_f16,
1300 NEON::BI__builtin_neon_vclezq_v,
1301 },
1302 {
1303 NEON::BI__builtin_neon_vcltz_f16,
1304 NEON::BI__builtin_neon_vcltz_v,
1305 },
1306 {
1307 NEON::BI__builtin_neon_vcltzq_f16,
1308 NEON::BI__builtin_neon_vcltzq_v,
1309 },
1310 {
1311 NEON::BI__builtin_neon_vfma_f16,
1312 NEON::BI__builtin_neon_vfma_v,
1313 },
1314 {
1315 NEON::BI__builtin_neon_vfma_lane_f16,
1316 NEON::BI__builtin_neon_vfma_lane_v,
1317 },
1318 {
1319 NEON::BI__builtin_neon_vfma_laneq_f16,
1320 NEON::BI__builtin_neon_vfma_laneq_v,
1321 },
1322 {
1323 NEON::BI__builtin_neon_vfmaq_f16,
1324 NEON::BI__builtin_neon_vfmaq_v,
1325 },
1326 {
1327 NEON::BI__builtin_neon_vfmaq_lane_f16,
1328 NEON::BI__builtin_neon_vfmaq_lane_v,
1329 },
1330 {
1331 NEON::BI__builtin_neon_vfmaq_laneq_f16,
1332 NEON::BI__builtin_neon_vfmaq_laneq_v,
1333 },
1334 {NEON::BI__builtin_neon_vld1_bf16_x2, NEON::BI__builtin_neon_vld1_x2_v},
1335 {NEON::BI__builtin_neon_vld1_bf16_x3, NEON::BI__builtin_neon_vld1_x3_v},
1336 {NEON::BI__builtin_neon_vld1_bf16_x4, NEON::BI__builtin_neon_vld1_x4_v},
1337 {NEON::BI__builtin_neon_vld1_bf16, NEON::BI__builtin_neon_vld1_v},
1338 {NEON::BI__builtin_neon_vld1_dup_bf16, NEON::BI__builtin_neon_vld1_dup_v},
1339 {NEON::BI__builtin_neon_vld1_lane_bf16, NEON::BI__builtin_neon_vld1_lane_v},
1340 {NEON::BI__builtin_neon_vld1q_bf16_x2, NEON::BI__builtin_neon_vld1q_x2_v},
1341 {NEON::BI__builtin_neon_vld1q_bf16_x3, NEON::BI__builtin_neon_vld1q_x3_v},
1342 {NEON::BI__builtin_neon_vld1q_bf16_x4, NEON::BI__builtin_neon_vld1q_x4_v},
1343 {NEON::BI__builtin_neon_vld1q_bf16, NEON::BI__builtin_neon_vld1q_v},
1344 {NEON::BI__builtin_neon_vld1q_dup_bf16, NEON::BI__builtin_neon_vld1q_dup_v},
1345 {NEON::BI__builtin_neon_vld1q_lane_bf16,
1346 NEON::BI__builtin_neon_vld1q_lane_v},
1347 {NEON::BI__builtin_neon_vld2_bf16, NEON::BI__builtin_neon_vld2_v},
1348 {NEON::BI__builtin_neon_vld2_dup_bf16, NEON::BI__builtin_neon_vld2_dup_v},
1349 {NEON::BI__builtin_neon_vld2_lane_bf16, NEON::BI__builtin_neon_vld2_lane_v},
1350 {NEON::BI__builtin_neon_vld2q_bf16, NEON::BI__builtin_neon_vld2q_v},
1351 {NEON::BI__builtin_neon_vld2q_dup_bf16, NEON::BI__builtin_neon_vld2q_dup_v},
1352 {NEON::BI__builtin_neon_vld2q_lane_bf16,
1353 NEON::BI__builtin_neon_vld2q_lane_v},
1354 {NEON::BI__builtin_neon_vld3_bf16, NEON::BI__builtin_neon_vld3_v},
1355 {NEON::BI__builtin_neon_vld3_dup_bf16, NEON::BI__builtin_neon_vld3_dup_v},
1356 {NEON::BI__builtin_neon_vld3_lane_bf16, NEON::BI__builtin_neon_vld3_lane_v},
1357 {NEON::BI__builtin_neon_vld3q_bf16, NEON::BI__builtin_neon_vld3q_v},
1358 {NEON::BI__builtin_neon_vld3q_dup_bf16, NEON::BI__builtin_neon_vld3q_dup_v},
1359 {NEON::BI__builtin_neon_vld3q_lane_bf16,
1360 NEON::BI__builtin_neon_vld3q_lane_v},
1361 {NEON::BI__builtin_neon_vld4_bf16, NEON::BI__builtin_neon_vld4_v},
1362 {NEON::BI__builtin_neon_vld4_dup_bf16, NEON::BI__builtin_neon_vld4_dup_v},
1363 {NEON::BI__builtin_neon_vld4_lane_bf16, NEON::BI__builtin_neon_vld4_lane_v},
1364 {NEON::BI__builtin_neon_vld4q_bf16, NEON::BI__builtin_neon_vld4q_v},
1365 {NEON::BI__builtin_neon_vld4q_dup_bf16, NEON::BI__builtin_neon_vld4q_dup_v},
1366 {NEON::BI__builtin_neon_vld4q_lane_bf16,
1367 NEON::BI__builtin_neon_vld4q_lane_v},
1368 {
1369 NEON::BI__builtin_neon_vmax_f16,
1370 NEON::BI__builtin_neon_vmax_v,
1371 },
1372 {
1373 NEON::BI__builtin_neon_vmaxnm_f16,
1374 NEON::BI__builtin_neon_vmaxnm_v,
1375 },
1376 {
1377 NEON::BI__builtin_neon_vmaxnmq_f16,
1378 NEON::BI__builtin_neon_vmaxnmq_v,
1379 },
1380 {
1381 NEON::BI__builtin_neon_vmaxq_f16,
1382 NEON::BI__builtin_neon_vmaxq_v,
1383 },
1384 {
1385 NEON::BI__builtin_neon_vmin_f16,
1386 NEON::BI__builtin_neon_vmin_v,
1387 },
1388 {
1389 NEON::BI__builtin_neon_vminnm_f16,
1390 NEON::BI__builtin_neon_vminnm_v,
1391 },
1392 {
1393 NEON::BI__builtin_neon_vminnmq_f16,
1394 NEON::BI__builtin_neon_vminnmq_v,
1395 },
1396 {
1397 NEON::BI__builtin_neon_vminq_f16,
1398 NEON::BI__builtin_neon_vminq_v,
1399 },
1400 {
1401 NEON::BI__builtin_neon_vmulx_f16,
1402 NEON::BI__builtin_neon_vmulx_v,
1403 },
1404 {
1405 NEON::BI__builtin_neon_vmulxq_f16,
1406 NEON::BI__builtin_neon_vmulxq_v,
1407 },
1408 {
1409 NEON::BI__builtin_neon_vpadd_f16,
1410 NEON::BI__builtin_neon_vpadd_v,
1411 },
1412 {
1413 NEON::BI__builtin_neon_vpaddq_f16,
1414 NEON::BI__builtin_neon_vpaddq_v,
1415 },
1416 {
1417 NEON::BI__builtin_neon_vpmax_f16,
1418 NEON::BI__builtin_neon_vpmax_v,
1419 },
1420 {
1421 NEON::BI__builtin_neon_vpmaxnm_f16,
1422 NEON::BI__builtin_neon_vpmaxnm_v,
1423 },
1424 {
1425 NEON::BI__builtin_neon_vpmaxnmq_f16,
1426 NEON::BI__builtin_neon_vpmaxnmq_v,
1427 },
1428 {
1429 NEON::BI__builtin_neon_vpmaxq_f16,
1430 NEON::BI__builtin_neon_vpmaxq_v,
1431 },
1432 {
1433 NEON::BI__builtin_neon_vpmin_f16,
1434 NEON::BI__builtin_neon_vpmin_v,
1435 },
1436 {
1437 NEON::BI__builtin_neon_vpminnm_f16,
1438 NEON::BI__builtin_neon_vpminnm_v,
1439 },
1440 {
1441 NEON::BI__builtin_neon_vpminnmq_f16,
1442 NEON::BI__builtin_neon_vpminnmq_v,
1443 },
1444 {
1445 NEON::BI__builtin_neon_vpminq_f16,
1446 NEON::BI__builtin_neon_vpminq_v,
1447 },
1448 {
1449 NEON::BI__builtin_neon_vrecpe_f16,
1450 NEON::BI__builtin_neon_vrecpe_v,
1451 },
1452 {
1453 NEON::BI__builtin_neon_vrecpeq_f16,
1454 NEON::BI__builtin_neon_vrecpeq_v,
1455 },
1456 {
1457 NEON::BI__builtin_neon_vrecps_f16,
1458 NEON::BI__builtin_neon_vrecps_v,
1459 },
1460 {
1461 NEON::BI__builtin_neon_vrecpsq_f16,
1462 NEON::BI__builtin_neon_vrecpsq_v,
1463 },
1464 {
1465 NEON::BI__builtin_neon_vrnd_f16,
1466 NEON::BI__builtin_neon_vrnd_v,
1467 },
1468 {
1469 NEON::BI__builtin_neon_vrnda_f16,
1470 NEON::BI__builtin_neon_vrnda_v,
1471 },
1472 {
1473 NEON::BI__builtin_neon_vrndaq_f16,
1474 NEON::BI__builtin_neon_vrndaq_v,
1475 },
1476 {
1477 NEON::BI__builtin_neon_vrndi_f16,
1478 NEON::BI__builtin_neon_vrndi_v,
1479 },
1480 {
1481 NEON::BI__builtin_neon_vrndiq_f16,
1482 NEON::BI__builtin_neon_vrndiq_v,
1483 },
1484 {
1485 NEON::BI__builtin_neon_vrndm_f16,
1486 NEON::BI__builtin_neon_vrndm_v,
1487 },
1488 {
1489 NEON::BI__builtin_neon_vrndmq_f16,
1490 NEON::BI__builtin_neon_vrndmq_v,
1491 },
1492 {
1493 NEON::BI__builtin_neon_vrndn_f16,
1494 NEON::BI__builtin_neon_vrndn_v,
1495 },
1496 {
1497 NEON::BI__builtin_neon_vrndnq_f16,
1498 NEON::BI__builtin_neon_vrndnq_v,
1499 },
1500 {
1501 NEON::BI__builtin_neon_vrndp_f16,
1502 NEON::BI__builtin_neon_vrndp_v,
1503 },
1504 {
1505 NEON::BI__builtin_neon_vrndpq_f16,
1506 NEON::BI__builtin_neon_vrndpq_v,
1507 },
1508 {
1509 NEON::BI__builtin_neon_vrndq_f16,
1510 NEON::BI__builtin_neon_vrndq_v,
1511 },
1512 {
1513 NEON::BI__builtin_neon_vrndx_f16,
1514 NEON::BI__builtin_neon_vrndx_v,
1515 },
1516 {
1517 NEON::BI__builtin_neon_vrndxq_f16,
1518 NEON::BI__builtin_neon_vrndxq_v,
1519 },
1520 {
1521 NEON::BI__builtin_neon_vrsqrte_f16,
1522 NEON::BI__builtin_neon_vrsqrte_v,
1523 },
1524 {
1525 NEON::BI__builtin_neon_vrsqrteq_f16,
1526 NEON::BI__builtin_neon_vrsqrteq_v,
1527 },
1528 {
1529 NEON::BI__builtin_neon_vrsqrts_f16,
1530 NEON::BI__builtin_neon_vrsqrts_v,
1531 },
1532 {
1533 NEON::BI__builtin_neon_vrsqrtsq_f16,
1534 NEON::BI__builtin_neon_vrsqrtsq_v,
1535 },
1536 {
1537 NEON::BI__builtin_neon_vsqrt_f16,
1538 NEON::BI__builtin_neon_vsqrt_v,
1539 },
1540 {
1541 NEON::BI__builtin_neon_vsqrtq_f16,
1542 NEON::BI__builtin_neon_vsqrtq_v,
1543 },
1544 {NEON::BI__builtin_neon_vst1_bf16_x2, NEON::BI__builtin_neon_vst1_x2_v},
1545 {NEON::BI__builtin_neon_vst1_bf16_x3, NEON::BI__builtin_neon_vst1_x3_v},
1546 {NEON::BI__builtin_neon_vst1_bf16_x4, NEON::BI__builtin_neon_vst1_x4_v},
1547 {NEON::BI__builtin_neon_vst1_bf16, NEON::BI__builtin_neon_vst1_v},
1548 {NEON::BI__builtin_neon_vst1_lane_bf16, NEON::BI__builtin_neon_vst1_lane_v},
1549 {NEON::BI__builtin_neon_vst1q_bf16_x2, NEON::BI__builtin_neon_vst1q_x2_v},
1550 {NEON::BI__builtin_neon_vst1q_bf16_x3, NEON::BI__builtin_neon_vst1q_x3_v},
1551 {NEON::BI__builtin_neon_vst1q_bf16_x4, NEON::BI__builtin_neon_vst1q_x4_v},
1552 {NEON::BI__builtin_neon_vst1q_bf16, NEON::BI__builtin_neon_vst1q_v},
1553 {NEON::BI__builtin_neon_vst1q_lane_bf16,
1554 NEON::BI__builtin_neon_vst1q_lane_v},
1555 {NEON::BI__builtin_neon_vst2_bf16, NEON::BI__builtin_neon_vst2_v},
1556 {NEON::BI__builtin_neon_vst2_lane_bf16, NEON::BI__builtin_neon_vst2_lane_v},
1557 {NEON::BI__builtin_neon_vst2q_bf16, NEON::BI__builtin_neon_vst2q_v},
1558 {NEON::BI__builtin_neon_vst2q_lane_bf16,
1559 NEON::BI__builtin_neon_vst2q_lane_v},
1560 {NEON::BI__builtin_neon_vst3_bf16, NEON::BI__builtin_neon_vst3_v},
1561 {NEON::BI__builtin_neon_vst3_lane_bf16, NEON::BI__builtin_neon_vst3_lane_v},
1562 {NEON::BI__builtin_neon_vst3q_bf16, NEON::BI__builtin_neon_vst3q_v},
1563 {NEON::BI__builtin_neon_vst3q_lane_bf16,
1564 NEON::BI__builtin_neon_vst3q_lane_v},
1565 {NEON::BI__builtin_neon_vst4_bf16, NEON::BI__builtin_neon_vst4_v},
1566 {NEON::BI__builtin_neon_vst4_lane_bf16, NEON::BI__builtin_neon_vst4_lane_v},
1567 {NEON::BI__builtin_neon_vst4q_bf16, NEON::BI__builtin_neon_vst4q_v},
1568 {NEON::BI__builtin_neon_vst4q_lane_bf16,
1569 NEON::BI__builtin_neon_vst4q_lane_v},
1570 // The mangling rules cause us to have one ID for each type for
1571 // vldap1(q)_lane and vstl1(q)_lane, but codegen is equivalent for all of
1572 // them. Choose an arbitrary one to be handled as tha canonical variation.
1573 {NEON::BI__builtin_neon_vldap1_lane_u64,
1574 NEON::BI__builtin_neon_vldap1_lane_s64},
1575 {NEON::BI__builtin_neon_vldap1_lane_f64,
1576 NEON::BI__builtin_neon_vldap1_lane_s64},
1577 {NEON::BI__builtin_neon_vldap1_lane_p64,
1578 NEON::BI__builtin_neon_vldap1_lane_s64},
1579 {NEON::BI__builtin_neon_vldap1q_lane_u64,
1580 NEON::BI__builtin_neon_vldap1q_lane_s64},
1581 {NEON::BI__builtin_neon_vldap1q_lane_f64,
1582 NEON::BI__builtin_neon_vldap1q_lane_s64},
1583 {NEON::BI__builtin_neon_vldap1q_lane_p64,
1584 NEON::BI__builtin_neon_vldap1q_lane_s64},
1585 {NEON::BI__builtin_neon_vstl1_lane_u64,
1586 NEON::BI__builtin_neon_vstl1_lane_s64},
1587 {NEON::BI__builtin_neon_vstl1_lane_f64,
1588 NEON::BI__builtin_neon_vstl1_lane_s64},
1589 {NEON::BI__builtin_neon_vstl1_lane_p64,
1590 NEON::BI__builtin_neon_vstl1_lane_s64},
1591 {NEON::BI__builtin_neon_vstl1q_lane_u64,
1592 NEON::BI__builtin_neon_vstl1q_lane_s64},
1593 {NEON::BI__builtin_neon_vstl1q_lane_f64,
1594 NEON::BI__builtin_neon_vstl1q_lane_s64},
1595 {NEON::BI__builtin_neon_vstl1q_lane_p64,
1596 NEON::BI__builtin_neon_vstl1q_lane_s64},
1597};
1598
1599std::optional<mlir::Value>
1602 llvm::Triple::ArchType arch) {
1603 if (builtinID >= clang::AArch64::FirstSVEBuiltin &&
1604 builtinID <= clang::AArch64::LastSVEBuiltin)
1605 return emitAArch64SVEBuiltinExpr(builtinID, expr);
1606
1607 if (builtinID >= clang::AArch64::FirstSMEBuiltin &&
1608 builtinID <= clang::AArch64::LastSMEBuiltin)
1609 return emitAArch64SMEBuiltinExpr(builtinID, expr);
1610
1611 if (builtinID == Builtin::BI__builtin_cpu_supports) {
1612 cgm.errorNYI(expr->getSourceRange(),
1613 std::string("unimplemented AArch64 builtin call: ") +
1614 getContext().BuiltinInfo.getName(builtinID));
1615 return mlir::Value{};
1616 }
1617
1618 switch (builtinID) {
1619 default:
1620 break;
1621 case clang::AArch64::BI__builtin_arm_nop:
1622 case clang::AArch64::BI__builtin_arm_yield:
1623 case clang::AArch64::BI__yield:
1624 case clang::AArch64::BI__builtin_arm_wfe:
1625 case clang::AArch64::BI__wfe:
1626 case clang::AArch64::BI__builtin_arm_wfi:
1627 case clang::AArch64::BI__wfi:
1628 case clang::AArch64::BI__builtin_arm_sev:
1629 case clang::AArch64::BI__sev:
1630 case clang::AArch64::BI__builtin_arm_sevl:
1631 case clang::AArch64::BI__sevl:
1632 cgm.errorNYI(expr->getSourceRange(),
1633 std::string("unimplemented AArch64 builtin call: ") +
1634 getContext().BuiltinInfo.getName(builtinID));
1635 return mlir::Value{};
1636 }
1637
1638 if (builtinID == clang::AArch64::BI__builtin_arm_trap) {
1639 cgm.errorNYI(expr->getSourceRange(),
1640 std::string("unimplemented AArch64 builtin call: ") +
1641 getContext().BuiltinInfo.getName(builtinID));
1642 return mlir::Value{};
1643 }
1644
1645 if (builtinID == clang::AArch64::BI__builtin_arm_get_sme_state) {
1646 cgm.errorNYI(expr->getSourceRange(),
1647 std::string("unimplemented AArch64 builtin call: ") +
1648 getContext().BuiltinInfo.getName(builtinID));
1649 return mlir::Value{};
1650 }
1651
1652 if (builtinID == clang::AArch64::BI__builtin_arm_rbit) {
1653 cgm.errorNYI(expr->getSourceRange(),
1654 std::string("unimplemented AArch64 builtin call: ") +
1655 getContext().BuiltinInfo.getName(builtinID));
1656 return mlir::Value{};
1657 }
1658 if (builtinID == clang::AArch64::BI__builtin_arm_rbit64) {
1659 cgm.errorNYI(expr->getSourceRange(),
1660 std::string("unimplemented AArch64 builtin call: ") +
1661 getContext().BuiltinInfo.getName(builtinID));
1662 return mlir::Value{};
1663 }
1664
1665 if (builtinID == clang::AArch64::BI__builtin_arm_clz ||
1666 builtinID == clang::AArch64::BI__builtin_arm_clz64) {
1667 cgm.errorNYI(expr->getSourceRange(),
1668 std::string("unimplemented AArch64 builtin call: ") +
1669 getContext().BuiltinInfo.getName(builtinID));
1670 return mlir::Value{};
1671 }
1672
1673 if (builtinID == clang::AArch64::BI__builtin_arm_cls) {
1674 cgm.errorNYI(expr->getSourceRange(),
1675 std::string("unimplemented AArch64 builtin call: ") +
1676 getContext().BuiltinInfo.getName(builtinID));
1677 return mlir::Value{};
1678 }
1679 if (builtinID == clang::AArch64::BI__builtin_arm_cls64) {
1680 cgm.errorNYI(expr->getSourceRange(),
1681 std::string("unimplemented AArch64 builtin call: ") +
1682 getContext().BuiltinInfo.getName(builtinID));
1683 return mlir::Value{};
1684 }
1685
1686 if (builtinID == clang::AArch64::BI__builtin_arm_rint32zf ||
1687 builtinID == clang::AArch64::BI__builtin_arm_rint32z) {
1688 cgm.errorNYI(expr->getSourceRange(),
1689 std::string("unimplemented AArch64 builtin call: ") +
1690 getContext().BuiltinInfo.getName(builtinID));
1691 return mlir::Value{};
1692 }
1693
1694 if (builtinID == clang::AArch64::BI__builtin_arm_rint64zf ||
1695 builtinID == clang::AArch64::BI__builtin_arm_rint64z) {
1696 cgm.errorNYI(expr->getSourceRange(),
1697 std::string("unimplemented AArch64 builtin call: ") +
1698 getContext().BuiltinInfo.getName(builtinID));
1699 return mlir::Value{};
1700 }
1701
1702 if (builtinID == clang::AArch64::BI__builtin_arm_rint32xf ||
1703 builtinID == clang::AArch64::BI__builtin_arm_rint32x) {
1704 cgm.errorNYI(expr->getSourceRange(),
1705 std::string("unimplemented AArch64 builtin call: ") +
1706 getContext().BuiltinInfo.getName(builtinID));
1707 return mlir::Value{};
1708 }
1709
1710 if (builtinID == clang::AArch64::BI__builtin_arm_rint64xf ||
1711 builtinID == clang::AArch64::BI__builtin_arm_rint64x) {
1712 cgm.errorNYI(expr->getSourceRange(),
1713 std::string("unimplemented AArch64 builtin call: ") +
1714 getContext().BuiltinInfo.getName(builtinID));
1715 return mlir::Value{};
1716 }
1717
1718 if (builtinID == clang::AArch64::BI__builtin_arm_jcvt) {
1719 cgm.errorNYI(expr->getSourceRange(),
1720 std::string("unimplemented AArch64 builtin call: ") +
1721 getContext().BuiltinInfo.getName(builtinID));
1722 return mlir::Value{};
1723 }
1724
1725 if (builtinID == clang::AArch64::BI__builtin_arm_ld64b ||
1726 builtinID == clang::AArch64::BI__builtin_arm_st64b ||
1727 builtinID == clang::AArch64::BI__builtin_arm_st64bv ||
1728 builtinID == clang::AArch64::BI__builtin_arm_st64bv0) {
1729 cgm.errorNYI(expr->getSourceRange(),
1730 std::string("unimplemented AArch64 builtin call: ") +
1731 getContext().BuiltinInfo.getName(builtinID));
1732 return mlir::Value{};
1733 }
1734
1735 if (builtinID == clang::AArch64::BI__builtin_arm_rndr ||
1736 builtinID == clang::AArch64::BI__builtin_arm_rndrrs) {
1737 cgm.errorNYI(expr->getSourceRange(),
1738 std::string("unimplemented AArch64 builtin call: ") +
1739 getContext().BuiltinInfo.getName(builtinID));
1740 return mlir::Value{};
1741 }
1742
1743 if (builtinID == clang::AArch64::BI__clear_cache) {
1744 cgm.errorNYI(expr->getSourceRange(),
1745 std::string("unimplemented AArch64 builtin call: ") +
1746 getContext().BuiltinInfo.getName(builtinID));
1747 return mlir::Value{};
1748 }
1749
1750 if ((builtinID == clang::AArch64::BI__builtin_arm_ldrex ||
1751 builtinID == clang::AArch64::BI__builtin_arm_ldaex) &&
1752 getContext().getTypeSize(expr->getType()) == 128) {
1753 cgm.errorNYI(expr->getSourceRange(),
1754 std::string("unimplemented AArch64 builtin call: ") +
1755 getContext().BuiltinInfo.getName(builtinID));
1756 return mlir::Value{};
1757 }
1758 if (builtinID == clang::AArch64::BI__builtin_arm_ldrex ||
1759 builtinID == clang::AArch64::BI__builtin_arm_ldaex) {
1760 cgm.errorNYI(expr->getSourceRange(),
1761 std::string("unimplemented AArch64 builtin call: ") +
1762 getContext().BuiltinInfo.getName(builtinID));
1763 return mlir::Value{};
1764 }
1765
1766 if ((builtinID == clang::AArch64::BI__builtin_arm_strex ||
1767 builtinID == clang::AArch64::BI__builtin_arm_stlex) &&
1768 getContext().getTypeSize(expr->getArg(0)->getType()) == 128) {
1769 cgm.errorNYI(expr->getSourceRange(),
1770 std::string("unimplemented AArch64 builtin call: ") +
1771 getContext().BuiltinInfo.getName(builtinID));
1772 return mlir::Value{};
1773 }
1774
1775 if (builtinID == clang::AArch64::BI__builtin_arm_strex ||
1776 builtinID == clang::AArch64::BI__builtin_arm_stlex) {
1777 cgm.errorNYI(expr->getSourceRange(),
1778 std::string("unimplemented AArch64 builtin call: ") +
1779 getContext().BuiltinInfo.getName(builtinID));
1780 return mlir::Value{};
1781 }
1782
1783 if (builtinID == clang::AArch64::BI__getReg) {
1784 cgm.errorNYI(expr->getSourceRange(),
1785 std::string("unimplemented AArch64 builtin call: ") +
1786 getContext().BuiltinInfo.getName(builtinID));
1787 return mlir::Value{};
1788 }
1789
1790 if (builtinID == clang::AArch64::BI__break) {
1791 cgm.errorNYI(expr->getSourceRange(),
1792 std::string("unimplemented AArch64 builtin call: ") +
1793 getContext().BuiltinInfo.getName(builtinID));
1794 return mlir::Value{};
1795 }
1796
1797 if (builtinID == clang::AArch64::BI__builtin_arm_clrex) {
1798 cgm.errorNYI(expr->getSourceRange(),
1799 std::string("unimplemented AArch64 builtin call: ") +
1800 getContext().BuiltinInfo.getName(builtinID));
1801 return mlir::Value{};
1802 }
1803
1804 if (builtinID == clang::AArch64::BI_ReadWriteBarrier) {
1805 cgm.errorNYI(expr->getSourceRange(),
1806 std::string("unimplemented AArch64 builtin call: ") +
1807 getContext().BuiltinInfo.getName(builtinID));
1808 return mlir::Value{};
1809 }
1810
1811 // CRC32
1812 Intrinsic::ID crcIntrinsicID = Intrinsic::not_intrinsic;
1813 switch (builtinID) {
1814 case clang::AArch64::BI__builtin_arm_crc32b:
1815 crcIntrinsicID = Intrinsic::aarch64_crc32b;
1816 break;
1817 case clang::AArch64::BI__builtin_arm_crc32cb:
1818 crcIntrinsicID = Intrinsic::aarch64_crc32cb;
1819 break;
1820 case clang::AArch64::BI__builtin_arm_crc32h:
1821 crcIntrinsicID = Intrinsic::aarch64_crc32h;
1822 break;
1823 case clang::AArch64::BI__builtin_arm_crc32ch:
1824 crcIntrinsicID = Intrinsic::aarch64_crc32ch;
1825 break;
1826 case clang::AArch64::BI__builtin_arm_crc32w:
1827 crcIntrinsicID = Intrinsic::aarch64_crc32w;
1828 break;
1829 case clang::AArch64::BI__builtin_arm_crc32cw:
1830 crcIntrinsicID = Intrinsic::aarch64_crc32cw;
1831 break;
1832 case clang::AArch64::BI__builtin_arm_crc32d:
1833 crcIntrinsicID = Intrinsic::aarch64_crc32x;
1834 break;
1835 case clang::AArch64::BI__builtin_arm_crc32cd:
1836 crcIntrinsicID = Intrinsic::aarch64_crc32cx;
1837 break;
1838 }
1839
1840 if (crcIntrinsicID != Intrinsic::not_intrinsic) {
1841 cgm.errorNYI(expr->getSourceRange(),
1842 std::string("unimplemented AArch64 builtin call: ") +
1843 getContext().BuiltinInfo.getName(builtinID));
1844 return mlir::Value{};
1845 }
1846
1847 // Memory Operations (MOPS)
1848 if (builtinID == AArch64::BI__builtin_arm_mops_memset_tag) {
1849 cgm.errorNYI(expr->getSourceRange(),
1850 std::string("unimplemented AArch64 builtin call: ") +
1851 getContext().BuiltinInfo.getName(builtinID));
1852 return mlir::Value{};
1853 }
1854
1855 // Memory Tagging Extensions (MTE) Intrinsics
1856 Intrinsic::ID mteIntrinsicID = Intrinsic::not_intrinsic;
1857 switch (builtinID) {
1858 case clang::AArch64::BI__builtin_arm_irg:
1859 mteIntrinsicID = Intrinsic::aarch64_irg;
1860 break;
1861 case clang::AArch64::BI__builtin_arm_addg:
1862 mteIntrinsicID = Intrinsic::aarch64_addg;
1863 break;
1864 case clang::AArch64::BI__builtin_arm_gmi:
1865 mteIntrinsicID = Intrinsic::aarch64_gmi;
1866 break;
1867 case clang::AArch64::BI__builtin_arm_ldg:
1868 mteIntrinsicID = Intrinsic::aarch64_ldg;
1869 break;
1870 case clang::AArch64::BI__builtin_arm_stg:
1871 mteIntrinsicID = Intrinsic::aarch64_stg;
1872 break;
1873 case clang::AArch64::BI__builtin_arm_subp:
1874 mteIntrinsicID = Intrinsic::aarch64_subp;
1875 break;
1876 }
1877
1878 if (mteIntrinsicID != Intrinsic::not_intrinsic) {
1879 cgm.errorNYI(expr->getSourceRange(),
1880 std::string("unimplemented AArch64 builtin call: ") +
1881 getContext().BuiltinInfo.getName(builtinID));
1882 return mlir::Value{};
1883 }
1884
1885 if (builtinID == clang::AArch64::BI__builtin_arm_rsr ||
1886 builtinID == clang::AArch64::BI__builtin_arm_rsr64 ||
1887 builtinID == clang::AArch64::BI__builtin_arm_rsr128 ||
1888 builtinID == clang::AArch64::BI__builtin_arm_rsrp ||
1889 builtinID == clang::AArch64::BI__builtin_arm_wsr ||
1890 builtinID == clang::AArch64::BI__builtin_arm_wsr64 ||
1891 builtinID == clang::AArch64::BI__builtin_arm_wsr128 ||
1892 builtinID == clang::AArch64::BI__builtin_arm_wsrp) {
1893 cgm.errorNYI(expr->getSourceRange(),
1894 std::string("unimplemented AArch64 builtin call: ") +
1895 getContext().BuiltinInfo.getName(builtinID));
1896 return mlir::Value{};
1897 }
1898
1899 if (builtinID == clang::AArch64::BI_ReadStatusReg ||
1900 builtinID == clang::AArch64::BI_WriteStatusReg ||
1901 builtinID == clang::AArch64::BI__sys) {
1902 cgm.errorNYI(expr->getSourceRange(),
1903 std::string("unimplemented AArch64 builtin call: ") +
1904 getContext().BuiltinInfo.getName(builtinID));
1905 return mlir::Value{};
1906 }
1907
1908 if (builtinID == clang::AArch64::BI_AddressOfReturnAddress) {
1909 cgm.errorNYI(expr->getSourceRange(),
1910 std::string("unimplemented AArch64 builtin call: ") +
1911 getContext().BuiltinInfo.getName(builtinID));
1912 return mlir::Value{};
1913 }
1914
1915 if (builtinID == clang::AArch64::BI__builtin_sponentry) {
1916 cgm.errorNYI(expr->getSourceRange(),
1917 std::string("unimplemented AArch64 builtin call: ") +
1918 getContext().BuiltinInfo.getName(builtinID));
1919 return mlir::Value{};
1920 }
1921
1922 if (builtinID == clang::AArch64::BI__mulh ||
1923 builtinID == clang::AArch64::BI__umulh) {
1924 cgm.errorNYI(expr->getSourceRange(),
1925 std::string("unimplemented AArch64 builtin call: ") +
1926 getContext().BuiltinInfo.getName(builtinID));
1927 return mlir::Value{};
1928 }
1929
1930 if (builtinID == AArch64::BI__writex18byte ||
1931 builtinID == AArch64::BI__writex18word ||
1932 builtinID == AArch64::BI__writex18dword ||
1933 builtinID == AArch64::BI__writex18qword) {
1934 cgm.errorNYI(expr->getSourceRange(),
1935 std::string("unimplemented AArch64 builtin call: ") +
1936 getContext().BuiltinInfo.getName(builtinID));
1937 return mlir::Value{};
1938 }
1939
1940 if (builtinID == AArch64::BI__readx18byte ||
1941 builtinID == AArch64::BI__readx18word ||
1942 builtinID == AArch64::BI__readx18dword ||
1943 builtinID == AArch64::BI__readx18qword) {
1944 cgm.errorNYI(expr->getSourceRange(),
1945 std::string("unimplemented AArch64 builtin call: ") +
1946 getContext().BuiltinInfo.getName(builtinID));
1947 return mlir::Value{};
1948 }
1949
1950 if (builtinID == AArch64::BI__addx18byte ||
1951 builtinID == AArch64::BI__addx18word ||
1952 builtinID == AArch64::BI__addx18dword ||
1953 builtinID == AArch64::BI__addx18qword ||
1954 builtinID == AArch64::BI__incx18byte ||
1955 builtinID == AArch64::BI__incx18word ||
1956 builtinID == AArch64::BI__incx18dword ||
1957 builtinID == AArch64::BI__incx18qword) {
1958 cgm.errorNYI(expr->getSourceRange(),
1959 std::string("unimplemented AArch64 builtin call: ") +
1960 getContext().BuiltinInfo.getName(builtinID));
1961 return mlir::Value{};
1962 }
1963
1964 if (builtinID == AArch64::BI_CopyDoubleFromInt64 ||
1965 builtinID == AArch64::BI_CopyFloatFromInt32 ||
1966 builtinID == AArch64::BI_CopyInt32FromFloat ||
1967 builtinID == AArch64::BI_CopyInt64FromDouble) {
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 == AArch64::BI_CountLeadingOnes ||
1975 builtinID == AArch64::BI_CountLeadingOnes64 ||
1976 builtinID == AArch64::BI_CountLeadingZeros ||
1977 builtinID == AArch64::BI_CountLeadingZeros64) {
1978 cgm.errorNYI(expr->getSourceRange(),
1979 std::string("unimplemented AArch64 builtin call: ") +
1980 getContext().BuiltinInfo.getName(builtinID));
1981 return mlir::Value{};
1982 }
1983
1984 if (builtinID == AArch64::BI_CountLeadingSigns ||
1985 builtinID == AArch64::BI_CountLeadingSigns64) {
1986 cgm.errorNYI(expr->getSourceRange(),
1987 std::string("unimplemented AArch64 builtin call: ") +
1988 getContext().BuiltinInfo.getName(builtinID));
1989 return mlir::Value{};
1990 }
1991
1992 if (builtinID == AArch64::BI_CountOneBits ||
1993 builtinID == AArch64::BI_CountOneBits64) {
1994 cgm.errorNYI(expr->getSourceRange(),
1995 std::string("unimplemented AArch64 builtin call: ") +
1996 getContext().BuiltinInfo.getName(builtinID));
1997 return mlir::Value{};
1998 }
1999
2000 if (builtinID == AArch64::BI__prefetch) {
2001 cgm.errorNYI(expr->getSourceRange(),
2002 std::string("unimplemented AArch64 builtin call: ") +
2003 getContext().BuiltinInfo.getName(builtinID));
2004 return mlir::Value{};
2005 }
2006
2007 if (builtinID == AArch64::BI__hlt) {
2008 cgm.errorNYI(expr->getSourceRange(),
2009 std::string("unimplemented AArch64 builtin call: ") +
2010 getContext().BuiltinInfo.getName(builtinID));
2011 return mlir::Value{};
2012 }
2013
2014 if (builtinID == NEON::BI__builtin_neon_vcvth_bf16_f32) {
2015 cgm.errorNYI(expr->getSourceRange(),
2016 std::string("unimplemented AArch64 builtin call: ") +
2017 getContext().BuiltinInfo.getName(builtinID));
2018 return mlir::Value{};
2019 }
2020
2021 // Handle MSVC intrinsics before argument evaluation to prevent double
2022 // evaluation.
2024
2025 // Some intrinsics are equivalent - if they are use the base intrinsic ID.
2026 auto it = llvm::find_if(neonEquivalentIntrinsicMap, [builtinID](auto &p) {
2027 return p.first == builtinID;
2028 });
2029 if (it != end(neonEquivalentIntrinsicMap))
2030 builtinID = it->second;
2031
2032 // Find out if any arguments are required to be integer constant
2033 // expressions.
2035 unsigned iceArguments = 0;
2037 getContext().GetBuiltinType(builtinID, error, &iceArguments);
2038 assert(error == ASTContext::GE_None && "Should not codegen an error");
2040
2041 // Skip extra arguments used to discriminate vector types and that are
2042 // intended for Sema checking.
2043 bool hasExtraArg = hasExtraNeonArgument(builtinID);
2044 unsigned numArgs = expr->getNumArgs() - (hasExtraArg ? 1 : 0);
2045 for (unsigned i = 0, e = numArgs; i != e; i++) {
2046 if (i == 0) {
2047 switch (builtinID) {
2048 case NEON::BI__builtin_neon_vld1_v:
2049 case NEON::BI__builtin_neon_vld1q_v:
2050 case NEON::BI__builtin_neon_vld1_dup_v:
2051 case NEON::BI__builtin_neon_vld1q_dup_v:
2052 case NEON::BI__builtin_neon_vld1_lane_v:
2053 case NEON::BI__builtin_neon_vld1q_lane_v:
2054 case NEON::BI__builtin_neon_vst1_v:
2055 case NEON::BI__builtin_neon_vst1q_v:
2056 case NEON::BI__builtin_neon_vst1_lane_v:
2057 case NEON::BI__builtin_neon_vst1q_lane_v:
2058 case NEON::BI__builtin_neon_vldap1_lane_s64:
2059 case NEON::BI__builtin_neon_vldap1q_lane_s64:
2060 case NEON::BI__builtin_neon_vstl1_lane_s64:
2061 case NEON::BI__builtin_neon_vstl1q_lane_s64:
2062 // Get the alignment for the argument in addition to the value;
2063 // we'll use it later.
2064 cgm.errorNYI(
2065 expr->getSourceRange(),
2066 std::string("unimplemented AArch64 builtin argument handling ") +
2067 getContext().BuiltinInfo.getName(builtinID));
2068 }
2069 }
2070 ops.push_back(
2071 emitScalarOrConstFoldImmArg(iceArguments, i, expr->getArg(i)));
2072 }
2073
2076 if (builtin)
2077 return emitCommonNeonSISDBuiltinExpr(*this, *builtin, ops, expr);
2078
2079 // Not all intrinsics handled by the common case work for AArch64 yet, so only
2080 // defer to common code if it's been added to our special map.
2082
2084
2085 const Expr *arg = expr->getArg(expr->getNumArgs() - 1);
2087 // A trailing constant integer is used for discriminating overloaded builtin
2088 // calls. Use it to determine the type of this overloaded NEON intrinsic.
2089 if (std::optional<llvm::APSInt> result =
2090 arg->getIntegerConstantExpr(getContext()))
2091 type = NeonTypeFlags(result->getZExtValue());
2092
2093 bool usgn = type.isUnsigned();
2094
2095 mlir::Location loc = getLoc(expr->getExprLoc());
2096
2097 // Not all intrinsics handled by the common case work for AArch64 yet, so only
2098 // defer to common code if it's been added to our special map.
2101 if (builtin)
2103 *this, builtin->BuiltinID, builtin->LLVMIntrinsic,
2104 builtin->AltLLVMIntrinsic, builtin->NameHint, builtin->TypeModifier,
2105 expr, ops);
2106
2107 // Handle non-overloaded intrinsics first.
2108 switch (builtinID) {
2109 default:
2110 break;
2111 case NEON::BI__builtin_neon_vabsh_f16: {
2112 return cir::FAbsOp::create(builder, loc, ops);
2113 }
2114 case NEON::BI__builtin_neon_vaddq_p128:
2115 case NEON::BI__builtin_neon_vldrq_p128:
2116 case NEON::BI__builtin_neon_vstrq_p128:
2117 case NEON::BI__builtin_neon_vcvts_f32_u32:
2118 case NEON::BI__builtin_neon_vcvtd_f64_u64:
2119 case NEON::BI__builtin_neon_vcvts_f32_s32:
2120 case NEON::BI__builtin_neon_vcvtd_f64_s64:
2121 case NEON::BI__builtin_neon_vcvth_f16_u16:
2122 case NEON::BI__builtin_neon_vcvth_f16_u32:
2123 case NEON::BI__builtin_neon_vcvth_f16_u64:
2124 case NEON::BI__builtin_neon_vcvth_f16_s16:
2125 case NEON::BI__builtin_neon_vcvth_f16_s32:
2126 case NEON::BI__builtin_neon_vcvth_f16_s64:
2127 case NEON::BI__builtin_neon_vcvtah_u16_f16:
2128 case NEON::BI__builtin_neon_vcvtmh_u16_f16:
2129 case NEON::BI__builtin_neon_vcvtnh_u16_f16:
2130 case NEON::BI__builtin_neon_vcvtph_u16_f16:
2131 case NEON::BI__builtin_neon_vcvth_u16_f16:
2132 case NEON::BI__builtin_neon_vcvtah_s16_f16:
2133 case NEON::BI__builtin_neon_vcvtmh_s16_f16:
2134 case NEON::BI__builtin_neon_vcvtnh_s16_f16:
2135 case NEON::BI__builtin_neon_vcvtph_s16_f16:
2136 case NEON::BI__builtin_neon_vcvth_s16_f16:
2137 case NEON::BI__builtin_neon_vcaleh_f16:
2138 case NEON::BI__builtin_neon_vcalth_f16:
2139 case NEON::BI__builtin_neon_vcageh_f16:
2140 case NEON::BI__builtin_neon_vcagth_f16:
2141 case NEON::BI__builtin_neon_vcvth_n_s16_f16:
2142 case NEON::BI__builtin_neon_vcvth_n_u16_f16:
2143 case NEON::BI__builtin_neon_vcvth_n_f16_s16:
2144 case NEON::BI__builtin_neon_vcvth_n_f16_u16:
2145 case NEON::BI__builtin_neon_vpaddd_s64:
2146 case NEON::BI__builtin_neon_vpaddd_f64:
2147 case NEON::BI__builtin_neon_vpadds_f32:
2148 cgm.errorNYI(expr->getSourceRange(),
2149 std::string("unimplemented AArch64 builtin call: ") +
2150 getContext().BuiltinInfo.getName(builtinID));
2151 return mlir::Value{};
2152 case NEON::BI__builtin_neon_vceqzd_s64:
2153 case NEON::BI__builtin_neon_vceqzd_f64:
2154 case NEON::BI__builtin_neon_vceqzs_f32:
2155 case NEON::BI__builtin_neon_vceqzh_f16:
2157 *this, builder, loc, ops[0],
2158 convertType(expr->getCallReturnType(getContext())), cir::CmpOpKind::eq);
2159 case NEON::BI__builtin_neon_vcgezd_s64:
2160 case NEON::BI__builtin_neon_vcgezd_f64:
2161 case NEON::BI__builtin_neon_vcgezs_f32:
2162 case NEON::BI__builtin_neon_vcgezh_f16:
2163 case NEON::BI__builtin_neon_vclezd_s64:
2164 case NEON::BI__builtin_neon_vclezd_f64:
2165 case NEON::BI__builtin_neon_vclezs_f32:
2166 case NEON::BI__builtin_neon_vclezh_f16:
2167 case NEON::BI__builtin_neon_vcgtzd_s64:
2168 case NEON::BI__builtin_neon_vcgtzd_f64:
2169 case NEON::BI__builtin_neon_vcgtzs_f32:
2170 case NEON::BI__builtin_neon_vcgtzh_f16:
2171 case NEON::BI__builtin_neon_vcltzd_s64:
2172 case NEON::BI__builtin_neon_vcltzd_f64:
2173 case NEON::BI__builtin_neon_vcltzs_f32:
2174 case NEON::BI__builtin_neon_vcltzh_f16:
2175 case NEON::BI__builtin_neon_vceqzd_u64: {
2177 *this, builder, loc, ops[0],
2178 convertType(expr->getCallReturnType(getContext())), cir::CmpOpKind::eq);
2179 }
2180 case NEON::BI__builtin_neon_vceqd_f64:
2181 case NEON::BI__builtin_neon_vcled_f64:
2182 case NEON::BI__builtin_neon_vcltd_f64:
2183 case NEON::BI__builtin_neon_vcged_f64:
2184 case NEON::BI__builtin_neon_vcgtd_f64:
2185 case NEON::BI__builtin_neon_vceqs_f32:
2186 case NEON::BI__builtin_neon_vcles_f32:
2187 case NEON::BI__builtin_neon_vclts_f32:
2188 case NEON::BI__builtin_neon_vcges_f32:
2189 case NEON::BI__builtin_neon_vcgts_f32:
2190 case NEON::BI__builtin_neon_vceqh_f16:
2191 case NEON::BI__builtin_neon_vcleh_f16:
2192 case NEON::BI__builtin_neon_vclth_f16:
2193 case NEON::BI__builtin_neon_vcgeh_f16:
2194 case NEON::BI__builtin_neon_vcgth_f16:
2195 case NEON::BI__builtin_neon_vceqd_s64:
2196 case NEON::BI__builtin_neon_vceqd_u64:
2197 case NEON::BI__builtin_neon_vcgtd_s64:
2198 case NEON::BI__builtin_neon_vcgtd_u64:
2199 case NEON::BI__builtin_neon_vcltd_s64:
2200 case NEON::BI__builtin_neon_vcltd_u64:
2201 case NEON::BI__builtin_neon_vcged_u64:
2202 case NEON::BI__builtin_neon_vcged_s64:
2203 case NEON::BI__builtin_neon_vcled_u64:
2204 case NEON::BI__builtin_neon_vcled_s64:
2205 cgm.errorNYI(expr->getSourceRange(),
2206 std::string("unimplemented AArch64 builtin call: ") +
2207 getContext().BuiltinInfo.getName(builtinID));
2208 return mlir::Value{};
2209 case NEON::BI__builtin_neon_vnegd_s64: {
2210 return builder.createNeg(ops[0]);
2211 }
2212 case NEON::BI__builtin_neon_vnegh_f16: {
2213 return builder.createFNeg(ops[0]);
2214 }
2215 case NEON::BI__builtin_neon_vtstd_s64:
2216 case NEON::BI__builtin_neon_vtstd_u64:
2217 case NEON::BI__builtin_neon_vset_lane_i8:
2218 case NEON::BI__builtin_neon_vset_lane_i16:
2219 case NEON::BI__builtin_neon_vset_lane_i32:
2220 case NEON::BI__builtin_neon_vset_lane_i64:
2221 case NEON::BI__builtin_neon_vset_lane_bf16:
2222 case NEON::BI__builtin_neon_vset_lane_f32:
2223 case NEON::BI__builtin_neon_vsetq_lane_i8:
2224 case NEON::BI__builtin_neon_vsetq_lane_i16:
2225 case NEON::BI__builtin_neon_vsetq_lane_i32:
2226 case NEON::BI__builtin_neon_vsetq_lane_i64:
2227 case NEON::BI__builtin_neon_vsetq_lane_bf16:
2228 case NEON::BI__builtin_neon_vsetq_lane_f32:
2229 case NEON::BI__builtin_neon_vset_lane_f64:
2230 case NEON::BI__builtin_neon_vset_lane_mf8:
2231 case NEON::BI__builtin_neon_vsetq_lane_mf8:
2232 case NEON::BI__builtin_neon_vsetq_lane_f64:
2233 case NEON::BI__builtin_neon_vget_lane_i8:
2234 case NEON::BI__builtin_neon_vdupb_lane_i8:
2235 case NEON::BI__builtin_neon_vgetq_lane_i8:
2236 case NEON::BI__builtin_neon_vdupb_laneq_i8:
2237 case NEON::BI__builtin_neon_vget_lane_mf8:
2238 case NEON::BI__builtin_neon_vdupb_lane_mf8:
2239 case NEON::BI__builtin_neon_vgetq_lane_mf8:
2240 case NEON::BI__builtin_neon_vdupb_laneq_mf8:
2241 case NEON::BI__builtin_neon_vget_lane_i16:
2242 case NEON::BI__builtin_neon_vduph_lane_i16:
2243 case NEON::BI__builtin_neon_vgetq_lane_i16:
2244 case NEON::BI__builtin_neon_vduph_laneq_i16:
2245 case NEON::BI__builtin_neon_vget_lane_i32:
2246 case NEON::BI__builtin_neon_vdups_lane_i32:
2247 case NEON::BI__builtin_neon_vdups_lane_f32:
2248 case NEON::BI__builtin_neon_vgetq_lane_i32:
2249 case NEON::BI__builtin_neon_vdups_laneq_i32:
2250 case NEON::BI__builtin_neon_vget_lane_i64:
2251 case NEON::BI__builtin_neon_vdupd_lane_i64:
2252 case NEON::BI__builtin_neon_vdupd_lane_f64:
2253 case NEON::BI__builtin_neon_vgetq_lane_i64:
2254 case NEON::BI__builtin_neon_vdupd_laneq_i64:
2255 case NEON::BI__builtin_neon_vget_lane_f32:
2256 case NEON::BI__builtin_neon_vget_lane_f64:
2257 case NEON::BI__builtin_neon_vgetq_lane_f32:
2258 case NEON::BI__builtin_neon_vdups_laneq_f32:
2259 case NEON::BI__builtin_neon_vgetq_lane_f64:
2260 case NEON::BI__builtin_neon_vdupd_laneq_f64:
2261 cgm.errorNYI(expr->getSourceRange(),
2262 std::string("unimplemented AArch64 builtin call: ") +
2263 getContext().BuiltinInfo.getName(builtinID));
2264 return mlir::Value{};
2265 case NEON::BI__builtin_neon_vaddh_f16:
2266 return builder.createFAdd(loc, ops[0], ops[1]);
2267 case NEON::BI__builtin_neon_vsubh_f16:
2268 return builder.createFSub(loc, ops[0], ops[1]);
2269 case NEON::BI__builtin_neon_vmulh_f16:
2270 return builder.createFMul(loc, ops[0], ops[1]);
2271 case NEON::BI__builtin_neon_vdivh_f16:
2272 return builder.createFDiv(loc, ops[0], ops[1]);
2273 case NEON::BI__builtin_neon_vfmah_f16:
2274 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
2275 std::rotate(ops.begin(), ops.begin() + 1, ops.end());
2276 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma",
2277 convertType(expr->getType()), ops);
2278 break;
2279 case NEON::BI__builtin_neon_vfmsh_f16:
2280 // NEON intrinsic puts accumulator first, unlike the LLVM fma.
2281 std::rotate(ops.begin(), ops.begin() + 1, ops.end());
2282 ops[0] = builder.createFNeg(ops[0]);
2283 return emitCallMaybeConstrainedBuiltin(builder, loc, "fma",
2284 convertType(expr->getType()), ops);
2285 case NEON::BI__builtin_neon_vaddd_s64:
2286 case NEON::BI__builtin_neon_vaddd_u64:
2287 case NEON::BI__builtin_neon_vsubd_s64:
2288 case NEON::BI__builtin_neon_vsubd_u64:
2289 case NEON::BI__builtin_neon_vqdmlalh_s16:
2290 case NEON::BI__builtin_neon_vqdmlslh_s16:
2291 case NEON::BI__builtin_neon_vqshlud_n_s64:
2292 case NEON::BI__builtin_neon_vqshld_n_u64:
2293 case NEON::BI__builtin_neon_vqshld_n_s64:
2294 case NEON::BI__builtin_neon_vrshrd_n_u64:
2295 case NEON::BI__builtin_neon_vrshrd_n_s64:
2296 cgm.errorNYI(expr->getSourceRange(),
2297 std::string("unimplemented AArch64 builtin call: ") +
2298 getContext().BuiltinInfo.getName(builtinID));
2299 return mlir::Value{};
2300 case NEON::BI__builtin_neon_vrsrad_n_u64:
2301 case NEON::BI__builtin_neon_vrsrad_n_s64: {
2302 cir::IntType int64Type = builtinID == NEON::BI__builtin_neon_vrsrad_n_u64
2303 ? builder.getUInt64Ty()
2304 : builder.getSInt64Ty();
2305 ops[2] = builder.createNeg(ops[2]);
2306 const StringRef intrName = builtinID == NEON::BI__builtin_neon_vrsrad_n_u64
2307 ? "aarch64.neon.urshl"
2308 : "aarch64.neon.srshl";
2309
2311 ops[1], builder.createIntCast(ops[2], builder.getSInt64Ty())};
2312 ops[1] = builder.emitIntrinsicCallOp(loc, intrName, int64Type, args);
2313 return builder.createAdd(loc, ops[0],
2314 builder.createBitcast(ops[1], int64Type));
2315 }
2316 case NEON::BI__builtin_neon_vshld_n_s64:
2317 case NEON::BI__builtin_neon_vshld_n_u64: {
2318 auto loc = getLoc(expr->getExprLoc());
2319 std::optional<llvm::APSInt> amt =
2320 expr->getArg(1)->getIntegerConstantExpr(getContext());
2321 assert(amt && "Expected argument to be a constant");
2322 return builder.createShiftLeft(loc, ops[0], amt->getZExtValue());
2323 }
2324 case NEON::BI__builtin_neon_vshrd_n_s64: {
2325 std::optional<llvm::APSInt> amt =
2326 expr->getArg(1)->getIntegerConstantExpr(getContext());
2327 assert(amt && "Expected argument to be a constant");
2328 return builder.createShiftRight(
2329 loc, ops[0], std::min(static_cast<uint64_t>(63), amt->getZExtValue()));
2330 }
2331 case NEON::BI__builtin_neon_vshrd_n_u64: {
2332 std::optional<llvm::APSInt> amt =
2333 expr->getArg(1)->getIntegerConstantExpr(getContext());
2334 assert(amt && "Expected argument to be a constant");
2335 uint64_t shiftAmt = amt->getZExtValue();
2336 // Right-shifting an unsigned value by its size yields 0.
2337 if (shiftAmt == 64)
2338 return builder.getConstInt(loc, builder.getUInt64Ty(), 0);
2339 return builder.createShiftRight(loc, ops[0], shiftAmt);
2340 }
2341 case NEON::BI__builtin_neon_vsrad_n_s64:
2342 case NEON::BI__builtin_neon_vsrad_n_u64:
2343 case NEON::BI__builtin_neon_vqdmlalh_lane_s16:
2344 case NEON::BI__builtin_neon_vqdmlalh_laneq_s16:
2345 case NEON::BI__builtin_neon_vqdmlslh_lane_s16:
2346 case NEON::BI__builtin_neon_vqdmlslh_laneq_s16:
2347 case NEON::BI__builtin_neon_vqdmlals_s32:
2348 case NEON::BI__builtin_neon_vqdmlsls_s32:
2349 case NEON::BI__builtin_neon_vqdmlals_lane_s32:
2350 case NEON::BI__builtin_neon_vqdmlals_laneq_s32:
2351 case NEON::BI__builtin_neon_vqdmlsls_lane_s32:
2352 case NEON::BI__builtin_neon_vqdmlsls_laneq_s32: {
2353 cgm.errorNYI(expr->getSourceRange(),
2354 std::string("unimplemented AArch64 builtin call: ") +
2355 getContext().BuiltinInfo.getName(builtinID));
2356 return mlir::Value{};
2357 }
2358 case NEON::BI__builtin_neon_vget_lane_bf16:
2359 case NEON::BI__builtin_neon_vduph_lane_bf16:
2360 case NEON::BI__builtin_neon_vduph_lane_f16:
2361 case NEON::BI__builtin_neon_vgetq_lane_bf16:
2362 case NEON::BI__builtin_neon_vduph_laneq_bf16:
2363 case NEON::BI__builtin_neon_vduph_laneq_f16: {
2364 return cir::VecExtractOp::create(builder, loc, ops[0], ops[1]);
2365 }
2366 case NEON::BI__builtin_neon_vcvt_bf16_f32:
2367 case NEON::BI__builtin_neon_vcvtq_low_bf16_f32:
2368 case NEON::BI__builtin_neon_vcvtq_high_bf16_f32:
2369 case clang::AArch64::BI_InterlockedAdd:
2370 case clang::AArch64::BI_InterlockedAdd_acq:
2371 case clang::AArch64::BI_InterlockedAdd_rel:
2372 case clang::AArch64::BI_InterlockedAdd_nf:
2373 case clang::AArch64::BI_InterlockedAdd64:
2374 case clang::AArch64::BI_InterlockedAdd64_acq:
2375 case clang::AArch64::BI_InterlockedAdd64_rel:
2376 case clang::AArch64::BI_InterlockedAdd64_nf:
2377 cgm.errorNYI(expr->getSourceRange(),
2378 std::string("unimplemented AArch64 builtin call: ") +
2379 getContext().BuiltinInfo.getName(builtinID));
2380 return mlir::Value{};
2381 }
2382
2383 cir::VectorType ty = getNeonType(this, type, loc);
2384 if (!ty)
2385 return nullptr;
2386
2387 llvm::StringRef intrName;
2388
2389 switch (builtinID) {
2390 default:
2391 return std::nullopt;
2392 case NEON::BI__builtin_neon_vbsl_v:
2393 case NEON::BI__builtin_neon_vbslq_v: {
2394
2395 cir::VectorType bitTy = getIntVecFromVecTy(builder, ty);
2396 ops[0] = builder.createBitcast(ops[0], bitTy);
2397 ops[1] = builder.createBitcast(ops[1], bitTy);
2398 ops[2] = builder.createBitcast(ops[2], bitTy);
2399
2400 ops[1] = builder.createAnd(loc, ops[0], ops[1]);
2401 ops[2] = builder.createAnd(loc, builder.createNot(ops[0]), ops[2]);
2402 ops[0] = builder.createOr(loc, ops[1], ops[2]);
2403 return builder.createBitcast(ops[0], ty);
2404 }
2405 case NEON::BI__builtin_neon_vfma_lane_v:
2406 case NEON::BI__builtin_neon_vfmaq_lane_v:
2407 case NEON::BI__builtin_neon_vfma_laneq_v:
2408 case NEON::BI__builtin_neon_vfmaq_laneq_v:
2409 case NEON::BI__builtin_neon_vfmah_lane_f16:
2410 case NEON::BI__builtin_neon_vfmas_lane_f32:
2411 case NEON::BI__builtin_neon_vfmah_laneq_f16:
2412 case NEON::BI__builtin_neon_vfmas_laneq_f32:
2413 case NEON::BI__builtin_neon_vfmad_lane_f64:
2414 case NEON::BI__builtin_neon_vfmad_laneq_f64:
2415 cgm.errorNYI(expr->getSourceRange(),
2416 std::string("unimplemented AArch64 builtin call: ") +
2417 getContext().BuiltinInfo.getName(builtinID));
2418 return mlir::Value{};
2419 case NEON::BI__builtin_neon_vmull_v: {
2420 intrName = usgn ? "aarch64.neon.umull" : "aarch64.neon.smull";
2421 if (type.isPoly())
2422 intrName = "aarch64.neon.pmull";
2423 cir::VectorType argTy = builder.getExtendedOrTruncatedElementVectorType(
2424 ty, /*isExtended*/ false, !usgn);
2425 return emitNeonCall(cgm, builder, {argTy, argTy}, ops, intrName, ty, loc);
2426 }
2427 case NEON::BI__builtin_neon_vmax_v:
2428 case NEON::BI__builtin_neon_vmaxq_v:
2429 intrName = usgn ? "aarch64.neon.umax" : "aarch64.neon.smax";
2430 if (cir::isFPOrVectorOfFPType(ty))
2431 intrName = "aarch64.neon.fmax";
2432 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2433 case NEON::BI__builtin_neon_vmaxh_f16:
2434 cgm.errorNYI(expr->getSourceRange(),
2435 std::string("unimplemented AArch64 builtin call: ") +
2436 getContext().BuiltinInfo.getName(builtinID));
2437 return mlir::Value{};
2438 case NEON::BI__builtin_neon_vmin_v:
2439 case NEON::BI__builtin_neon_vminq_v:
2440 intrName = usgn ? "aarch64.neon.umin" : "aarch64.neon.smin";
2441 if (cir::isFPOrVectorOfFPType(ty))
2442 intrName = "aarch64.neon.fmin";
2443 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2444 case NEON::BI__builtin_neon_vminh_f16:
2445 cgm.errorNYI(expr->getSourceRange(),
2446 std::string("unimplemented AArch64 builtin call: ") +
2447 getContext().BuiltinInfo.getName(builtinID));
2448 return mlir::Value{};
2449 case NEON::BI__builtin_neon_vabd_v:
2450 case NEON::BI__builtin_neon_vabdq_v:
2451 intrName = usgn ? "aarch64.neon.uabd" : "aarch64.neon.sabd";
2452 if (cir::isFPOrVectorOfFPType(ty))
2453 intrName = "aarch64.neon.fabd";
2454 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2455 case NEON::BI__builtin_neon_vpadal_v:
2456 case NEON::BI__builtin_neon_vpadalq_v:
2457 cgm.errorNYI(expr->getSourceRange(),
2458 std::string("unimplemented AArch64 builtin call: ") +
2459 getContext().BuiltinInfo.getName(builtinID));
2460 return mlir::Value{};
2461 case NEON::BI__builtin_neon_vpmin_v:
2462 case NEON::BI__builtin_neon_vpminq_v:
2463 intrName = usgn ? "aarch64.neon.uminp" : "aarch64.neon.sminp";
2464 if (cir::isFPOrVectorOfFPType(ty))
2465 intrName = "aarch64.neon.fminp";
2466 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2467 case NEON::BI__builtin_neon_vpmax_v:
2468 case NEON::BI__builtin_neon_vpmaxq_v:
2469 cgm.errorNYI(expr->getSourceRange(),
2470 std::string("unimplemented AArch64 builtin call: ") +
2471 getContext().BuiltinInfo.getName(builtinID));
2472 return mlir::Value{};
2473 case NEON::BI__builtin_neon_vminnm_v:
2474 case NEON::BI__builtin_neon_vminnmq_v:
2475 intrName = "aarch64.neon.fminnm";
2476 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2477 case NEON::BI__builtin_neon_vminnmh_f16:
2478 cgm.errorNYI(expr->getSourceRange(),
2479 std::string("unimplemented AArch64 builtin call: ") +
2480 getContext().BuiltinInfo.getName(builtinID));
2481 return mlir::Value{};
2482 case NEON::BI__builtin_neon_vmaxnm_v:
2483 case NEON::BI__builtin_neon_vmaxnmq_v:
2484 intrName = "aarch64.neon.fmaxnm";
2485 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2486 case NEON::BI__builtin_neon_vmaxnmh_f16:
2487 case NEON::BI__builtin_neon_vrecpss_f32:
2488 case NEON::BI__builtin_neon_vrecpsd_f64:
2489 case NEON::BI__builtin_neon_vrecpsh_f16:
2490 case NEON::BI__builtin_neon_vqshrun_n_v:
2491 case NEON::BI__builtin_neon_vqrshrun_n_v:
2492 case NEON::BI__builtin_neon_vqshrn_n_v:
2493 case NEON::BI__builtin_neon_vrshrn_n_v:
2494 case NEON::BI__builtin_neon_vqrshrn_n_v:
2495 case NEON::BI__builtin_neon_vrndah_f16:
2496 case NEON::BI__builtin_neon_vrnda_v:
2497 case NEON::BI__builtin_neon_vrndaq_v:
2498 case NEON::BI__builtin_neon_vrndih_f16:
2499 case NEON::BI__builtin_neon_vrndmh_f16:
2500 case NEON::BI__builtin_neon_vrndm_v:
2501 case NEON::BI__builtin_neon_vrndmq_v:
2502 case NEON::BI__builtin_neon_vrndnh_f16:
2503 case NEON::BI__builtin_neon_vrndn_v:
2504 case NEON::BI__builtin_neon_vrndnq_v:
2505 case NEON::BI__builtin_neon_vrndns_f32:
2506 case NEON::BI__builtin_neon_vrndph_f16:
2507 case NEON::BI__builtin_neon_vrndp_v:
2508 case NEON::BI__builtin_neon_vrndpq_v:
2509 case NEON::BI__builtin_neon_vrndxh_f16:
2510 case NEON::BI__builtin_neon_vrndx_v:
2511 case NEON::BI__builtin_neon_vrndxq_v:
2512 case NEON::BI__builtin_neon_vrndh_f16:
2513 case NEON::BI__builtin_neon_vrnd32x_f32:
2514 case NEON::BI__builtin_neon_vrnd32xq_f32:
2515 case NEON::BI__builtin_neon_vrnd32x_f64:
2516 case NEON::BI__builtin_neon_vrnd32xq_f64:
2517 case NEON::BI__builtin_neon_vrnd32z_f32:
2518 case NEON::BI__builtin_neon_vrnd32zq_f32:
2519 case NEON::BI__builtin_neon_vrnd32z_f64:
2520 case NEON::BI__builtin_neon_vrnd32zq_f64:
2521 case NEON::BI__builtin_neon_vrnd64x_f32:
2522 case NEON::BI__builtin_neon_vrnd64xq_f32:
2523 case NEON::BI__builtin_neon_vrnd64x_f64:
2524 case NEON::BI__builtin_neon_vrnd64xq_f64:
2525 case NEON::BI__builtin_neon_vrnd64z_f32:
2526 case NEON::BI__builtin_neon_vrnd64zq_f32:
2527 case NEON::BI__builtin_neon_vrnd64z_f64:
2528 case NEON::BI__builtin_neon_vrnd64zq_f64:
2529 case NEON::BI__builtin_neon_vrnd_v:
2530 case NEON::BI__builtin_neon_vrndq_v:
2531 cgm.errorNYI(expr->getSourceRange(),
2532 std::string("unimplemented AArch64 builtin call: ") +
2533 getContext().BuiltinInfo.getName(builtinID));
2534 return mlir::Value{};
2535 case NEON::BI__builtin_neon_vcvt_f64_v:
2536 case NEON::BI__builtin_neon_vcvtq_f64_v:
2537 ops[0] = builder.createBitcast(ops[0], ty);
2538 ty = getNeonType(
2539 this, NeonTypeFlags(NeonTypeFlags::Float64, false, type.isQuad()), loc);
2540 return builder.createCast(loc, cir::CastKind::int_to_float, ops[0], ty);
2541 case NEON::BI__builtin_neon_vcvt_f64_f32:
2542 case NEON::BI__builtin_neon_vcvt_f32_f64:
2543 case NEON::BI__builtin_neon_vcvt_s32_v:
2544 case NEON::BI__builtin_neon_vcvt_u32_v:
2545 case NEON::BI__builtin_neon_vcvt_s64_v:
2546 case NEON::BI__builtin_neon_vcvt_u64_v:
2547 case NEON::BI__builtin_neon_vcvt_s16_f16:
2548 case NEON::BI__builtin_neon_vcvt_u16_f16:
2549 case NEON::BI__builtin_neon_vcvtq_s32_v:
2550 case NEON::BI__builtin_neon_vcvtq_u32_v:
2551 case NEON::BI__builtin_neon_vcvtq_s64_v:
2552 case NEON::BI__builtin_neon_vcvtq_u64_v:
2553 case NEON::BI__builtin_neon_vcvtq_s16_f16:
2554 case NEON::BI__builtin_neon_vcvtq_u16_f16:
2555 case NEON::BI__builtin_neon_vcvta_s16_f16:
2556 case NEON::BI__builtin_neon_vcvta_u16_f16:
2557 case NEON::BI__builtin_neon_vcvta_s32_v:
2558 case NEON::BI__builtin_neon_vcvtaq_s16_f16:
2559 case NEON::BI__builtin_neon_vcvtaq_s32_v:
2560 case NEON::BI__builtin_neon_vcvta_u32_v:
2561 case NEON::BI__builtin_neon_vcvtaq_u16_f16:
2562 case NEON::BI__builtin_neon_vcvtaq_u32_v:
2563 case NEON::BI__builtin_neon_vcvta_s64_v:
2564 case NEON::BI__builtin_neon_vcvtaq_s64_v:
2565 case NEON::BI__builtin_neon_vcvta_u64_v:
2566 case NEON::BI__builtin_neon_vcvtaq_u64_v:
2567 case NEON::BI__builtin_neon_vcvtm_s16_f16:
2568 case NEON::BI__builtin_neon_vcvtm_s32_v:
2569 case NEON::BI__builtin_neon_vcvtmq_s16_f16:
2570 case NEON::BI__builtin_neon_vcvtmq_s32_v:
2571 case NEON::BI__builtin_neon_vcvtm_u16_f16:
2572 case NEON::BI__builtin_neon_vcvtm_u32_v:
2573 case NEON::BI__builtin_neon_vcvtmq_u16_f16:
2574 case NEON::BI__builtin_neon_vcvtmq_u32_v:
2575 case NEON::BI__builtin_neon_vcvtm_s64_v:
2576 case NEON::BI__builtin_neon_vcvtmq_s64_v:
2577 case NEON::BI__builtin_neon_vcvtm_u64_v:
2578 case NEON::BI__builtin_neon_vcvtmq_u64_v:
2579 case NEON::BI__builtin_neon_vcvtn_s16_f16:
2580 case NEON::BI__builtin_neon_vcvtn_s32_v:
2581 case NEON::BI__builtin_neon_vcvtnq_s16_f16:
2582 case NEON::BI__builtin_neon_vcvtnq_s32_v:
2583 case NEON::BI__builtin_neon_vcvtn_u16_f16:
2584 case NEON::BI__builtin_neon_vcvtn_u32_v:
2585 case NEON::BI__builtin_neon_vcvtnq_u16_f16:
2586 case NEON::BI__builtin_neon_vcvtnq_u32_v:
2587 case NEON::BI__builtin_neon_vcvtn_s64_v:
2588 case NEON::BI__builtin_neon_vcvtnq_s64_v:
2589 case NEON::BI__builtin_neon_vcvtn_u64_v:
2590 case NEON::BI__builtin_neon_vcvtnq_u64_v:
2591 case NEON::BI__builtin_neon_vcvtp_s16_f16:
2592 case NEON::BI__builtin_neon_vcvtp_s32_v:
2593 case NEON::BI__builtin_neon_vcvtpq_s16_f16:
2594 case NEON::BI__builtin_neon_vcvtpq_s32_v:
2595 case NEON::BI__builtin_neon_vcvtp_u16_f16:
2596 case NEON::BI__builtin_neon_vcvtp_u32_v:
2597 case NEON::BI__builtin_neon_vcvtpq_u16_f16:
2598 case NEON::BI__builtin_neon_vcvtpq_u32_v:
2599 case NEON::BI__builtin_neon_vcvtp_s64_v:
2600 case NEON::BI__builtin_neon_vcvtpq_s64_v:
2601 case NEON::BI__builtin_neon_vcvtp_u64_v:
2602 case NEON::BI__builtin_neon_vcvtpq_u64_v:
2603 case NEON::BI__builtin_neon_vmulx_v:
2604 case NEON::BI__builtin_neon_vmulxq_v:
2605 case NEON::BI__builtin_neon_vmulxh_lane_f16:
2606 case NEON::BI__builtin_neon_vmulxh_laneq_f16:
2607 case NEON::BI__builtin_neon_vmul_lane_v:
2608 case NEON::BI__builtin_neon_vmul_laneq_v:
2609 case NEON::BI__builtin_neon_vpmaxnm_v:
2610 case NEON::BI__builtin_neon_vpmaxnmq_v:
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_vpminnm_v:
2616 case NEON::BI__builtin_neon_vpminnmq_v:
2617 intrName = "aarch64.neon.fminnmp";
2618 return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc);
2619 case NEON::BI__builtin_neon_vsqrth_f16:
2620 case NEON::BI__builtin_neon_vsqrt_v:
2621 case NEON::BI__builtin_neon_vsqrtq_v:
2622 case NEON::BI__builtin_neon_vrbit_v:
2623 case NEON::BI__builtin_neon_vrbitq_v:
2624 case NEON::BI__builtin_neon_vmaxv_f16:
2625 case NEON::BI__builtin_neon_vmaxvq_f16:
2626 case NEON::BI__builtin_neon_vminv_f16:
2627 case NEON::BI__builtin_neon_vminvq_f16:
2628 case NEON::BI__builtin_neon_vmaxnmv_f16:
2629 case NEON::BI__builtin_neon_vmaxnmvq_f16:
2630 case NEON::BI__builtin_neon_vminnmv_f16:
2631 case NEON::BI__builtin_neon_vminnmvq_f16:
2632 case NEON::BI__builtin_neon_vmul_n_f64:
2633 case NEON::BI__builtin_neon_vaddlv_u8:
2634 case NEON::BI__builtin_neon_vaddlv_u16:
2635 case NEON::BI__builtin_neon_vaddlvq_u8:
2636 case NEON::BI__builtin_neon_vaddlvq_u16:
2637 case NEON::BI__builtin_neon_vaddlv_s8:
2638 case NEON::BI__builtin_neon_vaddlv_s16:
2639 case NEON::BI__builtin_neon_vaddlvq_s8:
2640 case NEON::BI__builtin_neon_vaddlvq_s16:
2641 case NEON::BI__builtin_neon_vsri_n_v:
2642 case NEON::BI__builtin_neon_vsriq_n_v:
2643 case NEON::BI__builtin_neon_vsli_n_v:
2644 case NEON::BI__builtin_neon_vsliq_n_v:
2645 case NEON::BI__builtin_neon_vsra_n_v:
2646 case NEON::BI__builtin_neon_vsraq_n_v:
2647 cgm.errorNYI(expr->getSourceRange(),
2648 std::string("unimplemented AArch64 builtin call: ") +
2649 getContext().BuiltinInfo.getName(builtinID));
2650 return mlir::Value{};
2651 case NEON::BI__builtin_neon_vrsra_n_v:
2652 case NEON::BI__builtin_neon_vrsraq_n_v: {
2653 intrName = usgn ? "aarch64.neon.urshl" : "aarch64.neon.srshl";
2654 cir::VectorType shiftAmtVecTy =
2655 usgn ? getSignChangedVectorType(builder, ty) : ty;
2656 llvm::SmallVector<mlir::Value, 2> tmpOps = {ops[1], ops[2]};
2657 mlir::Value tmp = emitNeonCall(cgm, builder, {ty, shiftAmtVecTy}, tmpOps,
2658 intrName, ty, loc,
2659 /*isConstrainedFPIntrinsic=*/false,
2660 /*shift=*/1, /*rightshift=*/true);
2661 ops[0] = builder.createBitcast(ops[0], ty);
2662 return builder.createAdd(loc, ops[0], tmp);
2663 }
2664 case NEON::BI__builtin_neon_vld1_v:
2665 case NEON::BI__builtin_neon_vld1q_v:
2666 case NEON::BI__builtin_neon_vst1_v:
2667 case NEON::BI__builtin_neon_vst1q_v:
2668 case NEON::BI__builtin_neon_vld1_lane_v:
2669 case NEON::BI__builtin_neon_vld1q_lane_v:
2670 case NEON::BI__builtin_neon_vldap1_lane_s64:
2671 case NEON::BI__builtin_neon_vldap1q_lane_s64:
2672 case NEON::BI__builtin_neon_vld1_dup_v:
2673 case NEON::BI__builtin_neon_vld1q_dup_v:
2674 case NEON::BI__builtin_neon_vst1_lane_v:
2675 case NEON::BI__builtin_neon_vst1q_lane_v:
2676 case NEON::BI__builtin_neon_vstl1_lane_s64:
2677 case NEON::BI__builtin_neon_vstl1q_lane_s64:
2678 case NEON::BI__builtin_neon_vld2_v:
2679 case NEON::BI__builtin_neon_vld2q_v:
2680 case NEON::BI__builtin_neon_vld3_v:
2681 case NEON::BI__builtin_neon_vld3q_v:
2682 case NEON::BI__builtin_neon_vld4_v:
2683 case NEON::BI__builtin_neon_vld4q_v:
2684 case NEON::BI__builtin_neon_vld2_dup_v:
2685 case NEON::BI__builtin_neon_vld2q_dup_v:
2686 case NEON::BI__builtin_neon_vld3_dup_v:
2687 case NEON::BI__builtin_neon_vld3q_dup_v:
2688 case NEON::BI__builtin_neon_vld4_dup_v:
2689 case NEON::BI__builtin_neon_vld4q_dup_v:
2690 case NEON::BI__builtin_neon_vld2_lane_v:
2691 case NEON::BI__builtin_neon_vld2q_lane_v:
2692 case NEON::BI__builtin_neon_vld3_lane_v:
2693 case NEON::BI__builtin_neon_vld3q_lane_v:
2694 case NEON::BI__builtin_neon_vld4_lane_v:
2695 case NEON::BI__builtin_neon_vld4q_lane_v:
2696 case NEON::BI__builtin_neon_vst2_v:
2697 case NEON::BI__builtin_neon_vst2q_v:
2698 case NEON::BI__builtin_neon_vst2_lane_v:
2699 case NEON::BI__builtin_neon_vst2q_lane_v:
2700 case NEON::BI__builtin_neon_vst3_v:
2701 case NEON::BI__builtin_neon_vst3q_v:
2702 case NEON::BI__builtin_neon_vst3_lane_v:
2703 case NEON::BI__builtin_neon_vst3q_lane_v:
2704 case NEON::BI__builtin_neon_vst4_v:
2705 case NEON::BI__builtin_neon_vst4q_v:
2706 case NEON::BI__builtin_neon_vst4_lane_v:
2707 case NEON::BI__builtin_neon_vst4q_lane_v:
2708 case NEON::BI__builtin_neon_vtrn_v:
2709 case NEON::BI__builtin_neon_vtrnq_v:
2710 case NEON::BI__builtin_neon_vuzp_v:
2711 case NEON::BI__builtin_neon_vuzpq_v:
2712 case NEON::BI__builtin_neon_vzip_v:
2713 case NEON::BI__builtin_neon_vzipq_v:
2714 case NEON::BI__builtin_neon_vqtbl1q_v:
2715 case NEON::BI__builtin_neon_vqtbl2q_v:
2716 case NEON::BI__builtin_neon_vqtbl3q_v:
2717 case NEON::BI__builtin_neon_vqtbl4q_v:
2718 case NEON::BI__builtin_neon_vqtbx1q_v:
2719 case NEON::BI__builtin_neon_vqtbx2q_v:
2720 case NEON::BI__builtin_neon_vqtbx3q_v:
2721 case NEON::BI__builtin_neon_vqtbx4q_v:
2722 case NEON::BI__builtin_neon_vsqadd_v:
2723 case NEON::BI__builtin_neon_vsqaddq_v:
2724 case NEON::BI__builtin_neon_vuqadd_v:
2725 case NEON::BI__builtin_neon_vuqaddq_v:
2726 case NEON::BI__builtin_neon_vluti2_laneq_mf8:
2727 case NEON::BI__builtin_neon_vluti2_laneq_bf16:
2728 case NEON::BI__builtin_neon_vluti2_laneq_f16:
2729 case NEON::BI__builtin_neon_vluti2_laneq_p16:
2730 case NEON::BI__builtin_neon_vluti2_laneq_p8:
2731 case NEON::BI__builtin_neon_vluti2_laneq_s16:
2732 case NEON::BI__builtin_neon_vluti2_laneq_s8:
2733 case NEON::BI__builtin_neon_vluti2_laneq_u16:
2734 case NEON::BI__builtin_neon_vluti2_laneq_u8:
2735 case NEON::BI__builtin_neon_vluti2q_laneq_mf8:
2736 case NEON::BI__builtin_neon_vluti2q_laneq_bf16:
2737 case NEON::BI__builtin_neon_vluti2q_laneq_f16:
2738 case NEON::BI__builtin_neon_vluti2q_laneq_p16:
2739 case NEON::BI__builtin_neon_vluti2q_laneq_p8:
2740 case NEON::BI__builtin_neon_vluti2q_laneq_s16:
2741 case NEON::BI__builtin_neon_vluti2q_laneq_s8:
2742 case NEON::BI__builtin_neon_vluti2q_laneq_u16:
2743 case NEON::BI__builtin_neon_vluti2q_laneq_u8:
2744 case NEON::BI__builtin_neon_vluti2_lane_mf8:
2745 case NEON::BI__builtin_neon_vluti2_lane_bf16:
2746 case NEON::BI__builtin_neon_vluti2_lane_f16:
2747 case NEON::BI__builtin_neon_vluti2_lane_p16:
2748 case NEON::BI__builtin_neon_vluti2_lane_p8:
2749 case NEON::BI__builtin_neon_vluti2_lane_s16:
2750 case NEON::BI__builtin_neon_vluti2_lane_s8:
2751 case NEON::BI__builtin_neon_vluti2_lane_u16:
2752 case NEON::BI__builtin_neon_vluti2_lane_u8:
2753 case NEON::BI__builtin_neon_vluti2q_lane_mf8:
2754 case NEON::BI__builtin_neon_vluti2q_lane_bf16:
2755 case NEON::BI__builtin_neon_vluti2q_lane_f16:
2756 case NEON::BI__builtin_neon_vluti2q_lane_p16:
2757 case NEON::BI__builtin_neon_vluti2q_lane_p8:
2758 case NEON::BI__builtin_neon_vluti2q_lane_s16:
2759 case NEON::BI__builtin_neon_vluti2q_lane_s8:
2760 case NEON::BI__builtin_neon_vluti2q_lane_u16:
2761 case NEON::BI__builtin_neon_vluti2q_lane_u8:
2762 case NEON::BI__builtin_neon_vluti4q_lane_mf8:
2763 case NEON::BI__builtin_neon_vluti4q_lane_p8:
2764 case NEON::BI__builtin_neon_vluti4q_lane_s8:
2765 case NEON::BI__builtin_neon_vluti4q_lane_u8:
2766 case NEON::BI__builtin_neon_vluti4q_laneq_mf8:
2767 case NEON::BI__builtin_neon_vluti4q_laneq_p8:
2768 case NEON::BI__builtin_neon_vluti4q_laneq_s8:
2769 case NEON::BI__builtin_neon_vluti4q_laneq_u8:
2770 case NEON::BI__builtin_neon_vluti4q_lane_bf16_x2:
2771 case NEON::BI__builtin_neon_vluti4q_lane_f16_x2:
2772 case NEON::BI__builtin_neon_vluti4q_lane_p16_x2:
2773 case NEON::BI__builtin_neon_vluti4q_lane_s16_x2:
2774 case NEON::BI__builtin_neon_vluti4q_lane_u16_x2:
2775 case NEON::BI__builtin_neon_vluti4q_laneq_bf16_x2:
2776 case NEON::BI__builtin_neon_vluti4q_laneq_f16_x2:
2777 case NEON::BI__builtin_neon_vluti4q_laneq_p16_x2:
2778 case NEON::BI__builtin_neon_vluti4q_laneq_s16_x2:
2779 case NEON::BI__builtin_neon_vluti4q_laneq_u16_x2:
2780 case NEON::BI__builtin_neon_vmmlaq_f16_mf8_fpm:
2781 case NEON::BI__builtin_neon_vmmlaq_f32_mf8_fpm:
2782 case NEON::BI__builtin_neon_vcvt1_low_bf16_mf8_fpm:
2783 case NEON::BI__builtin_neon_vcvt1_bf16_mf8_fpm:
2784 case NEON::BI__builtin_neon_vcvt1_high_bf16_mf8_fpm:
2785 case NEON::BI__builtin_neon_vcvt2_low_bf16_mf8_fpm:
2786 case NEON::BI__builtin_neon_vcvt2_bf16_mf8_fpm:
2787 case NEON::BI__builtin_neon_vcvt2_high_bf16_mf8_fpm:
2788 case NEON::BI__builtin_neon_vcvt1_low_f16_mf8_fpm:
2789 case NEON::BI__builtin_neon_vcvt1_f16_mf8_fpm:
2790 case NEON::BI__builtin_neon_vcvt1_high_f16_mf8_fpm:
2791 case NEON::BI__builtin_neon_vcvt2_low_f16_mf8_fpm:
2792 case NEON::BI__builtin_neon_vcvt2_f16_mf8_fpm:
2793 case NEON::BI__builtin_neon_vcvt2_high_f16_mf8_fpm:
2794 case NEON::BI__builtin_neon_vcvt_mf8_f32_fpm:
2795 case NEON::BI__builtin_neon_vcvt_mf8_f16_fpm:
2796 case NEON::BI__builtin_neon_vcvtq_mf8_f16_fpm:
2797 case NEON::BI__builtin_neon_vcvt_high_mf8_f32_fpm:
2798 case NEON::BI__builtin_neon_vdot_f16_mf8_fpm:
2799 case NEON::BI__builtin_neon_vdotq_f16_mf8_fpm:
2800 case NEON::BI__builtin_neon_vdot_lane_f16_mf8_fpm:
2801 case NEON::BI__builtin_neon_vdotq_lane_f16_mf8_fpm:
2802 case NEON::BI__builtin_neon_vdot_laneq_f16_mf8_fpm:
2803 case NEON::BI__builtin_neon_vdotq_laneq_f16_mf8_fpm:
2804 case NEON::BI__builtin_neon_vdot_f32_mf8_fpm:
2805 case NEON::BI__builtin_neon_vdotq_f32_mf8_fpm:
2806 case NEON::BI__builtin_neon_vdot_lane_f32_mf8_fpm:
2807 case NEON::BI__builtin_neon_vdotq_lane_f32_mf8_fpm:
2808 case NEON::BI__builtin_neon_vdot_laneq_f32_mf8_fpm:
2809 case NEON::BI__builtin_neon_vdotq_laneq_f32_mf8_fpm:
2810 case NEON::BI__builtin_neon_vmlalbq_f16_mf8_fpm:
2811 case NEON::BI__builtin_neon_vmlaltq_f16_mf8_fpm:
2812 case NEON::BI__builtin_neon_vmlallbbq_f32_mf8_fpm:
2813 case NEON::BI__builtin_neon_vmlallbtq_f32_mf8_fpm:
2814 case NEON::BI__builtin_neon_vmlalltbq_f32_mf8_fpm:
2815 case NEON::BI__builtin_neon_vmlallttq_f32_mf8_fpm:
2816 case NEON::BI__builtin_neon_vmlalbq_lane_f16_mf8_fpm:
2817 case NEON::BI__builtin_neon_vmlalbq_laneq_f16_mf8_fpm:
2818 case NEON::BI__builtin_neon_vmlaltq_lane_f16_mf8_fpm:
2819 case NEON::BI__builtin_neon_vmlaltq_laneq_f16_mf8_fpm:
2820 case NEON::BI__builtin_neon_vmlallbbq_lane_f32_mf8_fpm:
2821 case NEON::BI__builtin_neon_vmlallbbq_laneq_f32_mf8_fpm:
2822 case NEON::BI__builtin_neon_vmlallbtq_lane_f32_mf8_fpm:
2823 case NEON::BI__builtin_neon_vmlallbtq_laneq_f32_mf8_fpm:
2824 case NEON::BI__builtin_neon_vmlalltbq_lane_f32_mf8_fpm:
2825 case NEON::BI__builtin_neon_vmlalltbq_laneq_f32_mf8_fpm:
2826 case NEON::BI__builtin_neon_vmlallttq_lane_f32_mf8_fpm:
2827 case NEON::BI__builtin_neon_vmlallttq_laneq_f32_mf8_fpm:
2828 case NEON::BI__builtin_neon_vamin_f16:
2829 case NEON::BI__builtin_neon_vaminq_f16:
2830 case NEON::BI__builtin_neon_vamin_f32:
2831 case NEON::BI__builtin_neon_vaminq_f32:
2832 case NEON::BI__builtin_neon_vaminq_f64:
2833 case NEON::BI__builtin_neon_vamax_f16:
2834 case NEON::BI__builtin_neon_vamaxq_f16:
2835 case NEON::BI__builtin_neon_vamax_f32:
2836 case NEON::BI__builtin_neon_vamaxq_f32:
2837 case NEON::BI__builtin_neon_vamaxq_f64:
2838 case NEON::BI__builtin_neon_vscale_f16:
2839 case NEON::BI__builtin_neon_vscaleq_f16:
2840 case NEON::BI__builtin_neon_vscale_f32:
2841 case NEON::BI__builtin_neon_vscaleq_f32:
2842 case NEON::BI__builtin_neon_vscaleq_f64:
2843 cgm.errorNYI(expr->getSourceRange(),
2844 std::string("unimplemented AArch64 builtin call: ") +
2845 getContext().BuiltinInfo.getName(builtinID));
2846 return mlir::Value{};
2847 }
2848
2849 // Unreachable: All cases in the switch above return.
2850}
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 mlir::Value emitCommonNeonSISDBuiltinExpr(CIRGenFunction &cgf, const ARMVectorIntrinsicInfo &info, llvm::SmallVectorImpl< mlir::Value > &ops, const CallExpr *expr)
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 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 const ARMVectorIntrinsicInfo aarch64SVEIntrinsicMap[]
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 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 const ARMVectorIntrinsicInfo * findARMVectorIntrinsicInMap(ArrayRef< ARMVectorIntrinsicInfo > intrinsicMap, unsigned builtinID, bool &mapProvenSorted)
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 mlir::Value emitAArch64CompareBuiltinExpr(CIRGenFunction &cgf, CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value src, mlir::Type retTy, const cir::CmpOpKind kind)
static mlir::Value emitNeonRShiftImm(CIRGenFunction &cgf, mlir::Value shiftVec, mlir::Value shiftVal, cir::VectorType vecTy, bool usgn, mlir::Location loc)
static cir::VectorType getNeonType(CIRGenFunction *cgf, NeonTypeFlags typeFlags, mlir::Location loc, bool hasLegalHalfType=true, bool v1Ty=false, bool allowBFloatArgsAndRet=true)
static bool aarch64SISDIntrinsicsProvenSorted
TokenType getType() const
Returns the token's type, e.g.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Enumerates target-specific builtins in their own namespaces within namespace clang.
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createNUWAMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
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:226
Builtin::Context & BuiltinInfo
Definition ASTContext.h:800
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs=nullptr) const
Return the type for the specified builtin.
@ GE_None
No error.
std::string getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
Definition Builtins.cpp:80
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc)
mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str, const mlir::Type &resTy, Operands &&...op)
cir::IntType getSIntNTy(int n)
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef< mlir::Attribute > maskAttrs)
cir::ConstantOp getZero(mlir::Location loc, mlir::Type ty)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::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.
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:2946
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 ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[]
const ARMVectorIntrinsicInfo 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
static bool msvcBuiltins()
static bool handleBuiltinICEArguments()
static bool aarch64SIMDIntrinsics()
static bool aarch64SVEIntrinsics()
static bool emitConstrainedFPCall()
static bool aarch64SMEIntrinsics()
static bool aarch64TblBuiltinExpr()