https://github.com/iamvickynguyen created https://github.com/llvm/llvm-project/pull/191759
Related to https://github.com/llvm/llvm-project/issues/185382 >From 4310f93413bd86caaef2b36129101bdf4d4a2272 Mon Sep 17 00:00:00 2001 From: Vicky Nguyen <[email protected]> Date: Fri, 10 Apr 2026 21:53:37 -0700 Subject: [PATCH] [CIR][AArch64] Upstream pairwise-minimum NEON builtins --- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 6 + clang/test/CodeGen/AArch64/neon/intrinsics.c | 252 ++++++++++++++++++ 2 files changed, 258 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index cd29c2f16c004..3c6e7d14b7732 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -2378,6 +2378,10 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vpadalq_v: case NEON::BI__builtin_neon_vpmin_v: case NEON::BI__builtin_neon_vpminq_v: + intrName = usgn ? "aarch63.neon.uminp" : "aarch64.neon.sminp"; + if (cir::isFPOrVectorOfFPType(ty)) + intrName = "aarch64.neon.fminp"; + return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); case NEON::BI__builtin_neon_vpmax_v: case NEON::BI__builtin_neon_vpmaxq_v: cgm.errorNYI(expr->getSourceRange(), @@ -2516,6 +2520,8 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, case NEON::BI__builtin_neon_vpmaxnmq_v: case NEON::BI__builtin_neon_vpminnm_v: case NEON::BI__builtin_neon_vpminnmq_v: + intrName = "aarch64.neon.fminnmp"; + return emitNeonCall(cgm, builder, {ty, ty}, ops, intrName, ty, loc); case NEON::BI__builtin_neon_vsqrth_f16: case NEON::BI__builtin_neon_vsqrt_v: case NEON::BI__builtin_neon_vsqrtq_v: diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c index 7d8b7c0e7b629..9cd08179d5fda 100644 --- a/clang/test/CodeGen/AArch64/neon/intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c @@ -1778,6 +1778,258 @@ float64x2_t test_vminnmq_f64(float64x2_t v1, float64x2_t v2) { return vminnmq_f64(v1, v2); } +//===----------------------------------------------------------------------===// +// 2.1.8.6 Pairwise minimum +// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#pairwise-minimum +//===----------------------------------------------------------------------===// + +// LLVM-LABEL: @test_vpmin_s8( +// CIR-LABEL: @vpmin_s8( +int8x8_t test_vpmin_s8(int8x8_t a, int8x8_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.sminp" %{{.*}}, %{{.*}} : (!cir.vector<8 x !s8i>, !cir.vector<8 x !s8i>) -> !cir.vector<8 x !s8i> + +// LLVM-SAME: <8 x i8> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) +// LLVM: [[VPMIN_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sminp.v8i8(<8 x i8> [[A]], <8 x i8> [[B]]) +// LLVM: ret <8 x i8> [[VPMIN_I]] + return vpmin_s8(a, b); +} + +// LLVM-LABEL: @test_vpmin_s16( +// CIR-LABEL: @vpmin_s16( +int16x4_t test_vpmin_s16(int16x4_t a, int16x4_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.sminp" %{{.*}}, %{{.*}} : (!cir.vector<4 x !s16i>, !cir.vector<4 x !s16i>) -> !cir.vector<4 x !s16i> + +// LLVM-SAME: <4 x i16> noundef [[A:%.*]], <4 x i16> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sminp.v4i16(<4 x i16> {{.*}}, <4 x i16> {{.*}}) +// LLVM: ret <4 x i16> [[VPMIN2_I]] + return vpmin_s16(a, b); +} + +// LLVM-LABEL: @test_vpmin_s32( +// CIR-LABEL: @vpmin_s32( +int32x2_t test_vpmin_s32(int32x2_t a, int32x2_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.sminp" %{{.*}}, %{{.*}} : (!cir.vector<2 x !s32i>, !cir.vector<2 x !s32i>) -> !cir.vector<2 x !s32i> + +// LLVM-SAME: <2 x i32> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sminp.v2i32(<2 x i32> {{.*}}, <2 x i32> {{.*}}) +// LLVM: ret <2 x i32> [[VPMIN2_I]] + return vpmin_s32(a, b); +} + +// LLVM-LABEL: @test_vpmin_u8( +// CIR-LABEL: @vpmin_u8( +uint8x8_t test_vpmin_u8(uint8x8_t a, uint8x8_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uminp" %{{.*}}, %{{.*}} : (!cir.vector<8 x !u8i>, !cir.vector<8 x !u8i>) -> !cir.vector<8 x !u8i> + +// LLVM-SAME: <8 x i8> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) +// LLVM: [[VPMIN_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uminp.v8i8(<8 x i8> [[A]], <8 x i8> [[B]]) +// LLVM: ret <8 x i8> [[VPMIN_I]] + return vpmin_u8(a, b); +} + +// LLVM-LABEL: @test_vpmin_u16( +// CIR-LABEL: @vpmin_u16( +uint16x4_t test_vpmin_u16(uint16x4_t a, uint16x4_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uminp" %{{.*}}, %{{.*}} : (!cir.vector<4 x !u16i>, !cir.vector<4 x !u16i>) -> !cir.vector<4 x !u16i> + +// LLVM-SAME: <4 x i16> noundef [[A:%.*]], <4 x i16> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uminp.v4i16(<4 x i16> {{.*}}, <4 x i16> {{.*}}) +// LLVM: ret <4 x i16> [[VPMIN2_I]] + return vpmin_u16(a, b); +} + +// LLVM-LABEL: @test_vpmin_u32( +// CIR-LABEL: @vpmin_u32( +uint32x2_t test_vpmin_u32(uint32x2_t a, uint32x2_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uminp" %{{.*}}, %{{.*}} : (!cir.vector<2 x !u32i>, !cir.vector<2 x !u32i>) -> !cir.vector<2 x !u32i> + +// LLVM-SAME: <2 x i32> noundef [[A:%.*]], <2 x i32> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uminp.v2i32(<2 x i32> {{.*}}, <2 x i32> {{.*}}) +// LLVM: ret <2 x i32> [[VPMIN2_I]] + return vpmin_u32(a, b); +} + +// LLVM-LABEL: @test_vpmin_f32( +// CIR-LABEL: @vpmin_f32( +float32x2_t test_vpmin_f32(float32x2_t a, float32x2_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminp" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.float>, !cir.vector<2 x !cir.float>) -> !cir.vector<2 x !cir.float> + +// LLVM-SAME: <2 x float> noundef [[A:%.*]], <2 x float> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminp.v2f32(<2 x float> {{.*}}, <2 x float> {{.*}}) +// LLVM: ret <2 x float> [[VPMIN2_I]] + return vpmin_f32(a, b); +} + +// LLVM-LABEL: @test_vpminq_s8( +// CIR-LABEL: @vpminq_s8( +int8x16_t test_vpminq_s8(int8x16_t a, int8x16_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.sminp" %{{.*}}, %{{.*}} : (!cir.vector<16 x !s8i>, !cir.vector<16 x !s8i>) -> !cir.vector<16 x !s8i> + +// LLVM-SAME: <16 x i8> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) +// LLVM: [[VPMIN_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sminp.v16i8(<16 x i8> [[A]], <16 x i8> [[B]]) +// LLVM: ret <16 x i8> [[VPMIN_I]] + return vpminq_s8(a, b); +} + +// LLVM-LABEL: @test_vpminq_s16( +// CIR-LABEL: @vpminq_s16( +int16x8_t test_vpminq_s16(int16x8_t a, int16x8_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.sminp" %{{.*}}, %{{.*}} : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i> + +// LLVM-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sminp.v8i16(<8 x i16> {{.*}}, <8 x i16> {{.*}}) +// LLVM: ret <8 x i16> [[VPMIN2_I]] + return vpminq_s16(a, b); +} + +// LLVM-LABEL: @test_vpminq_s32( +// CIR-LABEL: @vpminq_s32( +int32x4_t test_vpminq_s32(int32x4_t a, int32x4_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.sminp" %{{.*}}, %{{.*}} : (!cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i> + +// LLVM-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sminp.v4i32(<4 x i32> {{.*}}, <4 x i32> {{.*}}) +// LLVM: ret <4 x i32> [[VPMIN2_I]] + return vpminq_s32(a, b); +} + +// LLVM-LABEL: @test_vpminq_u8( +// CIR-LABEL: @vpminq_u8( +uint8x16_t test_vpminq_u8(uint8x16_t a, uint8x16_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uminp" %{{.*}}, %{{.*}} : (!cir.vector<16 x !u8i>, !cir.vector<16 x !u8i>) -> !cir.vector<16 x !u8i> + +// LLVM-SAME: <16 x i8> noundef [[A:%.*]], <16 x i8> noundef [[B:%.*]]) +// LLVM: [[VPMIN_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uminp.v16i8(<16 x i8> [[A]], <16 x i8> [[B]]) +// LLVM: ret <16 x i8> [[VPMIN_I]] + return vpminq_u8(a, b); +} + +// LLVM-LABEL: @test_vpminq_u16( +// CIR-LABEL: @vpminq_u16( +uint16x8_t test_vpminq_u16(uint16x8_t a, uint16x8_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uminp" %{{.*}}, %{{.*}} : (!cir.vector<8 x !u16i>, !cir.vector<8 x !u16i>) -> !cir.vector<8 x !u16i> + +// LLVM-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uminp.v8i16(<8 x i16> {{.*}}, <8 x i16> {{.*}}) +// LLVM: ret <8 x i16> [[VPMIN2_I]] + return vpminq_u16(a, b); +} + +// LLVM-LABEL: @test_vpminq_u32( +// CIR-LABEL: @vpminq_u32( +uint32x4_t test_vpminq_u32(uint32x4_t a, uint32x4_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.uminp" %{{.*}}, %{{.*}} : (!cir.vector<4 x !u32i>, !cir.vector<4 x !u32i>) -> !cir.vector<4 x !u32i> + +// LLVM-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uminp.v4i32(<4 x i32> {{.*}}, <4 x i32> {{.*}}) +// LLVM: ret <4 x i32> [[VPMIN2_I]] + return vpminq_u32(a, b); +} + +// LLVM-LABEL: @test_vpminq_f32( +// CIR-LABEL: @vpminq_f32( +float32x4_t test_vpminq_f32(float32x4_t a, float32x4_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminp" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float> + +// LLVM-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminp.v4f32(<4 x float> {{.*}}, <4 x float> {{.*}}) +// LLVM: ret <4 x float> [[VPMIN2_I]] + return vpminq_f32(a, b); +} + +// LLVM-LABEL: @test_vpminq_f64( +// CIR-LABEL: @vpminq_f64( +float64x2_t test_vpminq_f64(float64x2_t a, float64x2_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminp" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double> + +// LLVM-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) +// LLVM: [[VPMIN2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminp.v2f64(<2 x double> {{.*}}, <2 x double> {{.*}}) +// LLVM: ret <2 x double> [[VPMIN2_I]] + return vpminq_f64(a, b); +} + +//===----------------------------------------------------------------------===// +// 2.1.8.7 Pairwise minimum (IEEE754) +// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#pairwise-minimum-ieee754 +//===----------------------------------------------------------------------===// + +// LLVM-LABEL: @test_vpminnm_f32( +// CIR-LABEL: @vpminnm_f32( +float32x2_t test_vpminnm_f32(float32x2_t a, float32x2_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmp" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.float>, !cir.vector<2 x !cir.float>) -> !cir.vector<2 x !cir.float> + +// LLVM-SAME: <2 x float> noundef [[A:%.*]], <2 x float> noundef [[B:%.*]]) +// LLVM: [[VPMINNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminnmp.v2f32(<2 x float> {{.*}}, <2 x float> {{.*}}) +// LLVM: ret <2 x float> [[VPMINNM2_I]] + return vpminnm_f32(a, b); +} + +// LLVM-LABEL: @test_vpminnmq_f32( +// CIR-LABEL: @vpminnmq_f32( +float32x4_t test_vpminnmq_f32(float32x4_t a, float32x4_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmp" %{{.*}}, %{{.*}} : (!cir.vector<4 x !cir.float>, !cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float> + +// LLVM-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) +// LLVM: [[VPMINNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminnmp.v4f32(<4 x float> {{.*}}, <4 x float> {{.*}}) +// LLVM: ret <4 x float> [[VPMINNM2_I]] + return vpminnmq_f32(a, b); +} + +// LLVM-LABEL: @test_vpminnmq_f64( +// CIR-LABEL: @vpminnmq_f64( +float64x2_t test_vpminnmq_f64(float64x2_t a, float64x2_t b) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmp" %{{.*}}, %{{.*}} : (!cir.vector<2 x !cir.double>, !cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double> + +// LLVM-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) +// LLVM: [[VPMINNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminnmp.v2f64(<2 x double> {{.*}}, <2 x double> {{.*}}) +// LLVM: ret <2 x double> [[VPMINNM2_I]] + return vpminnmq_f64(a, b); +} + +// LLVM-LABEL: @test_vpmins_f32( +// CIR-LABEL: @vpmins_f32( +float32_t test_vpmins_f32(float32x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminv" %{{.*}} : (!cir.vector<2 x !cir.float>) -> !cir.float + +// LLVM-SAME: <2 x float> noundef [[A:%.*]]) +// LLVM: [[VPMINS_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> [[A]]) +// LLVM: ret float [[VPMINS_F32_I]] + return vpmins_f32(a); +} + +// LLVM-LABEL: @test_vpminqd_f64( +// CIR-LABEL: @vpminqd_f64( +float64_t test_vpminqd_f64(float64x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminv" %{{.*}} : (!cir.vector<2 x !cir.double>) -> !cir.double + +// LLVM-SAME: <2 x double> noundef [[A:%.*]]) +// LLVM: [[VPMINQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> [[A]]) +// LLVM: ret double [[VPMINQD_F64_I]] + return vpminqd_f64(a); +} + +// LLVM-LABEL: @test_vpminnms_f32( +// CIR-LABEL: @vpminnms_f32( +float32_t test_vpminnms_f32(float32x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmv" %{{.*}} : (!cir.vector<2 x !cir.float>) -> !cir.float + +// LLVM-SAME: <2 x float> noundef [[A:%.*]]) +// LLVM: [[VPMINNMS_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> [[A]]) +// LLVM: ret float [[VPMINNMS_F32_I]] + return vpminnms_f32(a); +} + +// LLVM-LABEL: @test_vpminnmqd_f64( +// CIR-LABEL: @vpminnmqd_f64( +float64_t test_vpminnmqd_f64(float64x2_t a) { +// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmv" %{{.*}} : (!cir.vector<2 x !cir.double>) -> !cir.double + +// LLVM-SAME: <2 x double> noundef [[A:%.*]]) +// LLVM: [[VPMINNMQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> [[A]]) +// LLVM: ret double [[VPMINNMQD_F64_I]] + return vpminnmqd_f64(a); +} + //===------------------------------------------------------===// // 2.1.3.1.1. Vector Shift Left // https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#vector-shift-left _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
