[clang] [CIR][AArch64] Lower NEON vminv intrinsics (PR #192901)

via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 20 00:04:31 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Jiahao Guo (E00N777)

<details>
<summary>Changes</summary>

### Summary

part of : https://github.com/llvm/llvm-project/issues/185382

Lower all intrinsics in https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#minimum-across-vector and https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#minimum-across-vector-(IEEE754)

Add ClangIR (CIR) codegen support for the NEON minimum-across-vector builtins on AArch64. This covers the ACLE sections 2.1.1.13.4 Minimum across vector (signed/unsigned integer + float) and 2.1.1.13.6 Minimum across vector (IEEE 754, NaN-ignoring). Corresponding classic-CodeGen-only tests are migrated into the shared CIR+LLVM test file so both pipelines are checked from the same RUN lines.

These builtins are already registered in AArch64SISDIntrinsicMap (clang/include/clang/Basic/AArch64CodeGenUtils.h) with the correct LLVMIntrinsic IDs and TypeModifiers, mirroring the classic CodeGen flow in clang/lib/CodeGen/TargetBuiltins/ARM.cpp::EmitCommonNeonSISDBuiltinExpr. In CIR the same map drives emitCommonNeonSISDBuiltinExpr, so the only missing piece was adding these builtin IDs to the dispatch switch — no intrinsic-specific lowering is needed. 

---
Full diff: https://github.com/llvm/llvm-project/pull/192901.diff


4 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp (+18) 
- (modified) clang/test/CodeGen/AArch64/neon-across.c (-109) 
- (modified) clang/test/CodeGen/AArch64/neon-intrinsics.c (-60) 
- (modified) clang/test/CodeGen/AArch64/neon/intrinsics.c (+226) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 302218ec2567c..16f306665b265 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -260,6 +260,24 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr(
                      std::string("unimplemented AArch64 builtin call: ") +
                          cgf.getContext().BuiltinInfo.getName(info.BuiltinID));
     break;
+  case NEON::BI__builtin_neon_vminv_s8:
+  case NEON::BI__builtin_neon_vminvq_s8:
+  case NEON::BI__builtin_neon_vminv_s16:
+  case NEON::BI__builtin_neon_vminvq_s16:
+  case NEON::BI__builtin_neon_vminv_s32:
+  case NEON::BI__builtin_neon_vminvq_s32:
+  case NEON::BI__builtin_neon_vminv_u8:
+  case NEON::BI__builtin_neon_vminvq_u8:
+  case NEON::BI__builtin_neon_vminv_u16:
+  case NEON::BI__builtin_neon_vminvq_u16:
+  case NEON::BI__builtin_neon_vminv_u32:
+  case NEON::BI__builtin_neon_vminvq_u32:
+  case NEON::BI__builtin_neon_vminv_f32:
+  case NEON::BI__builtin_neon_vminvq_f32:
+  case NEON::BI__builtin_neon_vminvq_f64:
+  case NEON::BI__builtin_neon_vminnmv_f32:
+  case NEON::BI__builtin_neon_vminnmvq_f32:
+  case NEON::BI__builtin_neon_vminnmvq_f64:
   case NEON::BI__builtin_neon_vabdd_f64:
   case NEON::BI__builtin_neon_vabds_f32:
   case NEON::BI__builtin_neon_vshld_s64:
diff --git a/clang/test/CodeGen/AArch64/neon-across.c b/clang/test/CodeGen/AArch64/neon-across.c
index aae5097da7789..b97297552042f 100644
--- a/clang/test/CodeGen/AArch64/neon-across.c
+++ b/clang/test/CodeGen/AArch64/neon-across.c
@@ -210,96 +210,6 @@ uint32_t test_vmaxvq_u32(uint32x4_t a) {
   return vmaxvq_u32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vminv_s8
-// CHECK-SAME: (<8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINV_S8_I:%.*]] = call i8 @llvm.vector.reduce.smin.v8i8(<8 x i8> [[A]])
-// CHECK-NEXT:    ret i8 [[VMINV_S8_I]]
-//
-int8_t test_vminv_s8(int8x8_t a) {
-  return vminv_s8(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminv_s16
-// CHECK-SAME: (<4 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINV_S16_I:%.*]] = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> [[A]])
-// CHECK-NEXT:    ret i16 [[VMINV_S16_I]]
-//
-int16_t test_vminv_s16(int16x4_t a) {
-  return vminv_s16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminv_u8
-// CHECK-SAME: (<8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINV_U8_I:%.*]] = call i8 @llvm.vector.reduce.umin.v8i8(<8 x i8> [[A]])
-// CHECK-NEXT:    ret i8 [[VMINV_U8_I]]
-//
-uint8_t test_vminv_u8(uint8x8_t a) {
-  return vminv_u8(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminv_u16
-// CHECK-SAME: (<4 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINV_U16_I:%.*]] = call i16 @llvm.vector.reduce.umin.v4i16(<4 x i16> [[A]])
-// CHECK-NEXT:    ret i16 [[VMINV_U16_I]]
-//
-uint16_t test_vminv_u16(uint16x4_t a) {
-  return vminv_u16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminvq_s8
-// CHECK-SAME: (<16 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINVQ_S8_I:%.*]] = call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> [[A]])
-// CHECK-NEXT:    ret i8 [[VMINVQ_S8_I]]
-//
-int8_t test_vminvq_s8(int8x16_t a) {
-  return vminvq_s8(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminvq_s16
-// CHECK-SAME: (<8 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINVQ_S16_I:%.*]] = call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> [[A]])
-// CHECK-NEXT:    ret i16 [[VMINVQ_S16_I]]
-//
-int16_t test_vminvq_s16(int16x8_t a) {
-  return vminvq_s16(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminvq_s32
-// CHECK-SAME: (<4 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINVQ_S32_I:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[A]])
-// CHECK-NEXT:    ret i32 [[VMINVQ_S32_I]]
-//
-int32_t test_vminvq_s32(int32x4_t a) {
-  return vminvq_s32(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminvq_u8
-// CHECK-SAME: (<16 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINVQ_U8_I:%.*]] = call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> [[A]])
-// CHECK-NEXT:    ret i8 [[VMINVQ_U8_I]]
-//
-uint8_t test_vminvq_u8(uint8x16_t a) {
-  return vminvq_u8(a);
-}
-
-// CHECK-LABEL: define {{[^@]+}}@test_vminvq_u16
-// CHECK-SAME: (<8 x i16> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINVQ_U16_I:%.*]] = call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> [[A]])
-// CHECK-NEXT:    ret i16 [[VMINVQ_U16_I]]
-//
-uint16_t test_vminvq_u16(uint16x8_t a) {
-  return vminvq_u16(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vminvq_u32
 // CHECK-SAME: (<4 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -420,16 +330,6 @@ float32_t test_vmaxvq_f32(float32x4_t a) {
   return vmaxvq_f32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vminvq_f32
-// CHECK-SAME: (<4 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> [[A]])
-// CHECK-NEXT:    ret float [[VMINVQ_F32_I]]
-//
-float32_t test_vminvq_f32(float32x4_t a) {
-  return vminvq_f32(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vmaxnmvq_f32
 // CHECK-SAME: (<4 x float> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -440,13 +340,4 @@ float32_t test_vmaxnmvq_f32(float32x4_t a) {
   return vmaxnmvq_f32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vminnmvq_f32
-// CHECK-SAME: (<4 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VMINNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> [[A]])
-// CHECK-NEXT:    ret float [[VMINNMVQ_F32_I]]
-//
-float32_t test_vminnmvq_f32(float32x4_t a) {
-  return vminnmvq_f32(a);
-}
 
diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c
index dc7b0112407f5..c1c347c275f94 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c
@@ -20437,26 +20437,6 @@ float64_t test_vmaxvq_f64(float64x2_t a) {
   return vmaxvq_f64(a);
 }
 
-// CHECK-LABEL: define dso_local float @test_vminv_f32(
-// CHECK-SAME: <2 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VMINV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> [[A]])
-// CHECK-NEXT:    ret float [[VMINV_F32_I]]
-//
-float32_t test_vminv_f32(float32x2_t a) {
-  return vminv_f32(a);
-}
-
-// CHECK-LABEL: define dso_local double @test_vminvq_f64(
-// CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VMINVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> [[A]])
-// CHECK-NEXT:    ret double [[VMINVQ_F64_I]]
-//
-float64_t test_vminvq_f64(float64x2_t a) {
-  return vminvq_f64(a);
-}
-
 // CHECK-LABEL: define dso_local double @test_vmaxnmvq_f64(
 // CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -20477,26 +20457,6 @@ float32_t test_vmaxnmv_f32(float32x2_t a) {
   return vmaxnmv_f32(a);
 }
 
-// CHECK-LABEL: define dso_local double @test_vminnmvq_f64(
-// CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VMINNMVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> [[A]])
-// CHECK-NEXT:    ret double [[VMINNMVQ_F64_I]]
-//
-float64_t test_vminnmvq_f64(float64x2_t a) {
-  return vminnmvq_f64(a);
-}
-
-// CHECK-LABEL: define dso_local float @test_vminnmv_f32(
-// CHECK-SAME: <2 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VMINNMV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> [[A]])
-// CHECK-NEXT:    ret float [[VMINNMV_F32_I]]
-//
-float32_t test_vminnmv_f32(float32x2_t a) {
-  return vminnmv_f32(a);
-}
-
 // CHECK-LABEL: define dso_local <2 x i64> @test_vpaddq_s64(
 // CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -21057,26 +21017,6 @@ float64x1_t test_vrsqrts_f64(float64x1_t a, float64x1_t b) {
   return vrsqrts_f64(a, b);
 }
 
-// CHECK-LABEL: define dso_local i32 @test_vminv_s32(
-// CHECK-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VMINV_S32_I:%.*]] = call i32 @llvm.vector.reduce.smin.v2i32(<2 x i32> [[A]])
-// CHECK-NEXT:    ret i32 [[VMINV_S32_I]]
-//
-int32_t test_vminv_s32(int32x2_t a) {
-  return vminv_s32(a);
-}
-
-// CHECK-LABEL: define dso_local i32 @test_vminv_u32(
-// CHECK-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VMINV_U32_I:%.*]] = call i32 @llvm.vector.reduce.umin.v2i32(<2 x i32> [[A]])
-// CHECK-NEXT:    ret i32 [[VMINV_U32_I]]
-//
-uint32_t test_vminv_u32(uint32x2_t a) {
-  return vminv_u32(a);
-}
-
 // CHECK-LABEL: define dso_local i32 @test_vmaxv_s32(
 // CHECK-SAME: <2 x i32> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index 2f0a7014e9894..1d76ded41c1f6 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -3877,3 +3877,229 @@ uint64_t test_vrsrad_n_u64(uint64_t a, uint64_t b) {
   // LLVM: ret i64 [[RES]]
   return (uint64_t)vrsrad_n_u64(a, b, 63);
 }
+
+//===------------------------------------------------------===//
+// 2.1.1.13.4. Minimum across vector 
+// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#minimum-across-vector
+//===------------------------------------------------------===//
+
+// LLVM-LABEL: @test_vminv_s8(
+// CIR-LABEL: @vminv_s8(
+int8_t test_vminv_s8(int8x8_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.smin" %{{.*}} : (!cir.vector<8 x !s8i>) -> !s8i
+// CIR: cir.return %{{.*}} : !s8i
+
+// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_S8_I:%.*]] = call i8 @llvm.vector.reduce.smin.v8i8(<8 x i8> [[A]])
+// LLVM-NEXT:    ret i8 [[VMINV_S8_I]]
+  return vminv_s8(a);
+}
+
+// LLVM-LABEL: @test_vminvq_s8(
+// CIR-LABEL: @vminvq_s8(
+int8_t test_vminvq_s8(int8x16_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.smin" %{{.*}} : (!cir.vector<16 x !s8i>) -> !s8i
+// CIR: cir.return %{{.*}} : !s8i
+
+// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_S8_I:%.*]] = call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> [[A]])
+// LLVM-NEXT:    ret i8 [[VMINVQ_S8_I]]
+  return vminvq_s8(a);
+}
+
+// LLVM-LABEL: @test_vminv_s16(
+// CIR-LABEL: @vminv_s16(
+int16_t test_vminv_s16(int16x4_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.smin" %{{.*}} : (!cir.vector<4 x !s16i>) -> !s16i
+// CIR: cir.return %{{.*}} : !s16i
+
+// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_S16_I:%.*]] = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> [[A]])
+// LLVM-NEXT:    ret i16 [[VMINV_S16_I]]
+  return vminv_s16(a);
+}
+
+// LLVM-LABEL: @test_vminvq_s16(
+// CIR-LABEL: @vminvq_s16(
+int16_t test_vminvq_s16(int16x8_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.smin" %{{.*}} : (!cir.vector<8 x !s16i>) -> !s16i
+// CIR: cir.return %{{.*}} : !s16i
+
+// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_S16_I:%.*]] = call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> [[A]])
+// LLVM-NEXT:    ret i16 [[VMINVQ_S16_I]]
+  return vminvq_s16(a);
+}
+
+// LLVM-LABEL: @test_vminv_s32(
+// CIR-LABEL: @vminv_s32(
+int32_t test_vminv_s32(int32x2_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.smin" %{{.*}} : (!cir.vector<2 x !s32i>) -> !s32i
+// CIR: cir.return %{{.*}} : !s32i
+
+// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_S32_I:%.*]] = call i32 @llvm.vector.reduce.smin.v2i32(<2 x i32> [[A]])
+// LLVM-NEXT:    ret i32 [[VMINV_S32_I]]
+  return vminv_s32(a);
+}
+
+// LLVM-LABEL: @test_vminvq_s32(
+// CIR-LABEL: @vminvq_s32(
+int32_t test_vminvq_s32(int32x4_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.smin" %{{.*}} : (!cir.vector<4 x !s32i>) -> !s32i
+// CIR: cir.return %{{.*}} : !s32i
+
+// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_S32_I:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[A]])
+// LLVM-NEXT:    ret i32 [[VMINVQ_S32_I]]
+  return vminvq_s32(a);
+}
+
+// LLVM-LABEL: @test_vminv_u8(
+// CIR-LABEL: @vminv_u8(
+uint8_t test_vminv_u8(uint8x8_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.umin" %{{.*}} : (!cir.vector<8 x !u8i>) -> !u8i
+// CIR: cir.return %{{.*}} : !u8i
+
+// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_U8_I:%.*]] = call i8 @llvm.vector.reduce.umin.v8i8(<8 x i8> [[A]])
+// LLVM-NEXT:    ret i8 [[VMINV_U8_I]]
+  return vminv_u8(a);
+}
+
+// LLVM-LABEL: @test_vminvq_u8(
+// CIR-LABEL: @vminvq_u8(
+uint8_t test_vminvq_u8(uint8x16_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.umin" %{{.*}} : (!cir.vector<16 x !u8i>) -> !u8i
+// CIR: cir.return %{{.*}} : !u8i
+
+// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_U8_I:%.*]] = call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> [[A]])
+// LLVM-NEXT:    ret i8 [[VMINVQ_U8_I]]
+  return vminvq_u8(a);
+}
+
+// LLVM-LABEL: @test_vminv_u16(
+// CIR-LABEL: @vminv_u16(
+uint16_t test_vminv_u16(uint16x4_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.umin" %{{.*}} : (!cir.vector<4 x !u16i>) -> !u16i
+// CIR: cir.return %{{.*}} : !u16i
+
+// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_U16_I:%.*]] = call i16 @llvm.vector.reduce.umin.v4i16(<4 x i16> [[A]])
+// LLVM-NEXT:    ret i16 [[VMINV_U16_I]]
+  return vminv_u16(a);
+}
+
+// LLVM-LABEL: @test_vminvq_u16(
+// CIR-LABEL: @vminvq_u16(
+uint16_t test_vminvq_u16(uint16x8_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.umin" %{{.*}} : (!cir.vector<8 x !u16i>) -> !u16i
+// CIR: cir.return %{{.*}} : !u16i
+
+// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_U16_I:%.*]] = call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> [[A]])
+// LLVM-NEXT:    ret i16 [[VMINVQ_U16_I]]
+  return vminvq_u16(a);
+}
+
+// LLVM-LABEL: @test_vminv_u32(
+// CIR-LABEL: @vminv_u32(
+uint32_t test_vminv_u32(uint32x2_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.umin" %{{.*}} : (!cir.vector<2 x !u32i>) -> !u32i
+// CIR: cir.return %{{.*}} : !u32i
+
+// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_U32_I:%.*]] = call i32 @llvm.vector.reduce.umin.v2i32(<2 x i32> [[A]])
+// LLVM-NEXT:    ret i32 [[VMINV_U32_I]]
+  return vminv_u32(a);
+}
+
+// LLVM-LABEL: @test_vminvq_u32(
+// CIR-LABEL: @vminvq_u32(
+uint32_t test_vminvq_u32(uint32x4_t a) {
+// CIR: cir.call_llvm_intrinsic "vector.reduce.umin" %{{.*}} : (!cir.vector<4 x !u32i>) -> !u32i
+// CIR: cir.return %{{.*}} : !u32i
+
+// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_U32_I:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[A]])
+// LLVM-NEXT:    ret i32 [[VMINVQ_U32_I]]
+  return vminvq_u32(a);
+}
+
+// LLVM-LABEL: @test_vminv_f32(
+// CIR-LABEL: @vminv_f32(
+float32_t test_vminv_f32(float32x2_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminv" %{{.*}} : (!cir.vector<2 x !cir.float>) -> !cir.float
+// CIR: cir.return %{{.*}} : !cir.float
+
+// LLVM-SAME: <2 x float> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> [[A]])
+// LLVM-NEXT:    ret float [[VMINV_F32_I]]
+  return vminv_f32(a);
+}
+
+// LLVM-LABEL: @test_vminvq_f32(
+// CIR-LABEL: @vminvq_f32(
+float32_t test_vminvq_f32(float32x4_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminv" %{{.*}} : (!cir.vector<4 x !cir.float>) -> !cir.float
+// CIR: cir.return %{{.*}} : !cir.float
+
+// LLVM-SAME: <4 x float> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> [[A]])
+// LLVM-NEXT:    ret float [[VMINVQ_F32_I]]
+  return vminvq_f32(a);
+}
+
+// LLVM-LABEL: @test_vminvq_f64(
+// CIR-LABEL: @vminvq_f64(
+float64_t test_vminvq_f64(float64x2_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminv" %{{.*}} : (!cir.vector<2 x !cir.double>) -> !cir.double
+// CIR: cir.return %{{.*}} : !cir.double
+
+// LLVM-SAME: <2 x double> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> [[A]])
+// LLVM-NEXT:    ret double [[VMINVQ_F64_I]]
+  return vminvq_f64(a);
+}
+
+//===------------------------------------------------------===//
+// 2.1.1.13.6. Minimum across vector (IEEE754)
+// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#markdown-toc-maximum-across-vector-ieee754
+//===------------------------------------------------------===//
+
+// LLVM-LABEL: @test_vminnmv_f32(
+// CIR-LABEL: @vminnmv_f32(
+float32_t test_vminnmv_f32(float32x2_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmv" %{{.*}} : (!cir.vector<2 x !cir.float>) -> !cir.float
+// CIR: cir.return %{{.*}} : !cir.float
+
+// LLVM-SAME: <2 x float> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINNMV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> [[A]])
+// LLVM-NEXT:    ret float [[VMINNMV_F32_I]]
+  return vminnmv_f32(a);
+}
+
+// LLVM-LABEL: @test_vminnmvq_f32(
+// CIR-LABEL: @vminnmvq_f32(
+float32_t test_vminnmvq_f32(float32x4_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmv" %{{.*}} : (!cir.vector<4 x !cir.float>) -> !cir.float
+// CIR: cir.return %{{.*}} : !cir.float
+
+// LLVM-SAME: <4 x float> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> [[A]])
+// LLVM-NEXT:    ret float [[VMINNMVQ_F32_I]]
+  return vminnmvq_f32(a);
+}
+
+// LLVM-LABEL: @test_vminnmvq_f64(
+// CIR-LABEL: @vminnmvq_f64(
+float64_t test_vminnmvq_f64(float64x2_t a) {
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.fminnmv" %{{.*}} : (!cir.vector<2 x !cir.double>) -> !cir.double
+// CIR: cir.return %{{.*}} : !cir.double
+
+// LLVM-SAME: <2 x double> {{.*}} [[A:%.*]])
+// LLVM:    [[VMINNMVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> [[A]])
+// LLVM-NEXT:    ret double [[VMINNMVQ_F64_I]]
+  return vminnmvq_f64(a);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/192901


More information about the cfe-commits mailing list