[llvm] [InstCombine] Fold special cases of vector partial reduction add (PR #226714)

via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 26 08:51:41 PDT 2026


https://github.com/Chennesxu created https://github.com/llvm/llvm-project/pull/226714

Extend the constant folding from #212112 to scalable splat constants and combine partial reductions with constant inputs and non-constant accumulators into vector additions.

For fixed-length constant inputs, reuse the existing constant folder and its chosen lane grouping. For scalable constant splats and single-use runtime splats with a constant reduction ratio, compute each lane's input contribution by multiplying the splat value by that ratio. Also fold zero inputs to the accumulator and equal-width operands to an add.

For a single-use nxv16i32 splat with an nxv4i32 accumulator, an AArch64 SVE example lowers to three instructions instead of five, excluding ret.

Nonzero mixed fixed/scalable cases remain unchanged because their reduction ratio depends on vscale.

This implements the zero/splat and constant-input cases from items 1 and 2 of #224350, and adds equal-width and single-use runtime-splat folds from item 3.

>From 2c29fd425da3069cfbb4b6d9869244bb8b229cfe Mon Sep 17 00:00:00 2001
From: Chennes <xuchen359 at gmail.com>
Date: Fri, 18 Sep 2026 21:54:44 +0800
Subject: [PATCH 1/2] [InstCombine] Add tests for vector partial reduction add
 folds

---
 .../InstCombine/vector-partial-reduce-add.ll  | 157 ++++++++++++++++++
 .../InstSimplify/ConstProp/vecreduce.ll       |  54 ++++++
 .../InstSimplify/vector-partial-reduce-add.ll |  43 +++++
 3 files changed, 254 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll
 create mode 100644 llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll

diff --git a/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll b/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll
new file mode 100644
index 0000000000000..d61a59ce94536
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+; RUN: opt < %s -passes=instcombine -use-constant-int-for-fixed-length-splat -use-constant-int-for-scalable-splat -S | FileCheck %s
+
+define <2 x i8> @constant_input(<2 x i8> %acc) {
+;
+; CHECK-LABEL: define {{[^@]+}}@constant_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> <i8 1, i8 2, i8 3, i8 4>)
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> <i8 1, i8 2, i8 3, i8 4>)
+  ret <2 x i8> %r
+}
+
+define <2 x i8> @constant_input_poison(<2 x i8> %acc) {
+;
+; CHECK-LABEL: define {{[^@]+}}@constant_input_poison
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> <i8 1, i8 poison, i8 3, i8 4>)
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> <i8 1, i8 poison, i8 3, i8 4>)
+  ret <2 x i8> %r
+}
+
+define <vscale x 2 x i8> @scalable_constant_input(<vscale x 2 x i8> %acc) {
+;
+; CHECK-LABEL: define {{[^@]+}}@scalable_constant_input
+; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> [[ACC]], <vscale x 8 x i8> splat (i8 3))
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> %acc, <vscale x 8 x i8> splat (i8 3))
+  ret <vscale x 2 x i8> %r
+}
+
+define <2 x i8> @same_width(<2 x i8> %acc, <2 x i8> %input) {
+;
+; CHECK-LABEL: define {{[^@]+}}@same_width
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]], <2 x i8> [[INPUT:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v2i8(<2 x i8> [[ACC]], <2 x i8> [[INPUT]])
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v2i8(<2 x i8> %acc, <2 x i8> %input)
+  ret <2 x i8> %r
+}
+
+define <vscale x 2 x i8> @scalable_same_width(<vscale x 2 x i8> %acc, <vscale x 2 x i8> %input) {
+;
+; CHECK-LABEL: define {{[^@]+}}@scalable_same_width
+; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]], <vscale x 2 x i8> [[INPUT:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv2i8(<vscale x 2 x i8> [[ACC]], <vscale x 2 x i8> [[INPUT]])
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv2i8(<vscale x 2 x i8> %acc, <vscale x 2 x i8> %input)
+  ret <vscale x 2 x i8> %r
+}
+
+define <2 x i8> @splat_input(<2 x i8> %acc, i8 %x) {
+;
+; CHECK-LABEL: define {{[^@]+}}@splat_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]], i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[INS:%.*]] = insertelement <4 x i8> poison, i8 [[X]], i64 0
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i8> [[INS]], <4 x i8> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> [[SPLAT]])
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %ins = insertelement <4 x i8> poison, i8 %x, i32 0
+  %splat = shufflevector <4 x i8> %ins, <4 x i8> poison, <4 x i32> zeroinitializer
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> %splat)
+  ret <2 x i8> %r
+}
+
+define <vscale x 2 x i8> @scalable_splat_input(<vscale x 2 x i8> %acc, i8 %x) {
+;
+; CHECK-LABEL: define {{[^@]+}}@scalable_splat_input
+; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]], i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[INS:%.*]] = insertelement <vscale x 6 x i8> poison, i8 [[X]], i64 0
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <vscale x 6 x i8> [[INS]], <vscale x 6 x i8> poison, <vscale x 6 x i32> zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> [[ACC]], <vscale x 6 x i8> [[SPLAT]])
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %ins = insertelement <vscale x 6 x i8> poison, i8 %x, i32 0
+  %splat = shufflevector <vscale x 6 x i8> %ins, <vscale x 6 x i8> poison, <vscale x 6 x i32> zeroinitializer
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> %acc, <vscale x 6 x i8> %splat)
+  ret <vscale x 2 x i8> %r
+}
+
+define <2 x i1> @splat_input_i1(<2 x i1> %acc, i1 %x) {
+;
+; CHECK-LABEL: define {{[^@]+}}@splat_input_i1
+; CHECK-SAME: (<2 x i1> [[ACC:%.*]], i1 [[X:%.*]]) {
+; CHECK-NEXT:    [[INS:%.*]] = insertelement <4 x i1> poison, i1 [[X]], i64 0
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i1> [[INS]], <4 x i1> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i1> @llvm.vector.partial.reduce.add.v2i1.v4i1(<2 x i1> [[ACC]], <4 x i1> [[SPLAT]])
+; CHECK-NEXT:    ret <2 x i1> [[R]]
+;
+  %ins = insertelement <4 x i1> poison, i1 %x, i32 0
+  %splat = shufflevector <4 x i1> %ins, <4 x i1> poison, <4 x i32> zeroinitializer
+  %r = call <2 x i1> @llvm.vector.partial.reduce.add.v2i1.v4i1(<2 x i1> %acc, <4 x i1> %splat)
+  ret <2 x i1> %r
+}
+
+define <2 x i8> @splat_input_multiuse(<2 x i8> %acc, i8 %x, ptr %p) {
+; CHECK-LABEL: define {{[^@]+}}@splat_input_multiuse
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]], i8 [[X:%.*]], ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[INS:%.*]] = insertelement <4 x i8> poison, i8 [[X]], i64 0
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i8> [[INS]], <4 x i8> poison, <4 x i32> zeroinitializer
+; CHECK-NEXT:    store <4 x i8> [[SPLAT]], ptr [[P]], align 4
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> [[SPLAT]])
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %ins = insertelement <4 x i8> poison, i8 %x, i32 0
+  %splat = shufflevector <4 x i8> %ins, <4 x i8> poison, <4 x i32> zeroinitializer
+  store <4 x i8> %splat, ptr %p
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> %splat)
+  ret <2 x i8> %r
+}
+
+define <2 x i8> @nonconstant_input(<2 x i8> %acc, <4 x i8> %input) {
+;
+; CHECK-LABEL: define {{[^@]+}}@nonconstant_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]], <4 x i8> [[INPUT:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> [[INPUT]])
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> %input)
+  ret <2 x i8> %r
+}
+
+; The reduction ratio depends on vscale, so it cannot be used as a constant.
+define <2 x i8> @mixed_constant_input(<2 x i8> %acc) {
+;
+; CHECK-LABEL: define {{[^@]+}}@mixed_constant_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> [[ACC]], <vscale x 4 x i8> splat (i8 3))
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> %acc, <vscale x 4 x i8> splat (i8 3))
+  ret <2 x i8> %r
+}
+
+define <2 x i8> @mixed_splat_input(<2 x i8> %acc, i8 %x) {
+;
+; CHECK-LABEL: define {{[^@]+}}@mixed_splat_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]], i8 [[X:%.*]]) {
+; CHECK-NEXT:    [[INS:%.*]] = insertelement <vscale x 4 x i8> poison, i8 [[X]], i64 0
+; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <vscale x 4 x i8> [[INS]], <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> [[ACC]], <vscale x 4 x i8> [[SPLAT]])
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %ins = insertelement <vscale x 4 x i8> poison, i8 %x, i32 0
+  %splat = shufflevector <vscale x 4 x i8> %ins, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> %acc, <vscale x 4 x i8> %splat)
+  ret <2 x i8> %r
+}
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll b/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll
index 6c2ee928d7c0e..7d8f176975c5f 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll
@@ -1029,3 +1029,57 @@ define <2 x i8> @partial_reduce_add_wrap() {
   <4 x i8> <i8 1, i8 1, i8 2, i8 4>)
   ret <2 x i8> %x
 }
