[llvm] d0f56c3 - [AArch64] Add and expand the testing of fmin/fmax reduction. NFC

David Green via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 19 07:47:25 PDT 2023


Author: David Green
Date: 2023-06-19T15:47:21+01:00
New Revision: d0f56c3e5cc0ead069280d59c41fe12567ed0619

URL: https://github.com/llvm/llvm-project/commit/d0f56c3e5cc0ead069280d59c41fe12567ed0619
DIFF: https://github.com/llvm/llvm-project/commit/d0f56c3e5cc0ead069280d59c41fe12567ed0619.diff

LOG: [AArch64] Add and expand the testing of fmin/fmax reduction. NFC

For both CodeGen and CostModelling, this adds extran testing for the new
lvm.vector.reduce.fmaximum and lvm.vector.reduce.fminimum intrinsics, as well
as making sure there is test coverage for all the various cases.

Added: 
    llvm/test/CodeGen/AArch64/vecreduce-fminimum.ll

Modified: 
    llvm/test/Analysis/CostModel/AArch64/reduce-minmax.ll
    llvm/test/CodeGen/AArch64/vecreduce-fadd.ll
    llvm/test/CodeGen/AArch64/vecreduce-fmax-legalization.ll
    llvm/test/CodeGen/AArch64/vecreduce-fmaximum.ll
    llvm/test/CodeGen/AArch64/vecreduce-fmin-legalization.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Analysis/CostModel/AArch64/reduce-minmax.ll b/llvm/test/Analysis/CostModel/AArch64/reduce-minmax.ll
