Author: Andrzej Warzyński Date: 2026-02-09T18:48:42Z New Revision: 80677dc5e00c16e55dc29fce93867a77467b25ea
URL: https://github.com/llvm/llvm-project/commit/80677dc5e00c16e55dc29fce93867a77467b25ea DIFF: https://github.com/llvm/llvm-project/commit/80677dc5e00c16e55dc29fce93867a77467b25ea.diff LOG: [CIR][NEON] Add lowering support for `vceqzd_s64` (#179779) Rather than creating a dedicated ClangIR test file, the original test file for this intrinsic is effectively reused: * clang/test/CodeGen/AArch64/neon-intrinsics.c “Effectively” meaning that the corresponding test is moved (rather than literally reused) to a new file within the original AArch64 builtins test directory: * clang/test/CodeGen/AArch64/neon/intrinsics.c This is necessary to avoid lowering unsupported examples from intrinsics.c with `-fclangir`. The new file will eventually replace the original one once all builtins from it can be lowered via ClangIR. To facilitate test re-use, new LIT "feature" is added so that CIR tests can be run conditionally, e.g. the following will only run when `CLANG_ENABLE_CIR` is set: ```C // RUN: %if cir %{%clang_cc1 ... %} ``` This sort of substitutions are documented in [2]. REFERENCES: [1] https://developer.arm.com/architectures/instruction-sets/intrinsics/#f:@navigationhierarchiessimdisa=[Neon]&q=vceqzd_s64 [2] https://llvm.org/docs/TestingGuide.html#substitutions Added: clang/test/CodeGen/AArch64/neon/intrinsics.c Modified: clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp clang/lib/CIR/CodeGen/CIRGenFunction.h clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp clang/lib/CodeGen/TargetBuiltins/ARM.cpp clang/test/CodeGen/AArch64/neon-intrinsics.c clang/test/lit.cfg.py Removed: ################################################################################ diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index f51673cd92f5e..ae0aa8b7f733f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -1,5 +1,4 @@ //===---- CIRGenBuiltinAArch64.cpp - Emit CIR for AArch64 builtins --------===// -// // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -88,6 +87,42 @@ findARMVectorIntrinsicInMap(ArrayRef<AArch64BuiltinInfo> intrinsicMap, return nullptr; } +//===----------------------------------------------------------------------===// +// Emit-helpers +//===----------------------------------------------------------------------===// +static mlir::Value +emitAArch64CompareBuiltinExpr(CIRGenFunction &cgf, CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value src, + mlir::Type retTy, const cir::CmpOpKind kind) { + + bool scalarCmp = !isa<cir::VectorType>(src.getType()); + if (!scalarCmp) { + assert(cast<cir::VectorType>(retTy).getIsScalable() && + "This is only intended for fixed-width vectors"); + // Vector retTypes are cast to i8 vectors. Recover original retType. + cgf.cgm.errorNYI(loc, std::string("unimplemented vector compare")); + } + + mlir::Value zero = builder.getNullValue(src.getType(), loc); + mlir::Value cmp; + if (cir::isFPOrVectorOfFPType(src.getType())) { + cgf.cgm.errorNYI(loc, std::string("unimplemented FP compare")); + } else { + if (scalarCmp) + // For scalars, cast !cir.bool to !cir.int<s, 1> so that the compare + // result is sign- rather zero-extended when casting to the output + // retType. + cmp = builder.createCast( + loc, cir::CastKind::bool_to_int, + builder.createCompare(loc, cir::CmpOpKind::eq, src, zero), + builder.getSIntNTy(1)); + else + cgf.cgm.errorNYI(loc, std::string("unimplemented vector compare")); + } + + return builder.createCast(loc, cir::CastKind::integral, cmp, retTy); +} + bool CIRGenFunction::getAArch64SVEProcessedOperands( unsigned builtinID, const CallExpr *expr, SmallVectorImpl<mlir::Value> &ops, SVETypeFlags typeFlags) { @@ -1357,7 +1392,15 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vpaddd_s64: case NEON::BI__builtin_neon_vpaddd_f64: case NEON::BI__builtin_neon_vpadds_f32: + cgm.errorNYI(expr->getSourceRange(), + std::string("unimplemented AArch64 builtin call: ") + + getContext().BuiltinInfo.getName(builtinID)); + return mlir::Value{}; case NEON::BI__builtin_neon_vceqzd_s64: + ops.push_back(emitScalarExpr(expr->getArg(0))); + return emitAArch64CompareBuiltinExpr( + *this, builder, loc, ops[0], + convertType(expr->getCallReturnType(getContext())), cir::CmpOpKind::eq); case NEON::BI__builtin_neon_vceqzd_f64: case NEON::BI__builtin_neon_vceqzs_f32: case NEON::BI__builtin_neon_vceqzh_f16: diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index d25c6c941360f..3b07273f513e6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -36,6 +36,7 @@ #include "clang/CIR/MissingFeatures.h" #include "clang/CIR/TypeEvaluationKind.h" #include "llvm/ADT/ScopedHashTable.h" +#include "llvm/IR/Instructions.h" namespace { class ScalarExprEmitter; diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 6ac32cade4576..d411f7fa925ea 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1293,6 +1293,7 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( auto llvmSrcTy = mlir::cast<mlir::IntegerType>(llvmSrcVal.getType()); auto llvmDstTy = mlir::cast<mlir::IntegerType>(getTypeConverter()->convertType(dstTy)); + if (llvmSrcTy.getWidth() == llvmDstTy.getWidth()) rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(castOp, llvmDstTy, llvmSrcVal); diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index 2d7128bf95df2..c45e819a03855 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -1721,6 +1721,9 @@ Function *CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID, return CGM.getIntrinsic(IntrinsicID, Tys); } +//===----------------------------------------------------------------------===// +// Emit-helpers +//===----------------------------------------------------------------------===// static Value *EmitCommonNeonSISDBuiltinExpr( CodeGenFunction &CGF, const ARMVectorIntrinsicInfo &SISDInfo, SmallVectorImpl<Value *> &Ops, const CallExpr *E) { @@ -2494,13 +2497,15 @@ CodeGenFunction::EmitAArch64CompareBuiltinExpr(Value *Op, llvm::Type *Ty, Op = Builder.CreateBitCast(Op, Ty); } + Constant *zero = Constant::getNullValue(Op->getType()); + if (CmpInst::isFPPredicate(Pred)) { if (Pred == CmpInst::FCMP_OEQ) - Op = Builder.CreateFCmp(Pred, Op, Constant::getNullValue(Op->getType())); + Op = Builder.CreateFCmp(Pred, Op, zero); else - Op = Builder.CreateFCmpS(Pred, Op, Constant::getNullValue(Op->getType())); + Op = Builder.CreateFCmpS(Pred, Op, zero); } else { - Op = Builder.CreateICmp(Pred, Op, Constant::getNullValue(Op->getType())); + Op = Builder.CreateICmp(Pred, Op, zero); } llvm::Type *ResTy = Ty; diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c index 1c628bbba483f..3fc299b926009 100644 --- a/clang/test/CodeGen/AArch64/neon-intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c @@ -17242,17 +17242,6 @@ uint64_t test_vceqd_u64(uint64_t a, uint64_t b) { return (int64_t)vceqd_u64(a, b); } -// CHECK-LABEL: define dso_local i64 @test_vceqzd_s64( -// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[A]], 0 -// CHECK-NEXT: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i64 -// CHECK-NEXT: ret i64 [[VCEQZ_I]] -// -uint64_t test_vceqzd_s64(int64_t a) { - return (uint64_t)vceqzd_s64(a); -} - // CHECK-LABEL: define dso_local i64 @test_vceqzd_u64( // CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c new file mode 100644 index 0000000000000..6d0b25e6a66b7 --- /dev/null +++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c @@ -0,0 +1,33 @@ +// REQUIRES: aarch64-registered-target || arm-registered-target + +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM +// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM %} +// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-cir -o - %s | FileCheck %s --check-prefixes=CIR %} + +//============================================================================= +// NOTES +// +// Minor diff erences between RUNs (e.g. presence of `noundef` attached to +// argumens, `align` attribute attached to pointers), are matched using +// catch-alls like {{.*}}. +// +// Different labels for CIR stem from an additional function call that is +// present at the AST and CIR levels, but is inlined at the LLVM IR level. +//============================================================================= + +#include <arm_neon.h> + +// LLVM-LABEL: @test_vceqzd_s64 +// CIR-LABEL: @vceqzd_s64 +uint64_t test_vceqzd_s64(int64_t a) { +// CIR: [[C_0:%.*]] = cir.const #cir.int<0> +// CIR: [[CMP:%.*]] = cir.cmp(eq, %{{.*}}, [[C_0]]) : !s64i, !cir.bool +// CIR: [[RES:%.*]] = cir.cast bool_to_int [[CMP]] : !cir.bool -> !cir.int<s, 1> +// CIR: cir.cast integral [[RES]] : !cir.int<s, 1> -> !u64i + +// LLVM-SAME: i64{{.*}} [[A:%.*]]) +// LLVM: [[TMP0:%.*]] = icmp eq i64 [[A]], 0 +// LLVM-NEXT: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i64 +// LLVM-NEXT: ret i64 [[VCEQZ_I]] + return (uint64_t)vceqzd_s64(a); +} diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index a622f5335354a..c5e03e8e88aad 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -406,6 +406,8 @@ def calculate_arch_features(arch_string): if config.have_llvm_driver: config.available_features.add("llvm-driver") +if config.clang_enable_cir: + config.available_features.add("cir-enabled") # Some tests perform deep recursion, which requires a larger pthread stack size # than the relatively low default of 192 KiB for 64-bit processes on AIX. The _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