+
+define <vscale x 2 x i8> @partial_reduce_add_scalable_zero() {
+; CHECK-LABEL: @partial_reduce_add_scalable_zero(
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> zeroinitializer)
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> zeroinitializer)
+  ret <vscale x 2 x i8> %r
+}
+
+define <vscale x 2 x i8> @partial_reduce_add_scalable_splat() {
+; CHECK-LABEL: @partial_reduce_add_scalable_splat(
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> splat (i8 3), <vscale x 6 x i8> splat (i8 5))
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> splat (i8 3), <vscale x 6 x i8> splat (i8 5))
+  ret <vscale x 2 x i8> %r
+}
+
+define <vscale x 2 x i8> @partial_reduce_add_scalable_wrap() {
+; CHECK-LABEL: @partial_reduce_add_scalable_wrap(
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> splat (i8 127), <vscale x 8 x i8> splat (i8 127))
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> splat (i8 127), <vscale x 8 x i8> splat (i8 127))
+  ret <vscale x 2 x i8> %r
+}
+
+define <vscale x 2 x i1> @partial_reduce_add_scalable_i1() {
+; CHECK-LABEL: @partial_reduce_add_scalable_i1(
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i1> @llvm.vector.partial.reduce.add.nxv2i1.nxv4i1(<vscale x 2 x i1> splat (i1 true), <vscale x 4 x i1> splat (i1 true))
+; CHECK-NEXT:    ret <vscale x 2 x i1> [[R]]
+;
+  %r = call <vscale x 2 x i1> @llvm.vector.partial.reduce.add.nxv2i1.nxv4i1(<vscale x 2 x i1> splat (i1 true), <vscale x 4 x i1> splat (i1 true))
+  ret <vscale x 2 x i1> %r
+}
+
+define <vscale x 2 x i8> @partial_reduce_add_scalable_poison() {
+; CHECK-LABEL: @partial_reduce_add_scalable_poison(
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> poison)
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> poison)
+  ret <vscale x 2 x i8> %r
+}
+
+define <2 x i8> @partial_reduce_add_mixed_nonzero() {
+; CHECK-LABEL: @partial_reduce_add_mixed_nonzero(
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> <i8 1, i8 2>, <vscale x 4 x i8> splat (i8 3))
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> <i8 1, i8 2>, <vscale x 4 x i8> splat (i8 3))
+  ret <2 x i8> %r
+}
diff --git a/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll b/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll
new file mode 100644
index 0000000000000..6e393ced10b36
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+; RUN: opt < %s -passes=instsimplify -use-constant-int-for-fixed-length-splat -use-constant-int-for-scalable-splat -S | FileCheck %s
+
+define <2 x i8> @zero_input(<2 x i8> %acc) {
+; CHECK-LABEL: define {{[^@]+}}@zero_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> zeroinitializer)
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> zeroinitializer)
+  ret <2 x i8> %r
+}
+
+define <vscale x 2 x i8> @scalable_zero_input(<vscale x 2 x i8> %acc) {
+; CHECK-LABEL: define {{[^@]+}}@scalable_zero_input
+; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> [[ACC]], <vscale x 4 x i8> zeroinitializer)
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> %acc, <vscale x 4 x i8> zeroinitializer)
+  ret <vscale x 2 x i8> %r
+}
+
+define <2 x i8> @mixed_zero_input(<2 x i8> %acc) {
+; CHECK-LABEL: define {{[^@]+}}@mixed_zero_input
+; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> [[ACC]], <vscale x 4 x i8> zeroinitializer)
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> %acc, <vscale x 4 x i8> zeroinitializer)
+  ret <2 x i8> %r
+}
+
+define <vscale x 2 x i8> @scalable_nonzero_input(<vscale x 2 x i8> %acc) {
+; CHECK-LABEL: define {{[^@]+}}@scalable_nonzero_input
+; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> [[ACC]], <vscale x 4 x i8> splat (i8 1))
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+;
+  %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> %acc, <vscale x 4 x i8> splat (i8 1))
+  ret <vscale x 2 x i8> %r
+}

