[llvm] aeda9ae - [SelectionDAG] Fold VECREDUCE_AND/OR/XOR of a constant BUILD_VECTOR (#210883)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 21 04:04:11 PDT 2026
Author: Ankit Kumar Tiwari
Date: 2026-07-21T11:04:05Z
New Revision: aeda9aee7d81c0cb877de15452434121c1b95115
URL: https://github.com/llvm/llvm-project/commit/aeda9aee7d81c0cb877de15452434121c1b95115
DIFF: https://github.com/llvm/llvm-project/commit/aeda9aee7d81c0cb877de15452434121c1b95115.diff
LOG: [SelectionDAG] Fold VECREDUCE_AND/OR/XOR of a constant BUILD_VECTOR (#210883)
Follows up on #207560 and #210126
Adds constant folding for `ISD::VECREDUCE_AND`, `ISD::VECREDUCE_OR`, and
`ISD::VECREDUCE_XOR` in SelectionDAG::FoldConstantArithmetic when the
input is a BUILD_VECTOR of integer constants. Does not fold undef/poison
elements.
Fixes #209108
Added:
llvm/test/CodeGen/RISCV/rvv/vecreduce-and-constant-fold.ll
llvm/test/CodeGen/RISCV/rvv/vecreduce-or-constant-fold.ll
llvm/test/CodeGen/RISCV/rvv/vecreduce-xor-constant-fold.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index d2eb3a1ea65de..cb2ec929c942d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -7141,6 +7141,9 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
case ISD::VECREDUCE_UMAX:
case ISD::VECREDUCE_UMIN:
case ISD::VECREDUCE_MUL:
+ case ISD::VECREDUCE_AND:
+ case ISD::VECREDUCE_OR:
+ case ISD::VECREDUCE_XOR:
case ISD::STEP_VECTOR: {
SDValue Ops = {N1};
if (SDValue Fold = FoldConstantArithmetic(Opcode, DL, VT, Ops))
@@ -7837,7 +7840,9 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
// Constant fold integer vector reductions with constant BUILD_VECTORs.
if ((Opcode == ISD::VECREDUCE_ADD || Opcode == ISD::VECREDUCE_SMAX ||
Opcode == ISD::VECREDUCE_SMIN || Opcode == ISD::VECREDUCE_UMAX ||
- Opcode == ISD::VECREDUCE_UMIN || Opcode == ISD::VECREDUCE_MUL) &&
+ Opcode == ISD::VECREDUCE_UMIN || Opcode == ISD::VECREDUCE_MUL ||
+ Opcode == ISD::VECREDUCE_OR || Opcode == ISD::VECREDUCE_XOR ||
+ Opcode == ISD::VECREDUCE_AND) &&
ISD::isBuildVectorOfConstantSDNodes(N1.getNode())) {
unsigned EltBits = N1.getValueType().getScalarSizeInBits();
unsigned BaseOpcode = ISD::getVecReduceBaseOpcode(Opcode);
diff --git a/llvm/test/CodeGen/RISCV/rvv/vecreduce-and-constant-fold.ll b/llvm/test/CodeGen/RISCV/rvv/vecreduce-and-constant-fold.ll
new file mode 100644
index 0000000000000..a53165328bfad
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/vecreduce-and-constant-fold.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+v < %s | FileCheck %s
+
+define i32 @test_and_const() {
+; CHECK-LABEL: test_and_const:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 3
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> <i32 -1, i32 15, i32 7, i32 3>)
+ ret i32 %r
+}
+
+define i32 @test_and_const_wide() {
+; CHECK-LABEL: test_and_const_wide:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.and.v8i32(<8 x i32> <i32 10, i32 20, i32 30, i32 40, i32 50, i32 60, i32 70, i32 80>)
+ ret i32 %r
+}
+
+define i32 @test_and_nonconst(<4 x i32> %v) {
+; CHECK-LABEL: test_and_nonconst:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT: vredand.vs v8, v8, v8
+; CHECK-NEXT: vmv.x.s a0, v8
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %v)
+ ret i32 %r
+}
+
+define i32 @test_and_poison() {
+; CHECK-LABEL: test_and_poison:
+; CHECK: # %bb.0:
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> <i32 -1, i32 15, i32 poison, i32 3>)
+ ret i32 %r
+}
+
+define i32 @test_and_undef() {
+; CHECK-LABEL: test_and_undef:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lui a0, %hi(.LCPI4_0)
+; CHECK-NEXT: addi a0, a0, %lo(.LCPI4_0)
+; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT: vle32.v v8, (a0)
+; CHECK-NEXT: vredand.vs v8, v8, v8
+; CHECK-NEXT: vmv.x.s a0, v8
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> <i32 -1, i32 15, i32 undef, i32 3>)
+ ret i32 %r
+}
diff --git a/llvm/test/CodeGen/RISCV/rvv/vecreduce-or-constant-fold.ll b/llvm/test/CodeGen/RISCV/rvv/vecreduce-or-constant-fold.ll
new file mode 100644
index 0000000000000..4b3114527534e
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/vecreduce-or-constant-fold.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+v < %s | FileCheck %s
+
+define i32 @test_or_const() {
+; CHECK-LABEL: test_or_const:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, -1
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> <i32 1, i32 -2, i32 4, i32 8>)
+ ret i32 %r
+}
+
+define i32 @test_or_const_wide() {
+; CHECK-LABEL: test_or_const_wide:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.or.v8i32(<8 x i32> <i32 10, i32 20, i32 30, i32 40, i32 50, i32 60, i32 70, i32 80>)
+ ret i32 %r
+}
+
+define i32 @test_or_nonconst(<4 x i32> %v) {
+; CHECK-LABEL: test_or_nonconst:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT: vredor.vs v8, v8, v8
+; CHECK-NEXT: vmv.x.s a0, v8
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %v)
+ ret i32 %r
+}
+
+define i32 @test_or_poison() {
+; CHECK-LABEL: test_or_poison:
+; CHECK: # %bb.0:
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> <i32 1, i32 -2, i32 poison, i32 8>)
+ ret i32 %r
+}
+
+define i32 @test_or_undef() {
+; CHECK-LABEL: test_or_undef:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lui a0, %hi(.LCPI4_0)
+; CHECK-NEXT: addi a0, a0, %lo(.LCPI4_0)
+; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT: vle32.v v8, (a0)
+; CHECK-NEXT: vredor.vs v8, v8, v8
+; CHECK-NEXT: vmv.x.s a0, v8
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> <i32 1, i32 2, i32 undef, i32 -8>)
+ ret i32 %r
+}
diff --git a/llvm/test/CodeGen/RISCV/rvv/vecreduce-xor-constant-fold.ll b/llvm/test/CodeGen/RISCV/rvv/vecreduce-xor-constant-fold.ll
new file mode 100644
index 0000000000000..79b6a463263cf
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/vecreduce-xor-constant-fold.ll
@@ -0,0 +1,55 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+v < %s | FileCheck %s
+
+define i32 @test_xor_const() {
+; CHECK-LABEL: test_xor_const:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, -13
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> <i32 1, i32 -2, i32 4, i32 8>)
+ ret i32 %r
+}
+
+define i32 @test_xor_const_wide() {
+; CHECK-LABEL: test_xor_const_wide:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a0, 48
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.xor.v8i32(<8 x i32> <i32 10, i32 20, i32 30, i32 40, i32 50, i32 60, i32 70, i32 80>)
+ ret i32 %r
+}
+
+define i32 @test_xor_nonconst(<4 x i32> %v) {
+; CHECK-LABEL: test_xor_nonconst:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT: vmv.s.x v9, zero
+; CHECK-NEXT: vredxor.vs v8, v8, v9
+; CHECK-NEXT: vmv.x.s a0, v8
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> %v)
+ ret i32 %r
+}
+
+define i32 @test_xor_poison() {
+; CHECK-LABEL: test_xor_poison:
+; CHECK: # %bb.0:
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> <i32 1, i32 -2, i32 poison, i32 8>)
+ ret i32 %r
+}
+
+define i32 @test_xor_undef() {
+; CHECK-LABEL: test_xor_undef:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT: vmv.s.x v8, zero
+; CHECK-NEXT: lui a0, %hi(.LCPI4_0)
+; CHECK-NEXT: addi a0, a0, %lo(.LCPI4_0)
+; CHECK-NEXT: vle32.v v9, (a0)
+; CHECK-NEXT: vredxor.vs v8, v9, v8
+; CHECK-NEXT: vmv.x.s a0, v8
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.vector.reduce.xor.v4i32(<4 x i32> <i32 1, i32 2, i32 undef, i32 -8>)
+ ret i32 %r
+}
More information about the llvm-commits
mailing list