index cf813bae839c6..c10f87fcef658 100644
--- a/llvm/test/Analysis/CostModel/AArch64/reduce-minmax.ll
+++ b/llvm/test/Analysis/CostModel/AArch64/reduce-minmax.ll
@@ -166,6 +166,10 @@ define void @reduce_fmin16() {
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 40 for instruction: %V4f16 = call half @llvm.vector.reduce.fmin.v4f16(<4 x half> undef)
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 198 for instruction: %V8f16 = call half @llvm.vector.reduce.fmin.v8f16(<8 x half> undef)
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 298 for instruction: %V16f16 = call half @llvm.vector.reduce.fmin.v16f16(<16 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f16m = call half @llvm.vector.reduce.fminimum.v2f16(<2 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 13 for instruction: %V4f16m = call half @llvm.vector.reduce.fminimum.v4f16(<4 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 29 for instruction: %V8f16m = call half @llvm.vector.reduce.fminimum.v8f16(<8 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 58 for instruction: %V16f16m = call half @llvm.vector.reduce.fminimum.v16f16(<16 x half> undef)
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 0 for instruction: ret void
 ;
 ; CHECK-F16-LABEL: 'reduce_fmin16'
@@ -173,12 +177,20 @@ define void @reduce_fmin16() {
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 2 for instruction: %V4f16 = call half @llvm.vector.reduce.fmin.v4f16(<4 x half> undef)
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 2 for instruction: %V8f16 = call half @llvm.vector.reduce.fmin.v8f16(<8 x half> undef)
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 3 for instruction: %V16f16 = call half @llvm.vector.reduce.fmin.v16f16(<16 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f16m = call half @llvm.vector.reduce.fminimum.v2f16(<2 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 13 for instruction: %V4f16m = call half @llvm.vector.reduce.fminimum.v4f16(<4 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 29 for instruction: %V8f16m = call half @llvm.vector.reduce.fminimum.v8f16(<8 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 58 for instruction: %V16f16m = call half @llvm.vector.reduce.fminimum.v16f16(<16 x half> undef)
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 0 for instruction: ret void
 ;
   %V2f16 = call half @llvm.vector.reduce.fmin.v2f16(<2 x half> undef)
   %V4f16 = call half @llvm.vector.reduce.fmin.v4f16(<4 x half> undef)
   %V8f16 = call half @llvm.vector.reduce.fmin.v8f16(<8 x half> undef)
   %V16f16 = call half @llvm.vector.reduce.fmin.v16f16(<16 x half> undef)
+  %V2f16m = call half @llvm.vector.reduce.fminimum.v2f16(<2 x half> undef)
+  %V4f16m = call half @llvm.vector.reduce.fminimum.v4f16(<4 x half> undef)
+  %V8f16m = call half @llvm.vector.reduce.fminimum.v8f16(<8 x half> undef)
+  %V16f16m = call half @llvm.vector.reduce.fminimum.v16f16(<16 x half> undef)
   ret void
 }
 
@@ -188,6 +200,10 @@ define void @reduce_fmax16() {
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 40 for instruction: %V4f16 = call half @llvm.vector.reduce.fmax.v4f16(<4 x half> undef)
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 198 for instruction: %V8f16 = call half @llvm.vector.reduce.fmax.v8f16(<8 x half> undef)
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 298 for instruction: %V16f16 = call half @llvm.vector.reduce.fmax.v16f16(<16 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f16m = call half @llvm.vector.reduce.fmaximum.v2f16(<2 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 13 for instruction: %V4f16m = call half @llvm.vector.reduce.fmaximum.v4f16(<4 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 29 for instruction: %V8f16m = call half @llvm.vector.reduce.fmaximum.v8f16(<8 x half> undef)
+; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 58 for instruction: %V16f16m = call half @llvm.vector.reduce.fmaximum.v16f16(<16 x half> undef)
 ; CHECK-NOF16-NEXT:  Cost Model: Found an estimated cost of 0 for instruction: ret void
 ;
 ; CHECK-F16-LABEL: 'reduce_fmax16'
@@ -195,12 +211,20 @@ define void @reduce_fmax16() {
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 2 for instruction: %V4f16 = call half @llvm.vector.reduce.fmax.v4f16(<4 x half> undef)
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 2 for instruction: %V8f16 = call half @llvm.vector.reduce.fmax.v8f16(<8 x half> undef)
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 3 for instruction: %V16f16 = call half @llvm.vector.reduce.fmax.v16f16(<16 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f16m = call half @llvm.vector.reduce.fmaximum.v2f16(<2 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 13 for instruction: %V4f16m = call half @llvm.vector.reduce.fmaximum.v4f16(<4 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 29 for instruction: %V8f16m = call half @llvm.vector.reduce.fmaximum.v8f16(<8 x half> undef)
+; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 58 for instruction: %V16f16m = call half @llvm.vector.reduce.fmaximum.v16f16(<16 x half> undef)
 ; CHECK-F16-NEXT:  Cost Model: Found an estimated cost of 0 for instruction: ret void
 ;
   %V2f16 = call half @llvm.vector.reduce.fmax.v2f16(<2 x half> undef)
   %V4f16 = call half @llvm.vector.reduce.fmax.v4f16(<4 x half> undef)
   %V8f16 = call half @llvm.vector.reduce.fmax.v8f16(<8 x half> undef)
   %V16f16 = call half @llvm.vector.reduce.fmax.v16f16(<16 x half> undef)
+  %V2f16m = call half @llvm.vector.reduce.fmaximum.v2f16(<2 x half> undef)
+  %V4f16m = call half @llvm.vector.reduce.fmaximum.v4f16(<4 x half> undef)
+  %V8f16m = call half @llvm.vector.reduce.fmaximum.v8f16(<8 x half> undef)
+  %V16f16m = call half @llvm.vector.reduce.fmaximum.v16f16(<16 x half> undef)
   ret void
 }
 
@@ -211,6 +235,11 @@ define void @reduce_fmin() {
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 3 for instruction: %V8f32 = call float @llvm.vector.reduce.fmin.v8f32(<8 x float> undef)
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 2 for instruction: %V2f64 = call double @llvm.vector.reduce.fmin.v2f64(<2 x double> undef)
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 3 for instruction: %V4f64 = call double @llvm.vector.reduce.fmin.v4f64(<4 x double> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f32m = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 13 for instruction: %V4f32m = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 26 for instruction: %V8f32m = call float @llvm.vector.reduce.fminimum.v8f32(<8 x float> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f64m = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 10 for instruction: %V4f64m = call double @llvm.vector.reduce.fminimum.v4f64(<4 x double> undef)
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 0 for instruction: ret void
 ;
   %V2f32 = call float @llvm.vector.reduce.fmin.v2f32(<2 x float> undef)
@@ -218,6 +247,11 @@ define void @reduce_fmin() {
   %V8f32 = call float @llvm.vector.reduce.fmin.v8f32(<8 x float> undef)
   %V2f64 = call double @llvm.vector.reduce.fmin.v2f64(<2 x double> undef)
   %V4f64 = call double @llvm.vector.reduce.fmin.v4f64(<4 x double> undef)
+  %V2f32m = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef)
+  %V4f32m = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> undef)
+  %V8f32m = call float @llvm.vector.reduce.fminimum.v8f32(<8 x float> undef)
+  %V2f64m = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef)
+  %V4f64m = call double @llvm.vector.reduce.fminimum.v4f64(<4 x double> undef)
   ret void
 }
 
@@ -228,6 +262,11 @@ define void @reduce_fmax() {
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 3 for instruction: %V8f32 = call float @llvm.vector.reduce.fmax.v8f32(<8 x float> undef)
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 2 for instruction: %V2f64 = call double @llvm.vector.reduce.fmax.v2f64(<2 x double> undef)
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 3 for instruction: %V4f64 = call double @llvm.vector.reduce.fmax.v4f64(<4 x double> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f32m = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 13 for instruction: %V4f32m = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 26 for instruction: %V8f32m = call float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 5 for instruction: %V2f64m = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 10 for instruction: %V4f64m = call double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef)
 ; CHECK-NEXT:  Cost Model: Found an estimated cost of 0 for instruction: ret void
 ;
   %V2f32 = call float @llvm.vector.reduce.fmax.v2f32(<2 x float> undef)
@@ -235,6 +274,11 @@ define void @reduce_fmax() {
   %V8f32 = call float @llvm.vector.reduce.fmax.v8f32(<8 x float> undef)
   %V2f64 = call double @llvm.vector.reduce.fmax.v2f64(<2 x double> undef)
   %V4f64 = call double @llvm.vector.reduce.fmax.v4f64(<4 x double> undef)
+  %V2f32m = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef)
+  %V4f32m = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef)
+  %V8f32m = call float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef)
+  %V2f64m = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef)
+  %V4f64m = call double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef)
   ret void
 }
 
@@ -325,3 +369,23 @@ declare float @llvm.vector.reduce.fmax.v4f32(<4 x float>)
 declare float @llvm.vector.reduce.fmax.v8f32(<8 x float>)
 declare double @llvm.vector.reduce.fmax.v2f64(<2 x double>)
 declare double @llvm.vector.reduce.fmax.v4f64(<4 x double>)
+
+declare half @llvm.vector.reduce.fminimum.v2f16(<2 x half>)
+declare half @llvm.vector.reduce.fminimum.v4f16(<4 x half>)
+declare half @llvm.vector.reduce.fminimum.v8f16(<8 x half>)
+declare half @llvm.vector.reduce.fminimum.v16f16(<16 x half>)
+declare float @llvm.vector.reduce.fminimum.v2f32(<2 x float>)
+declare float @llvm.vector.reduce.fminimum.v4f32(<4 x float>)
+declare float @llvm.vector.reduce.fminimum.v8f32(<8 x float>)
+declare double @llvm.vector.reduce.fminimum.v2f64(<2 x double>)
+declare double @llvm.vector.reduce.fminimum.v4f64(<4 x double>)
+
+declare half @llvm.vector.reduce.fmaximum.v2f16(<2 x half>)
+declare half @llvm.vector.reduce.fmaximum.v4f16(<4 x half>)
+declare half @llvm.vector.reduce.fmaximum.v8f16(<8 x half>)
+declare half @llvm.vector.reduce.fmaximum.v16f16(<16 x half>)
+declare float @llvm.vector.reduce.fmaximum.v2f32(<2 x float>)
+declare float @llvm.vector.reduce.fmaximum.v4f32(<4 x float>)
+declare float @llvm.vector.reduce.fmaximum.v8f32(<8 x float>)
+declare double @llvm.vector.reduce.fmaximum.v2f64(<2 x double>)
+declare double @llvm.vector.reduce.fmaximum.v4f64(<4 x double>)

diff  --git a/llvm/test/CodeGen/AArch64/vecreduce-fadd.ll b/llvm/test/CodeGen/AArch64/vecreduce-fadd.ll
index 55b140b28bd49..b43b01027dda2 100644
--- a/llvm/test/CodeGen/AArch64/vecreduce-fadd.ll
+++ b/llvm/test/CodeGen/AArch64/vecreduce-fadd.ll
@@ -227,7 +227,7 @@ define float @add_S_init_42(<4 x float> %bin.rdx)  {
 ; CHECK-LABEL: add_S_init_42:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    faddp v0.4s, v0.4s, v0.4s
-; CHECK-NEXT:    mov w8, #1109917696
+; CHECK-NEXT:    mov w8, #1109917696 // =0x42280000
 ; CHECK-NEXT:    fmov s1, w8
 ; CHECK-NEXT:    faddp s0, v0.2s
 ; CHECK-NEXT:    fadd s0, s0, s1

diff  --git a/llvm/test/CodeGen/AArch64/vecreduce-fmax-legalization.ll b/llvm/test/CodeGen/AArch64/vecreduce-fmax-legalization.ll
index 51b60332bf5ab..3df8749d8978c 100644
--- a/llvm/test/CodeGen/AArch64/vecreduce-fmax-legalization.ll
+++ b/llvm/test/CodeGen/AArch64/vecreduce-fmax-legalization.ll
@@ -12,6 +12,7 @@ declare half @llvm.vector.reduce.fmax.v11f16(<11 x half> %a)
 declare float @llvm.vector.reduce.fmax.v3f32(<3 x float> %a)
 declare fp128 @llvm.vector.reduce.fmax.v2f128(<2 x fp128> %a)
 declare float @llvm.vector.reduce.fmax.v16f32(<16 x float> %a)
+declare double @llvm.vector.reduce.fmax.v2f64(<2 x double> %a)
 
 define half @test_v1f16(<1 x half> %a) nounwind {
 ; CHECK-LABEL: test_v1f16:
@@ -131,7 +132,7 @@ define half @test_v11f16(<11 x half> %a) nounwind {
 ; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
 ; CHECK-NOFP-NEXT:    fcsel s1, s2, s16, gt
 ; CHECK-NOFP-NEXT:    ldr h2, [x8, :lo12:.LCPI6_0]
-; CHECK-NOFP-NEXT:    mov w8, #-8388608
+; CHECK-NOFP-NEXT:    mov w8, #-8388608 // =0xff800000
 ; CHECK-NOFP-NEXT:    fcvt h0, s0
 ; CHECK-NOFP-NEXT:    fcvt h1, s1
 ; CHECK-NOFP-NEXT:    fcvt s2, h2
@@ -238,7 +239,7 @@ define half @test_v11f16_ninf(<11 x half> %a) nounwind {
 ; CHECK-NOFP-NEXT:    fmaxnm s0, s0, s1
 ; CHECK-NOFP-NEXT:    fcsel s1, s2, s16, gt
 ; CHECK-NOFP-NEXT:    ldr h2, [x8, :lo12:.LCPI7_0]
-; CHECK-NOFP-NEXT:    mov w8, #57344
+; CHECK-NOFP-NEXT:    mov w8, #57344 // =0xe000
 ; CHECK-NOFP-NEXT:    movk w8, #51071, lsl #16
 ; CHECK-NOFP-NEXT:    fcvt h0, s0
 ; CHECK-NOFP-NEXT:    fcvt h1, s1
@@ -323,7 +324,7 @@ define half @test_v11f16_ninf(<11 x half> %a) nounwind {
 define float @test_v3f32(<3 x float> %a) nounwind {
 ; CHECK-LABEL: test_v3f32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #-8388608
+; CHECK-NEXT:    mov w8, #-8388608 // =0xff800000
 ; CHECK-NEXT:    fmov s1, w8
 ; CHECK-NEXT:    mov v0.s[3], v1.s[0]
 ; CHECK-NEXT:    fmaxnmv s0, v0.4s
@@ -335,7 +336,7 @@ define float @test_v3f32(<3 x float> %a) nounwind {
 define float @test_v3f32_ninf(<3 x float> %a) nounwind {
 ; CHECK-LABEL: test_v3f32_ninf:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #-8388609
+; CHECK-NEXT:    mov w8, #-8388609 // =0xff7fffff
 ; CHECK-NEXT:    fmov s1, w8
 ; CHECK-NEXT:    mov v0.s[3], v1.s[0]
 ; CHECK-NEXT:    fmaxnmv s0, v0.4s
@@ -363,3 +364,12 @@ define float @test_v16f32(<16 x float> %a) nounwind {
   %b = call nnan float @llvm.vector.reduce.fmax.v16f32(<16 x float> %a)
   ret float %b
 }
+
+define double @test_v2f64(<2 x double> %a) nounwind {
+; CHECK-LABEL: test_v2f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxnmp d0, v0.2d
+; CHECK-NEXT:    ret
+  %b = call double @llvm.vector.reduce.fmax.v2f64(<2 x double> %a)
+  ret double %b
+}

diff  --git a/llvm/test/CodeGen/AArch64/vecreduce-fmaximum.ll b/llvm/test/CodeGen/AArch64/vecreduce-fmaximum.ll
index 82454564df68d..1204554294fd1 100644
--- a/llvm/test/CodeGen/AArch64/vecreduce-fmaximum.ll
+++ b/llvm/test/CodeGen/AArch64/vecreduce-fmaximum.ll
@@ -12,6 +12,7 @@ declare half @llvm.vector.reduce.fmaximum.v11f16(<11 x half> %a)
 declare float @llvm.vector.reduce.fmaximum.v3f32(<3 x float> %a)
 declare fp128 @llvm.vector.reduce.fmaximum.v2f128(<2 x fp128> %a)
 declare float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> %a)
+declare double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> %a)
 
 define half @test_v1f16(<1 x half> %a) nounwind {
 ; CHECK-LABEL: test_v1f16:
@@ -222,3 +223,13 @@ define float @test_v16f32(<16 x float> %a) nounwind {
   %b = call float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> %a)
   ret float %b
 }
+
+define double @test_v2f64(<2 x double> %a) nounwind {
+; CHECK-LABEL: test_v2f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov d1, v0.d[1]
+; CHECK-NEXT:    fmax d0, d0, d1
+; CHECK-NEXT:    ret
+  %b = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> %a)
+  ret double %b
+}

diff  --git a/llvm/test/CodeGen/AArch64/vecreduce-fmin-legalization.ll b/llvm/test/CodeGen/AArch64/vecreduce-fmin-legalization.ll
index fade974b07dc7..5e4205855707b 100644
--- a/llvm/test/CodeGen/AArch64/vecreduce-fmin-legalization.ll
+++ b/llvm/test/CodeGen/AArch64/vecreduce-fmin-legalization.ll
@@ -12,6 +12,7 @@ declare half @llvm.vector.reduce.fmin.v11f16(<11 x half> %a)
 declare float @llvm.vector.reduce.fmin.v3f32(<3 x float> %a)
 declare fp128 @llvm.vector.reduce.fmin.v2f128(<2 x fp128> %a)
 declare float @llvm.vector.reduce.fmin.v16f32(<16 x float> %a)
+declare double @llvm.vector.reduce.fmin.v2f64(<2 x double> %a)
 
 define half @test_v1f16(<1 x half> %a) nounwind {
 ; CHECK-LABEL: test_v1f16:
@@ -131,7 +132,7 @@ define half @test_v11f16(<11 x half> %a) nounwind {
 ; CHECK-NOFP-NEXT:    fminnm s0, s0, s1
 ; CHECK-NOFP-NEXT:    fcsel s1, s2, s16, lt
 ; CHECK-NOFP-NEXT:    ldr h2, [x8, :lo12:.LCPI6_0]
-; CHECK-NOFP-NEXT:    mov w8, #2139095040
+; CHECK-NOFP-NEXT:    mov w8, #2139095040 // =0x7f800000
 ; CHECK-NOFP-NEXT:    fcvt h0, s0
 ; CHECK-NOFP-NEXT:    fcvt h1, s1
 ; CHECK-NOFP-NEXT:    fcvt s2, h2
@@ -238,7 +239,7 @@ define half @test_v11f16_ninf(<11 x half> %a) nounwind {
 ; CHECK-NOFP-NEXT:    fminnm s0, s0, s1
 ; CHECK-NOFP-NEXT:    fcsel s1, s2, s16, lt
 ; CHECK-NOFP-NEXT:    ldr h2, [x8, :lo12:.LCPI7_0]
-; CHECK-NOFP-NEXT:    mov w8, #57344
+; CHECK-NOFP-NEXT:    mov w8, #57344 // =0xe000
 ; CHECK-NOFP-NEXT:    movk w8, #18303, lsl #16
 ; CHECK-NOFP-NEXT:    fcvt h0, s0
 ; CHECK-NOFP-NEXT:    fcvt h1, s1
@@ -323,7 +324,7 @@ define half @test_v11f16_ninf(<11 x half> %a) nounwind {
 define float @test_v3f32(<3 x float> %a) nounwind {
 ; CHECK-LABEL: test_v3f32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #2139095040
+; CHECK-NEXT:    mov w8, #2139095040 // =0x7f800000
 ; CHECK-NEXT:    fmov s1, w8
 ; CHECK-NEXT:    mov v0.s[3], v1.s[0]
 ; CHECK-NEXT:    fminnmv s0, v0.4s
@@ -335,7 +336,7 @@ define float @test_v3f32(<3 x float> %a) nounwind {
 define float @test_v3f32_ninf(<3 x float> %a) nounwind {
 ; CHECK-LABEL: test_v3f32_ninf:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #2139095039
+; CHECK-NEXT:    mov w8, #2139095039 // =0x7f7fffff
 ; CHECK-NEXT:    fmov s1, w8
 ; CHECK-NEXT:    mov v0.s[3], v1.s[0]
 ; CHECK-NEXT:    fminnmv s0, v0.4s
@@ -363,3 +364,12 @@ define float @test_v16f32(<16 x float> %a) nounwind {
   %b = call nnan float @llvm.vector.reduce.fmin.v16f32(<16 x float> %a)
   ret float %b
 }
+
+define double @test_v2f64(<2 x double> %a) nounwind {
+; CHECK-LABEL: test_v2f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminnmp d0, v0.2d
+; CHECK-NEXT:    ret
+  %b = call double @llvm.vector.reduce.fmin.v2f64(<2 x double> %a)
+  ret double %b
+}

diff  --git a/llvm/test/CodeGen/AArch64/vecreduce-fminimum.ll b/llvm/test/CodeGen/AArch64/vecreduce-fminimum.ll
new file mode 100644
index 0000000000000..3cf48c9a8ab33
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/vecreduce-fminimum.ll
@@ -0,0 +1,235 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOFP
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon,+fullfp16 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-FP
+
+declare half @llvm.vector.reduce.fminimum.v1f16(<1 x half> %a)
+declare float @llvm.vector.reduce.fminimum.v1f32(<1 x float> %a)
+declare double @llvm.vector.reduce.fminimum.v1f64(<1 x double> %a)
+declare fp128 @llvm.vector.reduce.fminimum.v1f128(<1 x fp128> %a)
+
+declare half @llvm.vector.reduce.fminimum.v4f16(<4 x half> %a)
+declare half @llvm.vector.reduce.fminimum.v11f16(<11 x half> %a)
+declare float @llvm.vector.reduce.fminimum.v3f32(<3 x float> %a)
+declare fp128 @llvm.vector.reduce.fminimum.v2f128(<2 x fp128> %a)
+declare float @llvm.vector.reduce.fminimum.v16f32(<16 x float> %a)
+declare double @llvm.vector.reduce.fminimum.v2f64(<2 x double> %a)
+
+define half @test_v1f16(<1 x half> %a) nounwind {
+; CHECK-LABEL: test_v1f16:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ret
+  %b = call half @llvm.vector.reduce.fminimum.v1f16(<1 x half> %a)
+  ret half %b
+}
+
+define float @test_v1f32(<1 x float> %a) nounwind {
+; CHECK-LABEL: test_v1f32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    // kill: def $s0 killed $s0 killed $q0
+; CHECK-NEXT:    ret
+  %b = call float @llvm.vector.reduce.fminimum.v1f32(<1 x float> %a)
+  ret float %b
+}
+
+define double @test_v1f64(<1 x double> %a) nounwind {
+; CHECK-LABEL: test_v1f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ret
+  %b = call double @llvm.vector.reduce.fminimum.v1f64(<1 x double> %a)
+  ret double %b
+}
+
+define fp128 @test_v1f128(<1 x fp128> %a) nounwind {
+; CHECK-LABEL: test_v1f128:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ret
+  %b = call fp128 @llvm.vector.reduce.fminimum.v1f128(<1 x fp128> %a)
+  ret fp128 %b
+}
+
+define half @test_v4f16(<4 x half> %a) nounwind {
+; CHECK-NOFP-LABEL: test_v4f16:
+; CHECK-NOFP:       // %bb.0:
+; CHECK-NOFP-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NOFP-NEXT:    mov h1, v0.h[1]
+; CHECK-NOFP-NEXT:    fcvt s2, h0
+; CHECK-NOFP-NEXT:    fcvt s1, h1
+; CHECK-NOFP-NEXT:    fmin s1, s2, s1
+; CHECK-NOFP-NEXT:    mov h2, v0.h[2]
+; CHECK-NOFP-NEXT:    mov h0, v0.h[3]
+; CHECK-NOFP-NEXT:    fcvt h1, s1
+; CHECK-NOFP-NEXT:    fcvt s2, h2
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fcvt s1, h1
+; CHECK-NOFP-NEXT:    fmin s1, s1, s2
+; CHECK-NOFP-NEXT:    fcvt h1, s1
+; CHECK-NOFP-NEXT:    fcvt s1, h1
+; CHECK-NOFP-NEXT:    fmin s0, s1, s0
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    ret
+;
+; CHECK-FP-LABEL: test_v4f16:
+; CHECK-FP:       // %bb.0:
+; CHECK-FP-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-FP-NEXT:    mov h1, v0.h[1]
+; CHECK-FP-NEXT:    mov h2, v0.h[2]
+; CHECK-FP-NEXT:    fmin h1, h0, h1
+; CHECK-FP-NEXT:    mov h0, v0.h[3]
+; CHECK-FP-NEXT:    fmin h1, h1, h2
+; CHECK-FP-NEXT:    fmin h0, h1, h0
+; CHECK-FP-NEXT:    ret
+  %b = call half @llvm.vector.reduce.fminimum.v4f16(<4 x half> %a)
+  ret half %b
+}
+
+define half @test_v11f16(<11 x half> %a) nounwind {
+; CHECK-NOFP-LABEL: test_v11f16:
+; CHECK-NOFP:       // %bb.0:
+; CHECK-NOFP-NEXT:    ldr h16, [sp, #8]
+; CHECK-NOFP-NEXT:    fcvt s1, h1
+; CHECK-NOFP-NEXT:    ldr h17, [sp]
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fcvt s2, h2
+; CHECK-NOFP-NEXT:    fcvt s16, h16
+; CHECK-NOFP-NEXT:    fcvt s17, h17
+; CHECK-NOFP-NEXT:    fmin s1, s1, s16
+; CHECK-NOFP-NEXT:    ldr h16, [sp, #16]
+; CHECK-NOFP-NEXT:    fmin s0, s0, s17
+; CHECK-NOFP-NEXT:    fcvt s16, h16
+; CHECK-NOFP-NEXT:    fcvt h1, s1
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt s1, h1
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fmin s1, s2, s16
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt h1, s1
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fcvt s1, h1
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fcvt s1, h3
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fcvt s1, h4
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fcvt s1, h5
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fcvt s1, h6
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fcvt s1, h7
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    fcvt s0, h0
+; CHECK-NOFP-NEXT:    fmin s0, s0, s1
+; CHECK-NOFP-NEXT:    fcvt h0, s0
+; CHECK-NOFP-NEXT:    ret
+;
+; CHECK-FP-LABEL: test_v11f16:
+; CHECK-FP:       // %bb.0:
+; CHECK-FP-NEXT:    // kill: def $h0 killed $h0 def $q0
+; CHECK-FP-NEXT:    // kill: def $h1 killed $h1 def $q1
+; CHECK-FP-NEXT:    // kill: def $h2 killed $h2 def $q2
+; CHECK-FP-NEXT:    // kill: def $h3 killed $h3 def $q3
+; CHECK-FP-NEXT:    // kill: def $h4 killed $h4 def $q4
+; CHECK-FP-NEXT:    mov x8, sp
+; CHECK-FP-NEXT:    // kill: def $h5 killed $h5 def $q5
+; CHECK-FP-NEXT:    // kill: def $h6 killed $h6 def $q6
+; CHECK-FP-NEXT:    // kill: def $h7 killed $h7 def $q7
+; CHECK-FP-NEXT:    mov v0.h[1], v1.h[0]
+; CHECK-FP-NEXT:    movi v1.8h, #124, lsl #8
+; CHECK-FP-NEXT:    mov v0.h[2], v2.h[0]
+; CHECK-FP-NEXT:    ld1 { v1.h }[0], [x8]
+; CHECK-FP-NEXT:    add x8, sp, #8
+; CHECK-FP-NEXT:    mov v0.h[3], v3.h[0]
+; CHECK-FP-NEXT:    ld1 { v1.h }[1], [x8]
+; CHECK-FP-NEXT:    add x8, sp, #16
+; CHECK-FP-NEXT:    mov v0.h[4], v4.h[0]
+; CHECK-FP-NEXT:    ld1 { v1.h }[2], [x8]
+; CHECK-FP-NEXT:    mov v0.h[5], v5.h[0]
+; CHECK-FP-NEXT:    mov v0.h[6], v6.h[0]
+; CHECK-FP-NEXT:    mov v0.h[7], v7.h[0]
+; CHECK-FP-NEXT:    fmin v0.8h, v0.8h, v1.8h
+; CHECK-FP-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-FP-NEXT:    fmin v0.4h, v0.4h, v1.4h
+; CHECK-FP-NEXT:    mov h1, v0.h[1]
+; CHECK-FP-NEXT:    mov h2, v0.h[2]
+; CHECK-FP-NEXT:    fmin h1, h0, h1
+; CHECK-FP-NEXT:    mov h0, v0.h[3]
+; CHECK-FP-NEXT:    fmin h1, h1, h2
+; CHECK-FP-NEXT:    fmin h0, h1, h0
+; CHECK-FP-NEXT:    ret
+  %b = call half @llvm.vector.reduce.fminimum.v11f16(<11 x half> %a)
+  ret half %b
+}
+
+; Neutral element is negative infinity which is chosen for padding the widened
+; vector.
+define float @test_v3f32(<3 x float> %a) nounwind {
+; CHECK-LABEL: test_v3f32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w8, #2139095040 // =0x7f800000
+; CHECK-NEXT:    fmov s1, w8
+; CHECK-NEXT:    mov v0.s[3], v1.s[0]
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    fmin v0.2s, v0.2s, v1.2s
+; CHECK-NEXT:    mov s1, v0.s[1]
+; CHECK-NEXT:    fmin s0, s0, s1
+; CHECK-NEXT:    ret
+  %b = call float @llvm.vector.reduce.fminimum.v3f32(<3 x float> %a)
+  ret float %b
+}
+
+; Neutral element chosen for padding the widened vector is not negative infinity.
+define float @test_v3f32_ninf(<3 x float> %a) nounwind {
+; CHECK-LABEL: test_v3f32_ninf:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w8, #2139095039 // =0x7f7fffff
+; CHECK-NEXT:    fmov s1, w8
+; CHECK-NEXT:    mov v0.s[3], v1.s[0]
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    fmin v0.2s, v0.2s, v1.2s
+; CHECK-NEXT:    mov s1, v0.s[1]
+; CHECK-NEXT:    fmin s0, s0, s1
+; CHECK-NEXT:    ret
+  %b = call ninf float @llvm.vector.reduce.fminimum.v3f32(<3 x float> %a)
+  ret float %b
+}
+
+; Cannot legalize f128. See PR63267 - The underlying fminimum has no default
+; expansion and no libcalls.
+;define fp128 @test_v2f128(<2 x fp128> %a) nounwind {
+;  %b = call fp128 @llvm.vector.reduce.fminimum.v2f128(<2 x fp128> %a)
+;  ret fp128 %b
+;}
+
+define float @test_v16f32(<16 x float> %a) nounwind {
+; CHECK-LABEL: test_v16f32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmin v1.4s, v1.4s, v3.4s
+; CHECK-NEXT:    fmin v0.4s, v0.4s, v2.4s
+; CHECK-NEXT:    fmin v0.4s, v0.4s, v1.4s
+; CHECK-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-NEXT:    fmin v0.2s, v0.2s, v1.2s
+; CHECK-NEXT:    mov s1, v0.s[1]
+; CHECK-NEXT:    fmin s0, s0, s1
+; CHECK-NEXT:    ret
+  %b = call float @llvm.vector.reduce.fminimum.v16f32(<16 x float> %a)
+  ret float %b
+}
+
+define double @test_v2f64(<2 x double> %a) nounwind {
+; CHECK-LABEL: test_v2f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov d1, v0.d[1]
+; CHECK-NEXT:    fmin d0, d0, d1
+; CHECK-NEXT:    ret
+  %b = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> %a)
+  ret double %b
+}


        


More information about the llvm-commits mailing list