>From 754b027e820242b66655ffcb9a7f3e3b87a493cb Mon Sep 17 00:00:00 2001
From: Chennes <xuchen359 at gmail.com>
Date: Fri, 18 Sep 2026 21:54:46 +0800
Subject: [PATCH 2/2] [InstCombine] Fold special cases of vector partial
 reduction add

Extend the constant folding from #212112 to scalable splats, and reuse it
to reduce constant inputs with a non-constant accumulator. Separate the
constant reduction from the accumulator using an ordinary vector add.

Fold zero inputs to the accumulator, equal-width operands to a vector add,
and single-use non-constant splats using scalar multiplication by the ratio.
For matching scalable vector types, the vscale factors cancel. Keep
nonzero mixed fixed/scalable cases unchanged because their ratio is not
constant.

Related to #224350.
---
 llvm/lib/Analysis/ConstantFolding.cpp         | 26 ++++++++++++++
 llvm/lib/Analysis/InstructionSimplify.cpp     |  4 +++
 .../InstCombine/InstCombineCalls.cpp          | 34 +++++++++++++++++++
 .../InstCombine/vector-partial-reduce-add.ll  | 29 ++++++++--------
 .../InstSimplify/ConstProp/vecreduce.ll       | 18 ++++------
 .../InstSimplify/vector-partial-reduce-add.ll |  9 ++---
 6 files changed, 87 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index b09f348a3b30a..ea7f3a2af7efe 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -2431,6 +2431,30 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
 static Constant *constantFoldVectorPartialReduceAdd(Constant *Acc,
                                                     Constant *Input,
                                                     const DataLayout &DL) {
+  if (Input->isNullValue())
+    return Acc;
+
+  if (auto *AccTy = dyn_cast<ScalableVectorType>(Acc->getType())) {
+    auto *InputTy = dyn_cast<ScalableVectorType>(Input->getType());
+    Constant *Splat = Input->getSplatValue();
+    if (!InputTy || !Splat)
+      return nullptr;
+
+    // The vscale factors cancel, so each result lane accumulates a constant
+    // number of input elements.
+    unsigned Ratio = InputTy->getMinNumElements() / AccTy->getMinNumElements();
+    Constant *Sum = ConstantFoldBinaryOpOperands(
+        Instruction::Mul, Splat,
+        ConstantInt::get(Splat->getType(), Ratio, /*IsSigned=*/false,
+                         /*ImplicitTrunc=*/true),
+        DL);
+    if (!Sum)
+      return nullptr;
+    return ConstantFoldBinaryOpOperands(
+        Instruction::Add, Acc,
+        ConstantVector::getSplat(AccTy->getElementCount(), Sum), DL);
+  }
+
   auto *AccTy = cast<FixedVectorType>(Acc->getType());
   // A fixed result type does not guarantee a fixed input type.
   auto *InputTy = dyn_cast<FixedVectorType>(Input->getType());
@@ -4589,6 +4613,8 @@ static Constant *ConstantFoldScalableVectorCall(
     ArrayRef<Constant *> Operands, const DataLayout &DL,
     const TargetLibraryInfo *TLI, const CallBase *Call) {
   switch (IntrinsicID) {
+  case Intrinsic::vector_partial_reduce_add:
+    return constantFoldVectorPartialReduceAdd(Operands[0], Operands[1], DL);
   case Intrinsic::aarch64_sve_convert_from_svbool: {
     Constant *Src = Operands[0];
     if (!Src->isNullValue())
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 4e91cb44c7a18..941e254e15fa6 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6952,6 +6952,10 @@ static Value *simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
                                       const SimplifyQuery &Q) {
   unsigned BitWidth = ReturnType->getScalarSizeInBits();
   switch (IID) {
+  case Intrinsic::vector_partial_reduce_add:
+    if (match(Op1, m_Zero()))
+      return Op0;
+    break;
   case Intrinsic::get_active_lane_mask: {
     if (match(Op1, m_Zero()))
       return ConstantInt::getFalse(ReturnType);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 7fae7b8cea710..2afeb1e869e23 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -24,6 +24,7 @@
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/Loads.h"
 #include "llvm/Analysis/MemoryBuiltins.h"
@@ -4227,6 +4228,39 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     }
     break;
   }
+  case Intrinsic::vector_partial_reduce_add: {
+    Value *Acc = II->getArgOperand(0);
+    Value *Input = II->getArgOperand(1);
+    if (Acc->getType() == Input->getType())
+      return BinaryOperator::CreateAdd(Acc, Input);
+
+    // Separate the accumulator so the constant input can be reduced using
+    // the same grouping as a fully constant partial reduction.
+    if (auto *C = dyn_cast<Constant>(Input)) {
+      Constant *Zero = Constant::getNullValue(Acc->getType());
+      if (Constant *Sum =
+              ConstantFoldCall(II, II->getCalledFunction(), {Zero, C}, &TLI))
+        return BinaryOperator::CreateAdd(Acc, Sum);
+    }
+
+    ElementCount AccEC = cast<VectorType>(Acc->getType())->getElementCount();
+    ElementCount InputEC =
+        cast<VectorType>(Input->getType())->getElementCount();
+    // A fixed accumulator and scalable input have a vscale-dependent ratio.
+    if (AccEC.isScalable() != InputEC.isScalable())
+      break;
+
+    // Avoid creating an additional splat when the input has other uses.
+    if (Value *Splat = Input->hasOneUse() ? getSplatValue(Input) : nullptr) {
+      unsigned Ratio = InputEC.getKnownMinValue() / AccEC.getKnownMinValue();
+      Value *Sum = Builder.CreateMul(
+          Splat, ConstantInt::get(Splat->getType(), Ratio, /*IsSigned=*/false,
+                                  /*ImplicitTrunc=*/true));
+      return BinaryOperator::CreateAdd(Acc,
+                                       Builder.CreateVectorSplat(AccEC, Sum));
+    }
+    break;
+  }
   case Intrinsic::vector_reduce_or:
   case Intrinsic::vector_reduce_and: {
     // Canonicalize logical or/and reductions:
diff --git a/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll b/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll
index d61a59ce94536..a8fa6b1f3dfb5 100644
--- a/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll
+++ b/llvm/test/Transforms/InstCombine/vector-partial-reduce-add.ll
@@ -6,7 +6,7 @@ define <2 x i8> @constant_input(<2 x i8> %acc) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@constant_input
 ; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> <i8 1, i8 2, i8 3, i8 4>)
+; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[ACC]], <i8 4, i8 6>
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> <i8 1, i8 2, i8 3, i8 4>)
@@ -17,7 +17,7 @@ define <2 x i8> @constant_input_poison(<2 x i8> %acc) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@constant_input_poison
 ; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> <i8 1, i8 poison, i8 3, i8 4>)
+; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[ACC]], <i8 4, i8 poison>
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> <i8 1, i8 poison, i8 3, i8 4>)
@@ -28,7 +28,7 @@ define <vscale x 2 x i8> @scalable_constant_input(<vscale x 2 x i8> %acc) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@scalable_constant_input
 ; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> [[ACC]], <vscale x 8 x i8> splat (i8 3))
