[clang] [CIR][AArch64] Lower vfma lane builtins (PR #188190)
Andrzej WarzyĆski via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 07:26:38 PDT 2026
================
@@ -912,6 +599,157 @@ static cir::VectorType getSVEVectorForElementType(CIRGenModule &cgm,
return cir::VectorType::get(eltTy, numElts, /*is_scalable=*/true);
}
+//===----------------------------------------------------------------------===//
+// NEON helpers
+//===----------------------------------------------------------------------===//
+/// Return true if BuiltinID is an overloaded Neon intrinsic with an extra
+/// argument that specifies the vector type. The additional argument is meant
+/// for Sema checking (see `CheckNeonBuiltinFunctionCall`) and this function
+/// should be kept consistent with the logic in Sema.
+/// TODO: Make this return false for SISD builtins.
+/// TODO(cir): Share this with ARM.cpp
+static bool hasExtraNeonArgument(unsigned builtinID) {
+ // Required by the headers included below, but not in this particular
+ // function.
+ [[maybe_unused]] int PtrArgNum = -1;
+ [[maybe_unused]] bool HasConstPtr = false;
+
+ // The mask encodes the type. We don't care about the actual value. Instead,
+ // we just check whether its been set.
+ uint64_t mask = 0;
+ switch (builtinID) {
+#define GET_NEON_OVERLOAD_CHECK
+#include "clang/Basic/arm_fp16.inc"
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_OVERLOAD_CHECK
+ // Non-neon builtins for controling VFP that take extra argument for
+ // discriminating the type.
+ case ARM::BI__builtin_arm_vcvtr_f:
+ case ARM::BI__builtin_arm_vcvtr_d:
+ mask = 1;
+ }
+ switch (builtinID) {
+ default:
+ break;
+ }
+
+ return mask != 0;
+}
+
+// TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.
+template <typename Operation>
+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) {
+ // TODO(cir): Consider removing the following unreachable when we have
+ // emitConstrainedFPCall feature implemented
+ assert(!cir::MissingFeatures::emitConstrainedFPCall());
+ if (isConstrainedFPIntrinsic)
+ cgm.errorNYI(loc, std::string("constrained FP intrinsic"));
+
+ for (unsigned j = 0; j < argTypes.size(); ++j) {
+ if (isConstrainedFPIntrinsic) {
+ assert(!cir::MissingFeatures::emitConstrainedFPCall());
+ }
+ if (shift > 0 && shift == j) {
+ cgm.errorNYI(loc, std::string("intrinsic requiring a shift Op"));
+ } else {
+ args[j] = builder.createBitcast(args[j], argTypes[j]);
+ }
+ }
+ if (isConstrainedFPIntrinsic) {
+ assert(!cir::MissingFeatures::emitConstrainedFPCall());
+ return nullptr;
+ }
+ if constexpr (std::is_same_v<Operation, cir::LLVMIntrinsicCallOp>) {
+ return Operation::create(builder, loc,
+ builder.getStringAttr(intrinsicName.value()),
+ funcResTy, args)
+ .getResult();
+ } else {
+ return Operation::create(builder, loc, funcResTy, args).getResult();
+ }
+}
+
+// TODO(cir): Remove `cgm` from the list of arguments once all NYI(s) are gone.
+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) {
+ return emitNeonCallToOp<cir::LLVMIntrinsicCallOp>(
+ cgm, builder, std::move(argTypes), args, intrinsicName, funcResTy, loc,
+ isConstrainedFPIntrinsic, shift, rightshift);
+}
+
+static mlir::Value emitCommonNeonSISDBuiltinExpr(
+ CIRGenFunction &cgf, const ARMVectorIntrinsicInfo &info,
+ llvm::SmallVectorImpl<mlir::Value> &ops, const CallExpr *expr) {
+ assert(info.LLVMIntrinsic && "Generic code assumes a valid intrinsic");
+
+ switch (info.BuiltinID) {
+ case NEON::BI__builtin_neon_vcled_s64:
+ case NEON::BI__builtin_neon_vcled_u64:
+ case NEON::BI__builtin_neon_vcles_f32:
+ case NEON::BI__builtin_neon_vcled_f64:
+ case NEON::BI__builtin_neon_vcltd_s64:
+ case NEON::BI__builtin_neon_vcltd_u64:
+ case NEON::BI__builtin_neon_vclts_f32:
+ case NEON::BI__builtin_neon_vcltd_f64:
+ case NEON::BI__builtin_neon_vcales_f32:
+ case NEON::BI__builtin_neon_vcaled_f64:
+ case NEON::BI__builtin_neon_vcalts_f32:
+ case NEON::BI__builtin_neon_vcaltd_f64:
+ cgf.cgm.errorNYI(expr->getSourceRange(),
+ std::string("unimplemented AArch64 builtin call: ") +
+ cgf.getContext().BuiltinInfo.getName(info.BuiltinID));
+ break;
+ }
+
+ llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
+ static_cast<llvm::Intrinsic::ID>(info.LLVMIntrinsic));
+ mlir::Location loc = cgf.getLoc(expr->getExprLoc());
+
+ // The switch stmt is intended to help catch NYI cases and will be removed
+ // once the CIR implementation is complete. Avoid adding specialized
+ // code in cases - that should only be required for a handful of examples.
+ switch (info.BuiltinID) {
+ default:
+ cgf.cgm.errorNYI(expr->getSourceRange(),
+ std::string("unimplemented AArch64 builtin call: ") +
+ cgf.getContext().BuiltinInfo.getName(info.BuiltinID));
+ break;
+ case NEON::BI__builtin_neon_vabdd_f64:
+ case NEON::BI__builtin_neon_vabds_f32:
+ case NEON::BI__builtin_neon_vshld_s64:
+ case NEON::BI__builtin_neon_vshld_u64:
+ return emitNeonCall(cgf.cgm, cgf.getBuilder(),
+ {cgf.convertType(expr->getArg(0)->getType())}, ops,
+ llvmIntrName, cgf.convertType(expr->getType()), loc);
+ case NEON::BI__builtin_neon_vfma_v:
+ case NEON::BI__builtin_neon_vfmaq_v: {
+ auto ty = mlir::cast<cir::VectorType>(cgf.convertType(expr->getType()));
+ for (auto &op : ops)
+ if (op.getType() != ty)
+ op = cgf.getBuilder().createBitcast(loc, op, ty);
----------------
banach-space wrote:
Please avoid the control flow (`for` and `if) )and just cast unconditionally.
I will also note that the bitcasts aren't really required, but I suspect that without them there will be match failures when compared with the original code-gen.
https://github.com/llvm/llvm-project/pull/188190
More information about the cfe-commits
mailing list