[llvm] 404ceba - [AArch64][NEON] Fold insert(zero, extract(X, 0), 0) -> X when X is known to zero lanes 1-N (#213940)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 01:40:09 PDT 2026


Author: CarolineConcatto
Date: 2026-09-10T09:40:04+01:00
New Revision: 404ceba2628b7f925ce650b63e1ea90440927481

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

LOG: [AArch64][NEON] Fold insert(zero, extract(X, 0), 0) -> X when X is known to zero lanes 1-N (#213940)

Add patterns for NEON across-lane reductions whose scalar result
is inserted into lane zero of a zero vector.

This is valid because these instructions place their result in lane zero
and
clear the remaining lanes.

Limit this change to matching input and result vector types. Mixed
vector
sizes and scalar conversions are not part of this PR.

Handle llvm.vector.reduce.add.v2i64 separately because it lowers to
ADDP.
NEON has no equivalent instruction for v2i64 signed or unsigned min/max
reductions, so they cannot use this fold. Double-precision
floating-point
reductions are already handled by pairwise instruction patterns.

Added: 
    llvm/test/CodeGen/AArch64/neon-implicit-zero-filling.ll

Modified: 
    llvm/lib/Target/AArch64/AArch64InstrInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 3b226e9a78105..f09f9c2a2f61e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -8778,6 +8778,34 @@ defm FMAXV   : SIMDFPAcrossLanes<0b01111, 0, "fmaxv", AArch64fmaxv>;
 defm FMINNMV : SIMDFPAcrossLanes<0b01100, 1, "fminnmv", AArch64fminnmv>;
 defm FMINV   : SIMDFPAcrossLanes<0b01111, 1, "fminv", AArch64fminv>;
 
+multiclass SIMDAcrossLanesFPIntrinsic<string acrossLanesOpc,
+                                      SDPatternOperator opNode> {
+  // Reductions have the unused lanes set to zero. Inserting the reduction's
+  // result into lane zero of a zero vector is therefore redundant.
+  let Predicates = [HasFullFP16] in {
+  def : Pat<(v4f16 (vector_insert (v4f16 immAllZerosV),
+                    (f16 (opNode (v4f16 V64:$Rn))), (i64 0))),
+            (v4f16 (SUBREG_TO_REG
+              (!cast<Instruction>(acrossLanesOpc # "v4i16v") V64:$Rn),
+              hsub))>;
+  def : Pat<(v8f16 (vector_insert (v8f16 immAllZerosV),
+                    (f16 (opNode (v8f16 V128:$Rn))), (i64 0))),
+            (v8f16 (SUBREG_TO_REG
+              (!cast<Instruction>(acrossLanesOpc # "v8i16v") V128:$Rn),
+              hsub))>;
+  }
+  def : Pat<(v4f32 (vector_insert (v4f32 immAllZerosV),
+                    (f32 (opNode (v4f32 V128:$Rn))), (i64 0))),
+            (v4f32 (SUBREG_TO_REG
+              (!cast<Instruction>(acrossLanesOpc # "v4i32v") V128:$Rn),
+              ssub))>;
+}
+
+defm : SIMDAcrossLanesFPIntrinsic<"FMAXV", AArch64fmaxv>;
+defm : SIMDAcrossLanesFPIntrinsic<"FMINV", AArch64fminv>;
+defm : SIMDAcrossLanesFPIntrinsic<"FMAXNMV", AArch64fmaxnmv>;
+defm : SIMDAcrossLanesFPIntrinsic<"FMINNMV", AArch64fminnmv>;
+
 multiclass SIMDAcrossLaneLongReductionExt<string Opc, SDPatternOperator ext> {
   def : Pat<(i32 (vector_extract (v8i16 (AArch64uaddv (v8i16 (ext (v8i8 V64:$op))))), (i64 0))),
             (EXTRACT_SUBREG (v8i16 (SUBREG_TO_REG (!cast<Instruction>(Opc#"v8i8v") V64:$op), hsub)), ssub)>;
@@ -8952,7 +8980,38 @@ def : Pat<(i32 (vector_extract (v4i32 (opNode V128:$Rn)), (i64 0))),
             (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn),
             ssub), ssub)>;
 
-}
+// Reductions have the unused lanes set to zero. Inserting the reduction's
+// result into lane zero of a zero vector is therefore redundant.
+def : Pat<(v16i8 (vector_insert immAllZerosV,
+                    (i32 (vector_extract (v16i8 (opNode V128:$Rn)), (i64 0))),
+                    (i64 0))),
+          (v16i8 (SUBREG_TO_REG (!cast<Instruction>(!strconcat(baseOpc, "v16i8v")) V128:$Rn), bsub))>;
+def : Pat<(v8i16 (vector_insert immAllZerosV,
+                    (i32 (vector_extract (v8i16 (opNode V128:$Rn)), (i64 0))),
+                    (i64 0))),
+          (v8i16 (SUBREG_TO_REG (!cast<Instruction>(!strconcat(baseOpc, "v8i16v")) V128:$Rn), hsub))>;
+def : Pat<(v4i32 (vector_insert immAllZerosV,
+                    (i32 (vector_extract (v4i32 (opNode V128:$Rn)), (i64 0))),
+                    (i64 0))),
+          (v4i32 (SUBREG_TO_REG (!cast<Instruction>(!strconcat(baseOpc, "v4i32v")) V128:$Rn), ssub))>;
+
+def : Pat<(v8i8 (vector_insert immAllZerosV,
+                   (i32 (vector_extract (v16i8 (insert_subvector undef,
+                   (v8i8 (opNode V64:$Rn)), (i64 0))), (i64 0))), (i64 0))),
+          (v8i8 (SUBREG_TO_REG (!cast<Instruction>(!strconcat(baseOpc, "v8i8v")) V64:$Rn), bsub))>;
+
+def : Pat<(v4i16 (vector_insert immAllZerosV,
+                    (i32 (vector_extract (v8i16 (insert_subvector undef,
+                    (v4i16 (opNode V64:$Rn)), (i64 0))), (i64 0))), (i64 0))),
+          (v4i16 (SUBREG_TO_REG(!cast<Instruction>(!strconcat(baseOpc, "v4i16v")) V64:$Rn), hsub))>;
+}
+// Reductions have the unused lanes set to zero. Inserting the reduction's
+// result into lane zero of a zero vector is therefore redundant.
+def : Pat<(v2i64 (concat_vectors (v1i64 (extract_subvector (v2i64 ( AArch64uaddv (v2i64 V128:$Rn))), (i64 0))),
+                                 immAllZerosV)),
+          (v2i64 (SUBREG_TO_REG (ADDPv2i64p V128:$Rn), dsub))>;
+
+
 
 multiclass SIMDAcrossLanesSignedIntrinsic<string baseOpc,
                                           SDPatternOperator opNode>

diff  --git a/llvm/test/CodeGen/AArch64/neon-implicit-zero-filling.ll b/llvm/test/CodeGen/AArch64/neon-implicit-zero-filling.ll
new file mode 100644
index 0000000000000..8233426286361
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/neon-implicit-zero-filling.ll
@@ -0,0 +1,400 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+;; The following tests are the LLVM IR of this function. The example uses
+;; vector_reduce_add, but this applies to the other vector reductions as well.
+;vec_sz_out uaddvq_sz_zero_fill(vec_sz_in a) {
+;  return (vec_sz_out){vaddvq_u8(a)};
+;}
+
+
+;; Add reductions
+
+define <8 x i8> @reduce_add_v8i8_zero_fill(<8 x i8> %a) {
+; CHECK-LABEL: reduce_add_v8i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    addv b0, v0.8b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %a)
+  %t2 = insertelement <8 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <8 x i8> %t2
+}
+
+define <16 x i8> @reduce_add_v16i8_zero_fill(<16 x i8> %a) {
+; CHECK-LABEL: reduce_add_v16i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    addv b0, v0.16b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %a)
+  %t2 = insertelement <16 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <16 x i8> %t2
+}
+
+define <4 x i16> @reduce_add_v4i16_zero_fill(<4 x i16> %a) {
+; CHECK-LABEL: reduce_add_v4i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    addv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %a)
+  %t2 = insertelement <4 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <4 x i16> %t2
+}
+
+define <8 x i16> @reduce_add_v8i16_zero_fill(<8 x i16> %a) {
+; CHECK-LABEL: reduce_add_v8i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    addv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %a)
+  %t2 = insertelement <8 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <8 x i16> %t2
+}
+
+define <4 x i32> @reduce_add_v4i32_zero_fill(<4 x i32> %a) {
+; CHECK-LABEL: reduce_add_v4i32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    addv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
+  %t2 = insertelement <4 x i32> zeroinitializer, i32 %t1, i64 0
+  ret <4 x i32> %t2
+}
+
+define <2 x i64> @reduce_add_2i64_zero_fill(<2 x i64> %a) {
+; CHECK-LABEL: reduce_add_2i64_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    addp d0, v0.2d
+; CHECK-NEXT:    ret
+  %t1 = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %a)
+  %t2 = insertelement <2 x i64> zeroinitializer, i64 %t1, i64 0
+  ret <2 x i64> %t2
+}
+
+;; Maximum reductions
+
+define <8 x i8> @reduce_smax_v8i8_zero_fill(<8 x i8> %a) {
+; CHECK-LABEL: reduce_smax_v8i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    smaxv b0, v0.8b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.smax.v8i8(<8 x i8> %a)
+  %t2 = insertelement <8 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <8 x i8> %t2
+}
+
+define <16 x i8> @reduce_smax_v16i8_zero_fill(<16 x i8> %a) {
+; CHECK-LABEL: reduce_smax_v16i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    smaxv b0, v0.16b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> %a)
+  %t2 = insertelement <16 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <16 x i8> %t2
+}
+
+define <4 x i16> @reduce_smax_v4i16_zero_fill(<4 x i16> %a) {
+; CHECK-LABEL: reduce_smax_v4i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    smaxv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.smax.v4i16(<4 x i16> %a)
+  %t2 = insertelement <4 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <4 x i16> %t2
+}
+
+define <8 x i16> @reduce_smax_v8i16_zero_fill(<8 x i16> %a) {
+; CHECK-LABEL: reduce_smax_v8i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    smaxv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> %a)
+  %t2 = insertelement <8 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <8 x i16> %t2
+}
+
+define <4 x i32> @reduce_smax_v4i32_zero_fill(<4 x i32> %a) {
+; CHECK-LABEL: reduce_smax_v4i32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    smaxv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> %a)
+  %t2 = insertelement <4 x i32> zeroinitializer, i32 %t1, i64 0
+  ret <4 x i32> %t2
+}
+
+define <8 x i8> @reduce_umax_v8i8_zero_fill(<8 x i8> %a) {
+; CHECK-LABEL: reduce_umax_v8i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    umaxv b0, v0.8b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.umax.v8i8(<8 x i8> %a)
+  %t2 = insertelement <8 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <8 x i8> %t2
+}
+
+define <16 x i8> @reduce_umax_v16i8_zero_fill(<16 x i8> %a) {
+; CHECK-LABEL: reduce_umax_v16i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    umaxv b0, v0.16b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> %a)
+  %t2 = insertelement <16 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <16 x i8> %t2
+}
+
+define <4 x i16> @reduce_umax_v4i16_zero_fill(<4 x i16> %a) {
+; CHECK-LABEL: reduce_umax_v4i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    umaxv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.umax.v4i16(<4 x i16> %a)
+  %t2 = insertelement <4 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <4 x i16> %t2
+}
+
+define <8 x i16> @reduce_umax_v8i16_zero_fill(<8 x i16> %a) {
+; CHECK-LABEL: reduce_umax_v8i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    umaxv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> %a)
+  %t2 = insertelement <8 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <8 x i16> %t2
+}
+
+define <4 x i32> @reduce_umax_v4i32_zero_fill(<4 x i32> %a) {
+; CHECK-LABEL: reduce_umax_v4i32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    umaxv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %a)
+  %t2 = insertelement <4 x i32> zeroinitializer, i32 %t1, i64 0
+  ret <4 x i32> %t2
+}
+
+define <4 x half> @reduce_fmaximum_v4f16_zero_fill(<4 x half> %a) #0 {
+; CHECK-LABEL: reduce_fmaximum_v4f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fmaximum.v4f16(<4 x half> %a)
+  %t2 = insertelement <4 x half> zeroinitializer, half %t1, i64 0
+  ret <4 x half> %t2
+}
+
+define <8 x half> @reduce_fmaximum_v8f16_zero_fill(<8 x half> %a) #0 {
+; CHECK-LABEL: reduce_fmaximum_v8f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fmaximum.v8f16(<8 x half> %a)
+  %t2 = insertelement <8 x half> zeroinitializer, half %t1, i64 0
+  ret <8 x half> %t2
+}
+
+define <4 x float> @reduce_fmaximum_v4f32_zero_fill(<4 x float> %a) {
+; CHECK-LABEL: reduce_fmaximum_v4f32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> %a)
+  %t2 = insertelement <4 x float> zeroinitializer, float %t1, i64 0
+  ret <4 x float> %t2
+}
+
+define <4 x half> @reduce_fmax_v4f16_zero_fill(<4 x half> %a) #0 {
+; CHECK-LABEL: reduce_fmax_v4f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxnmv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fmax.v4f16(<4 x half> %a)
+  %t2 = insertelement <4 x half> zeroinitializer, half %t1, i64 0
+  ret <4 x half> %t2
+}
+
+define <8 x half> @reduce_fmax_v8f16_zero_fill(<8 x half> %a) #0 {
+; CHECK-LABEL: reduce_fmax_v8f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxnmv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fmax.v8f16(<8 x half> %a)
+  %t2 = insertelement <8 x half> zeroinitializer, half %t1, i64 0
+  ret <8 x half> %t2
+}
+
+define <4 x float> @reduce_fmax_v4f32_zero_fill(<4 x float> %a) {
+; CHECK-LABEL: reduce_fmax_v4f32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmaxnmv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> %a)
+  %t2 = insertelement <4 x float> zeroinitializer, float %t1, i64 0
+  ret <4 x float> %t2
+}
+
+;; Minimum reductions
+
+define <8 x i8> @reduce_smin_v8i8_zero_fill(<8 x i8> %a) {
+; CHECK-LABEL: reduce_smin_v8i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sminv b0, v0.8b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.smin.v8i8(<8 x i8> %a)
+  %t2 = insertelement <8 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <8 x i8> %t2
+}
+
+define <16 x i8> @reduce_smin_v16i8_zero_fill(<16 x i8> %a) {
+; CHECK-LABEL: reduce_smin_v16i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sminv b0, v0.16b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> %a)
+  %t2 = insertelement <16 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <16 x i8> %t2
+}
+
+define <4 x i16> @reduce_smin_v4i16_zero_fill(<4 x i16> %a) {
+; CHECK-LABEL: reduce_smin_v4i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sminv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> %a)
+  %t2 = insertelement <4 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <4 x i16> %t2
+}
+
+define <8 x i16> @reduce_smin_v8i16_zero_fill(<8 x i16> %a) {
+; CHECK-LABEL: reduce_smin_v8i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sminv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> %a)
+  %t2 = insertelement <8 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <8 x i16> %t2
+}
+
+define <4 x i32> @reduce_smin_v4i32_zero_fill(<4 x i32> %a) {
+; CHECK-LABEL: reduce_smin_v4i32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    sminv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> %a)
+  %t2 = insertelement <4 x i32> zeroinitializer, i32 %t1, i64 0
+  ret <4 x i32> %t2
+}
+
+define <8 x i8> @reduce_umin_v8i8_zero_fill(<8 x i8> %a) {
+; CHECK-LABEL: reduce_umin_v8i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    uminv b0, v0.8b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.umin.v8i8(<8 x i8> %a)
+  %t2 = insertelement <8 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <8 x i8> %t2
+}
+
+define <16 x i8> @reduce_umin_v16i8_zero_fill(<16 x i8> %a) {
+; CHECK-LABEL: reduce_umin_v16i8_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    uminv b0, v0.16b
+; CHECK-NEXT:    ret
+  %t1 = call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> %a)
+  %t2 = insertelement <16 x i8> zeroinitializer, i8 %t1, i64 0
+  ret <16 x i8> %t2
+}
+
+define <4 x i16> @reduce_umin_v4i16_zero_fill(<4 x i16> %a) {
+; CHECK-LABEL: reduce_umin_v4i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    uminv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.umin.v4i16(<4 x i16> %a)
+  %t2 = insertelement <4 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <4 x i16> %t2
+}
+
+define <8 x i16> @reduce_umin_v8i16_zero_fill(<8 x i16> %a) {
+; CHECK-LABEL: reduce_umin_v8i16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    uminv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> %a)
+  %t2 = insertelement <8 x i16> zeroinitializer, i16 %t1, i64 0
+  ret <8 x i16> %t2
+}
+
+define <4 x i32> @reduce_umin_v4i32_zero_fill(<4 x i32> %a) {
+; CHECK-LABEL: reduce_umin_v4i32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    uminv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %a)
+  %t2 = insertelement <4 x i32> zeroinitializer, i32 %t1, i64 0
+  ret <4 x i32> %t2
+}
+
+define <4 x half> @reduce_fminimum_v4f16_zero_fill(<4 x half> %a) #0 {
+; CHECK-LABEL: reduce_fminimum_v4f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fminimum.v4f16(<4 x half> %a)
+  %t2 = insertelement <4 x half> zeroinitializer, half %t1, i64 0
+  ret <4 x half> %t2
+}
+
+define <8 x half> @reduce_fminimum_v8f16_zero_fill(<8 x half> %a) #0 {
+; CHECK-LABEL: reduce_fminimum_v8f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fminimum.v8f16(<8 x half> %a)
+  %t2 = insertelement <8 x half> zeroinitializer, half %t1, i64 0
+  ret <8 x half> %t2
+}
+
+define <4 x float> @reduce_fminimum_v4f32_zero_fill(<4 x float> %a) {
+; CHECK-LABEL: reduce_fminimum_v4f32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> %a)
+  %t2 = insertelement <4 x float> zeroinitializer, float %t1, i64 0
+  ret <4 x float> %t2
+}
+
+define <4 x half> @reduce_fmin_v4f16_zero_fill(<4 x half> %a) #0 {
+; CHECK-LABEL: reduce_fmin_v4f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminnmv h0, v0.4h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fmin.v4f16(<4 x half> %a)
+  %t2 = insertelement <4 x half> zeroinitializer, half %t1, i64 0
+  ret <4 x half> %t2
+}
+
+define <8 x half> @reduce_fmin_v8f16_zero_fill(<8 x half> %a) #0 {
+; CHECK-LABEL: reduce_fmin_v8f16_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminnmv h0, v0.8h
+; CHECK-NEXT:    ret
+  %t1 = call half @llvm.vector.reduce.fmin.v8f16(<8 x half> %a)
+  %t2 = insertelement <8 x half> zeroinitializer, half %t1, i64 0
+  ret <8 x half> %t2
+}
+
+define <4 x float> @reduce_fmin_v4f32_zero_fill(<4 x float> %a) {
+; CHECK-LABEL: reduce_fmin_v4f32_zero_fill:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fminnmv s0, v0.4s
+; CHECK-NEXT:    ret
+  %t1 = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> %a)
+  %t2 = insertelement <4 x float> zeroinitializer, float %t1, i64 0
+  ret <4 x float> %t2
+
+}
+
+attributes #0 = { "target-features"="+fullfp16" }


        


More information about the llvm-commits mailing list