+; CHECK-NEXT:    [[R:%.*]] = add <vscale x 2 x i8> [[ACC]], splat (i8 12)
 ; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> %acc, <vscale x 8 x i8> splat (i8 3))
@@ -39,7 +39,7 @@ define <2 x i8> @same_width(<2 x i8> %acc, <2 x i8> %input) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@same_width
 ; CHECK-SAME: (<2 x i8> [[ACC:%.*]], <2 x i8> [[INPUT:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v2i8(<2 x i8> [[ACC]], <2 x i8> [[INPUT]])
+; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[ACC]], [[INPUT]]
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v2i8(<2 x i8> %acc, <2 x i8> %input)
@@ -50,7 +50,7 @@ define <vscale x 2 x i8> @scalable_same_width(<vscale x 2 x i8> %acc, <vscale x
 ;
 ; CHECK-LABEL: define {{[^@]+}}@scalable_same_width
 ; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]], <vscale x 2 x i8> [[INPUT:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv2i8(<vscale x 2 x i8> [[ACC]], <vscale x 2 x i8> [[INPUT]])
+; CHECK-NEXT:    [[R:%.*]] = add <vscale x 2 x i8> [[ACC]], [[INPUT]]
 ; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv2i8(<vscale x 2 x i8> %acc, <vscale x 2 x i8> %input)
@@ -61,9 +61,10 @@ define <2 x i8> @splat_input(<2 x i8> %acc, i8 %x) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@splat_input
 ; CHECK-SAME: (<2 x i8> [[ACC:%.*]], i8 [[X:%.*]]) {
-; CHECK-NEXT:    [[INS:%.*]] = insertelement <4 x i8> poison, i8 [[X]], i64 0
-; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i8> [[INS]], <4 x i8> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> [[SPLAT]])
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[X]], 1
+; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <2 x i8> poison, i8 [[TMP1]], i64 0
+; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <2 x i8> [[DOTSPLATINSERT]], <2 x i8> poison, <2 x i32> zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = add <2 x i8> [[ACC]], [[DOTSPLAT]]
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %ins = insertelement <4 x i8> poison, i8 %x, i32 0
@@ -76,9 +77,10 @@ define <vscale x 2 x i8> @scalable_splat_input(<vscale x 2 x i8> %acc, i8 %x) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@scalable_splat_input
 ; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]], i8 [[X:%.*]]) {
-; CHECK-NEXT:    [[INS:%.*]] = insertelement <vscale x 6 x i8> poison, i8 [[X]], i64 0
-; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <vscale x 6 x i8> [[INS]], <vscale x 6 x i8> poison, <vscale x 6 x i32> zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> [[ACC]], <vscale x 6 x i8> [[SPLAT]])
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i8 [[X]], 3
+; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 2 x i8> poison, i8 [[TMP1]], i64 0
+; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <vscale x 2 x i8> [[DOTSPLATINSERT]], <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer
+; CHECK-NEXT:    [[R:%.*]] = add <vscale x 2 x i8> [[ACC]], [[DOTSPLAT]]
 ; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
 ;
   %ins = insertelement <vscale x 6 x i8> poison, i8 %x, i32 0
