[llvm] [SelectionDAG] Fold constant min/max vector reductions (PR #209190)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 20:06:20 PDT 2026


https://github.com/mygitljf updated https://github.com/llvm/llvm-project/pull/209190

>From feb25b7db006bc12c6c69bb10c73af0f1dd77076 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Mon, 13 Jul 2026 21:58:15 +0800
Subject: [PATCH 1/2] [SelectionDAG] Fold constant min/max vector reductions

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 21 ++++-
 .../rvv/vecreduce-minmax-constant-fold.ll     | 93 +++++++++++++++++++
 2 files changed, 109 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 626803ed92a40..61bd3ea527a8f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -7130,6 +7130,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
   case ISD::CTPOP:
   case ISD::CTLS:
   case ISD::VECREDUCE_ADD:
+  case ISD::VECREDUCE_SMAX:
+  case ISD::VECREDUCE_SMIN:
+  case ISD::VECREDUCE_UMAX:
+  case ISD::VECREDUCE_UMIN:
   case ISD::STEP_VECTOR: {
     SDValue Ops = {N1};
     if (SDValue Fold = FoldConstantArithmetic(Opcode, DL, VT, Ops))
@@ -7802,19 +7806,26 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
     if (Opcode == ISD::BITCAST)
       return SDValue();
 
-    // Constant fold VECREDUCE_ADD with a BUILD_VECTOR of integer constants.
-    if (Opcode == ISD::VECREDUCE_ADD && ISD::isBuildVectorOfConstantSDNodes(N1.getNode())) {
+    // 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) &&
+        ISD::isBuildVectorOfConstantSDNodes(N1.getNode())) {
       unsigned EltBits = N1.getValueType().getScalarSizeInBits();
-      APInt Acc = APInt::getZero(EltBits);
+      std::optional<APInt> Acc;
+      unsigned BaseOpcode = ISD::getVecReduceBaseOpcode(Opcode);
       for (SDValue Elt : N1->op_values()) {
         if (Elt.getOpcode() == ISD::POISON)
           return getPOISON(VT);
         if (Elt.isUndef() || cast<ConstantSDNode>(Elt)->isOpaque())
           return SDValue();
-        Acc += cast<ConstantSDNode>(Elt)->getAPIntValue().trunc(EltBits);
+        APInt Value = cast<ConstantSDNode>(Elt)->getAPIntValue().trunc(EltBits);
+        Acc = Acc ? FoldValue(BaseOpcode, *Acc, Value) : Value;
+        assert(Acc && "Unexpected vector reduction opcode");
       }
+      assert(Acc && "Expected non-empty BUILD_VECTOR");
       EVT EltVT = N1.getValueType().getScalarType();
-      return getAnyExtOrTrunc(getConstant(Acc, DL, EltVT), DL, VT);
+      return getAnyExtOrTrunc(getConstant(*Acc, DL, EltVT), DL, VT);
     }
   }
 
diff --git a/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll b/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll
new file mode 100644
index 0000000000000..57bbcf7920fc3
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll
@@ -0,0 +1,93 @@
+; RUN: llc -mtriple=riscv64 -mattr=+v -global-isel=0 -verify-machineinstrs < %s | FileCheck %s
+
+define i64 @test_const_smax() {
+; CHECK-LABEL: test_const_smax:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 127
+; CHECK-NEXT:    ret
+  %r = call i64 @llvm.vector.reduce.smax.v4i64(<4 x i64> <i64 -128, i64 -1, i64 0, i64 127>)
+  ret i64 %r
+}
+
+define i64 @test_const_smin() {
+; CHECK-LABEL: test_const_smin:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, -128
+; CHECK-NEXT:    ret
+  %r = call i64 @llvm.vector.reduce.smin.v4i64(<4 x i64> <i64 -128, i64 -1, i64 0, i64 127>)
+  ret i64 %r
+}
+
+define i64 @test_const_umax() {
+; CHECK-LABEL: test_const_umax:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, -1
+; CHECK-NEXT:    ret
+  %r = call i64 @llvm.vector.reduce.umax.v4i64(<4 x i64> <i64 -128, i64 -1, i64 0, i64 127>)
+  ret i64 %r
+}
+
+define i64 @test_const_umin() {
+; CHECK-LABEL: test_const_umin:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %r = call i64 @llvm.vector.reduce.umin.v4i64(<4 x i64> <i64 -128, i64 -1, i64 0, i64 127>)
+  ret i64 %r
+}
+
+define i64 @test_const_smax_i8() {
+; CHECK-LABEL: test_const_smax_i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 127
+; CHECK-NEXT:    ret
+  %r = call i8 @llvm.vector.reduce.smax.v4i8(<4 x i8> <i8 -128, i8 -1, i8 0, i8 127>)
+  %ext = sext i8 %r to i64
+  ret i64 %ext
+}
+
+define i64 @test_const_smin_i8() {
+; CHECK-LABEL: test_const_smin_i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, -128
+; CHECK-NEXT:    ret
+  %r = call i8 @llvm.vector.reduce.smin.v4i8(<4 x i8> <i8 -128, i8 -1, i8 0, i8 127>)
+  %ext = sext i8 %r to i64
+  ret i64 %ext
+}
+
+define i64 @test_const_umax_i8() {
+; CHECK-LABEL: test_const_umax_i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 255
+; CHECK-NEXT:    ret
+  %r = call i8 @llvm.vector.reduce.umax.v4i8(<4 x i8> <i8 -128, i8 -1, i8 0, i8 127>)
+  %ext = zext i8 %r to i64
+  ret i64 %ext
+}
+
+define i64 @test_const_umin_i8() {
+; CHECK-LABEL: test_const_umin_i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    ret
+  %r = call i8 @llvm.vector.reduce.umin.v4i8(<4 x i8> <i8 -128, i8 -1, i8 0, i8 127>)
+  %ext = zext i8 %r to i64
+  ret i64 %ext
+}
+
+define i64 @test_nonconst(<4 x i64> %v) {
+; CHECK-LABEL: test_nonconst:
+; CHECK:         vredmax.vs
+; CHECK:         ret
+  %r = call i64 @llvm.vector.reduce.smax.v4i64(<4 x i64> %v)
+  ret i64 %r
+}
+
+define i64 @test_poison() {
+; CHECK-LABEL: test_poison:
+; CHECK-NOT:     vredmax.vs
+; CHECK:         ret
+  %r = call i64 @llvm.vector.reduce.smax.v4i64(<4 x i64> <i64 -128, i64 -1, i64 poison, i64 127>)
+  ret i64 %r
+}

>From 66b51e1b0e6862d650fac5161be22ef3568db110 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Tue, 14 Jul 2026 10:31:05 +0800
Subject: [PATCH 2/2] [RISCV] Simplify vector reduction test invocation

---
 llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll b/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll
index 57bbcf7920fc3..e6231e3eb7f8c 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vecreduce-minmax-constant-fold.ll
@@ -1,4 +1,4 @@
-; RUN: llc -mtriple=riscv64 -mattr=+v -global-isel=0 -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+v < %s | FileCheck %s
 
 define i64 @test_const_smax() {
 ; CHECK-LABEL: test_const_smax:



More information about the llvm-commits mailing list