[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