@@ -91,10 +93,7 @@ define <2 x i1> @splat_input_i1(<2 x i1> %acc, i1 %x) {
 ;
 ; CHECK-LABEL: define {{[^@]+}}@splat_input_i1
 ; CHECK-SAME: (<2 x i1> [[ACC:%.*]], i1 [[X:%.*]]) {
-; CHECK-NEXT:    [[INS:%.*]] = insertelement <4 x i1> poison, i1 [[X]], i64 0
-; CHECK-NEXT:    [[SPLAT:%.*]] = shufflevector <4 x i1> [[INS]], <4 x i1> poison, <4 x i32> zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i1> @llvm.vector.partial.reduce.add.v2i1.v4i1(<2 x i1> [[ACC]], <4 x i1> [[SPLAT]])
-; CHECK-NEXT:    ret <2 x i1> [[R]]
+; CHECK-NEXT:    ret <2 x i1> [[ACC]]
 ;
   %ins = insertelement <4 x i1> poison, i1 %x, i32 0
   %splat = shufflevector <4 x i1> %ins, <4 x i1> poison, <4 x i32> zeroinitializer
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll b/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll
index 7d8f176975c5f..353c19d4c28f1 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll
@@ -969,8 +969,7 @@ define <4 x i32> @partial_reduce_add_nonconstant_input(<16 x i32> %input) {
 
 define <4 x i32> @partial_reduce_add_mixed_fixed_scalable() {
 ; CHECK-LABEL: @partial_reduce_add_mixed_fixed_scalable(
-; CHECK-NEXT:    [[X:%.*]] = call <4 x i32> @llvm.vector.partial.reduce.add.v4i32.nxv8i32(<4 x i32> zeroinitializer, <vscale x 8 x i32> zeroinitializer)
-; CHECK-NEXT:    ret <4 x i32> [[X]]
+; CHECK-NEXT:    ret <4 x i32> zeroinitializer
 ;
   %x = call <4 x i32> @llvm.vector.partial.reduce.add.v4i32.nxv8i32(
   <4 x i32> zeroinitializer, <vscale x 8 x i32> zeroinitializer)
@@ -1032,8 +1031,7 @@ define <2 x i8> @partial_reduce_add_wrap() {
 
 define <vscale x 2 x i8> @partial_reduce_add_scalable_zero() {
 ; CHECK-LABEL: @partial_reduce_add_scalable_zero(
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> zeroinitializer)
-; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+; CHECK-NEXT:    ret <vscale x 2 x i8> splat (i8 3)
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> zeroinitializer)
   ret <vscale x 2 x i8> %r
@@ -1041,8 +1039,7 @@ define <vscale x 2 x i8> @partial_reduce_add_scalable_zero() {
 
 define <vscale x 2 x i8> @partial_reduce_add_scalable_splat() {
 ; CHECK-LABEL: @partial_reduce_add_scalable_splat(
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> splat (i8 3), <vscale x 6 x i8> splat (i8 5))
-; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+; CHECK-NEXT:    ret <vscale x 2 x i8> splat (i8 18)
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv6i8(<vscale x 2 x i8> splat (i8 3), <vscale x 6 x i8> splat (i8 5))
   ret <vscale x 2 x i8> %r
@@ -1050,8 +1047,7 @@ define <vscale x 2 x i8> @partial_reduce_add_scalable_splat() {
 
 define <vscale x 2 x i8> @partial_reduce_add_scalable_wrap() {
 ; CHECK-LABEL: @partial_reduce_add_scalable_wrap(
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> splat (i8 127), <vscale x 8 x i8> splat (i8 127))
-; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+; CHECK-NEXT:    ret <vscale x 2 x i8> splat (i8 123)
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv8i8(<vscale x 2 x i8> splat (i8 127), <vscale x 8 x i8> splat (i8 127))
   ret <vscale x 2 x i8> %r
@@ -1059,8 +1055,7 @@ define <vscale x 2 x i8> @partial_reduce_add_scalable_wrap() {
 
 define <vscale x 2 x i1> @partial_reduce_add_scalable_i1() {
 ; CHECK-LABEL: @partial_reduce_add_scalable_i1(
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i1> @llvm.vector.partial.reduce.add.nxv2i1.nxv4i1(<vscale x 2 x i1> splat (i1 true), <vscale x 4 x i1> splat (i1 true))
-; CHECK-NEXT:    ret <vscale x 2 x i1> [[R]]
+; CHECK-NEXT:    ret <vscale x 2 x i1> splat (i1 true)
 ;
   %r = call <vscale x 2 x i1> @llvm.vector.partial.reduce.add.nxv2i1.nxv4i1(<vscale x 2 x i1> splat (i1 true), <vscale x 4 x i1> splat (i1 true))
   ret <vscale x 2 x i1> %r
@@ -1068,8 +1063,7 @@ define <vscale x 2 x i1> @partial_reduce_add_scalable_i1() {
 
 define <vscale x 2 x i8> @partial_reduce_add_scalable_poison() {
 ; CHECK-LABEL: @partial_reduce_add_scalable_poison(
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> poison)
-; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+; CHECK-NEXT:    ret <vscale x 2 x i8> poison
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> splat (i8 3), <vscale x 4 x i8> poison)
   ret <vscale x 2 x i8> %r
diff --git a/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll b/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll
index 6e393ced10b36..60db23a26df9a 100644
--- a/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll
+++ b/llvm/test/Transforms/InstSimplify/vector-partial-reduce-add.ll
@@ -5,8 +5,7 @@
 define <2 x i8> @zero_input(<2 x i8> %acc) {
 ; CHECK-LABEL: define {{[^@]+}}@zero_input
 ; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> [[ACC]], <4 x i8> zeroinitializer)
-; CHECK-NEXT:    ret <2 x i8> [[R]]
+; CHECK-NEXT:    ret <2 x i8> [[ACC]]
 ;
   %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.v4i8(<2 x i8> %acc, <4 x i8> zeroinitializer)
   ret <2 x i8> %r
@@ -15,8 +14,7 @@ define <2 x i8> @zero_input(<2 x i8> %acc) {
 define <vscale x 2 x i8> @scalable_zero_input(<vscale x 2 x i8> %acc) {
 ; CHECK-LABEL: define {{[^@]+}}@scalable_zero_input
 ; CHECK-SAME: (<vscale x 2 x i8> [[ACC:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> [[ACC]], <vscale x 4 x i8> zeroinitializer)
-; CHECK-NEXT:    ret <vscale x 2 x i8> [[R]]
+; CHECK-NEXT:    ret <vscale x 2 x i8> [[ACC]]
 ;
   %r = call <vscale x 2 x i8> @llvm.vector.partial.reduce.add.nxv2i8.nxv4i8(<vscale x 2 x i8> %acc, <vscale x 4 x i8> zeroinitializer)
   ret <vscale x 2 x i8> %r
@@ -25,8 +23,7 @@ define <vscale x 2 x i8> @scalable_zero_input(<vscale x 2 x i8> %acc) {
 define <2 x i8> @mixed_zero_input(<2 x i8> %acc) {
 ; CHECK-LABEL: define {{[^@]+}}@mixed_zero_input
 ; CHECK-SAME: (<2 x i8> [[ACC:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> [[ACC]], <vscale x 4 x i8> zeroinitializer)
-; CHECK-NEXT:    ret <2 x i8> [[R]]
+; CHECK-NEXT:    ret <2 x i8> [[ACC]]
 ;
   %r = call <2 x i8> @llvm.vector.partial.reduce.add.v2i8.nxv4i8(<2 x i8> %acc, <vscale x 4 x i8> zeroinitializer)
   ret <2 x i8> %r



More information about the llvm-commits mailing list