[llvm] 4f22636 - [DAG] Don't detect flippable signs in MinMax matchers (#220527)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 10:46:57 PDT 2026


Author: Luke Lau
Date: 2026-09-23T18:46:50+01:00
New Revision: 4f22636ba6d33280d2609206b281c88a66a65997

URL: https://github.com/llvm/llvm-project/commit/4f22636ba6d33280d2609206b281c88a66a65997
DIFF: https://github.com/llvm/llvm-project/commit/4f22636ba6d33280d2609206b281c88a66a65997.diff

LOG: [DAG] Don't detect flippable signs in MinMax matchers (#220527)

The Min/MaxLike pattern matchers are the only pattern matchers that use
computeKnownBits. They're used to match a smax as a umax if the operands
are known positive and so forth.

However in practice it has no affect on real-world codegen as correlated
value propagation already does this transform earlier in the pipeline,
including for all the tests changed in this PR:
https://llvm.godbolt.org/z/Pr4Ec1xrv

Nothing in the backends will emit a min/max that needs re-transformed in
this way as far as I'm aware.

Removing computeKnownBits from these matchers allows us to remove the
match context in #218372, and saves some compilation time at O3
https://llvm-compile-time-tracker.com/compare.php?from=2f2aa940de68abcdfe4959ddd3b9a0741a7c2a16&to=b771556fb2a7e9c2cb0c853a4a71ea9641e5ede0&stat=instructions:u

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/SDPatternMatch.h
    llvm/test/CodeGen/AArch64/abds.ll
    llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index 18fa8ef12e730..0eb174531cd70 100644
--- a/llvm/include/llvm/CodeGen/SDPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h
@@ -905,10 +905,7 @@ inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) {
 
 template <typename LHS, typename RHS>
 inline auto m_SMinLike(const LHS &L, const RHS &R) {
-  return m_AnyOf(
-      m_MaxMinLike<ISD::SMIN, smin_pred_ty>(L, R),
-      m_MaxMinLike<ISD::UMIN, umin_pred_ty>(m_NonNegative(L), m_NonNegative(R)),
-      m_MaxMinLike<ISD::UMIN, umin_pred_ty>(m_Negative(L), m_Negative(R)));
+  return m_MaxMinLike<ISD::SMIN, smin_pred_ty>(L, R);
 }
 
 template <typename LHS, typename RHS>
@@ -918,10 +915,7 @@ inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) {
 
 template <typename LHS, typename RHS>
 inline auto m_SMaxLike(const LHS &L, const RHS &R) {
-  return m_AnyOf(
-      m_MaxMinLike<ISD::SMAX, smax_pred_ty>(L, R),
-      m_MaxMinLike<ISD::UMAX, umax_pred_ty>(m_NonNegative(L), m_NonNegative(R)),
-      m_MaxMinLike<ISD::UMAX, umax_pred_ty>(m_Negative(L), m_Negative(R)));
+  return m_MaxMinLike<ISD::SMAX, smax_pred_ty>(L, R);
 }
 
 template <typename LHS, typename RHS>
@@ -931,10 +925,7 @@ inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) {
 
 template <typename LHS, typename RHS>
 inline auto m_UMinLike(const LHS &L, const RHS &R) {
-  return m_AnyOf(
-      m_MaxMinLike<ISD::UMIN, umin_pred_ty>(L, R),
-      m_MaxMinLike<ISD::SMIN, smin_pred_ty>(m_NonNegative(L), m_NonNegative(R)),
-      m_MaxMinLike<ISD::SMIN, smin_pred_ty>(m_Negative(L), m_Negative(R)));
+  return m_MaxMinLike<ISD::UMIN, umin_pred_ty>(L, R);
 }
 
 template <typename LHS, typename RHS>
@@ -944,10 +935,7 @@ inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) {
 
 template <typename LHS, typename RHS>
 inline auto m_UMaxLike(const LHS &L, const RHS &R) {
-  return m_AnyOf(
-      m_MaxMinLike<ISD::UMAX, umax_pred_ty>(L, R),
-      m_MaxMinLike<ISD::SMAX, smax_pred_ty>(m_NonNegative(L), m_NonNegative(R)),
-      m_MaxMinLike<ISD::SMAX, smax_pred_ty>(m_Negative(L), m_Negative(R)));
+  return m_MaxMinLike<ISD::UMAX, umax_pred_ty>(L, R);
 }
 
 template <typename LHS, typename RHS>

diff  --git a/llvm/test/CodeGen/AArch64/abds.ll b/llvm/test/CodeGen/AArch64/abds.ll
index d0c390c2f0632..31bd0774bf82d 100644
--- a/llvm/test/CodeGen/AArch64/abds.ll
+++ b/llvm/test/CodeGen/AArch64/abds.ll
@@ -271,8 +271,8 @@ define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind {
   ret i128 %sub
 }
 
-define i8 @abd_sminumax_i8(i8 %a, i8 %b) nounwind {
-; CHECK-LABEL: abd_sminumax_i8:
+define i8 @abd_uminumax_i8(i8 %a, i8 %b) nounwind {
+; CHECK-LABEL: abd_uminumax_i8:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    and w8, w0, #0x7f
 ; CHECK-NEXT:    and w9, w1, #0x7f
@@ -282,14 +282,14 @@ define i8 @abd_sminumax_i8(i8 %a, i8 %b) nounwind {
 entry:
   %a2 = and i8 %a, 127        ; 0x7f
   %b2 = and i8 %b, 127
-  %min = call i8 @llvm.smin.i8(i8 %a2, i8 %b2)
+  %min = call i8 @llvm.umin.i8(i8 %a2, i8 %b2)
   %max = call i8 @llvm.umax.i8(i8 %a2, i8 %b2)
   %d   = sub i8 %max, %min
   ret i8 %d
 }
 
-define i16 @abd_sminumax_i16(i16 %a, i16 %b) nounwind {
-; CHECK-LABEL: abd_sminumax_i16:
+define i16 @abd_uminumax_i16(i16 %a, i16 %b) nounwind {
+; CHECK-LABEL: abd_uminumax_i16:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    and w8, w0, #0x7fff
 ; CHECK-NEXT:    and w9, w1, #0x7fff
@@ -299,14 +299,14 @@ define i16 @abd_sminumax_i16(i16 %a, i16 %b) nounwind {
 entry:
   %a2 = and i16 %a, 32767     ; 0x7fff
   %b2 = and i16 %b, 32767
-  %min = call i16 @llvm.smin.i16(i16 %a2, i16 %b2)
+  %min = call i16 @llvm.umin.i16(i16 %a2, i16 %b2)
   %max = call i16 @llvm.umax.i16(i16 %a2, i16 %b2)
   %d   = sub i16 %max, %min
   ret i16 %d
 }
 
-define i32 @abd_sminumax_i32(i32 %a, i32 %b) nounwind {
-; CHECK-LABEL: abd_sminumax_i32:
+define i32 @abd_uminumax_i32(i32 %a, i32 %b) nounwind {
+; CHECK-LABEL: abd_uminumax_i32:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    and w8, w0, #0x7fffffff
 ; CHECK-NEXT:    and w9, w1, #0x7fffffff
@@ -315,14 +315,14 @@ define i32 @abd_sminumax_i32(i32 %a, i32 %b) nounwind {
 ; CHECK-NEXT:    ret
   %a2 = and i32 %a, 2147483647 ; 0x7fffffff
   %b2 = and i32 %b, 2147483647
-  %min = call i32 @llvm.smin.i32(i32 %a2, i32 %b2)
+  %min = call i32 @llvm.umin.i32(i32 %a2, i32 %b2)
   %max = call i32 @llvm.umax.i32(i32 %a2, i32 %b2)
   %d = sub i32 %max, %min
   ret i32 %d
 }
 
-define i64 @abd_sminumax_i64(i64 %a, i64 %b) nounwind {
-; CHECK-LABEL: abd_sminumax_i64:
+define i64 @abd_uminumax_i64(i64 %a, i64 %b) nounwind {
+; CHECK-LABEL: abd_uminumax_i64:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    and x8, x0, #0x7fffffffffffffff
 ; CHECK-NEXT:    and x9, x1, #0x7fffffffffffffff
@@ -333,7 +333,7 @@ entry:
   %a2 = and i64 %a, 9223372036854775807
   %b2 = and i64 %b, 9223372036854775807
 
-  %min = call i64 @llvm.smin.i64(i64 %a2, i64 %b2)
+  %min = call i64 @llvm.umin.i64(i64 %a2, i64 %b2)
   %max = call i64 @llvm.umax.i64(i64 %a2, i64 %b2)
   %d   = sub i64 %max, %min
   ret i64 %d

diff  --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
index 5b7c1e9ebc24f..3bb0d4121c8d3 100644
--- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
+++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
@@ -195,9 +195,6 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
   auto Idx0 = DAG->getVectorIdxConstant(0, DL);
   auto Idx1 = DAG->getVectorIdxConstant(1, DL);
 
-  SDValue SignBit = DAG->getConstant(0x80000000u, DL, Int32VT);
-  SDValue NoSignBit = DAG->getConstant(0x7fffffffu, DL, Int32VT);
-
   SDValue Op0 = DAG->getCopyFromReg(DAG->getEntryNode(), DL,
                                     Register::index2VirtReg(1), Int32VT);
   SDValue Op1 = DAG->getCopyFromReg(DAG->getEntryNode(), DL,
@@ -208,11 +205,6 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
                                     Register::index2VirtReg(8), Int32VT);
   SDValue Op4 = DAG->getConstant(1, DL, Int32VT);
 
-  SDValue NonNeg0 = DAG->getNode(ISD::AND, DL, Int32VT, Op0, NoSignBit);
-  SDValue NonNeg1 = DAG->getNode(ISD::AND, DL, Int32VT, Op1, NoSignBit);
-  SDValue Neg0 = DAG->getNode(ISD::OR, DL, Int32VT, Op0, SignBit);
-  SDValue Neg1 = DAG->getNode(ISD::OR, DL, Int32VT, Op1, SignBit);
-
   SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1);
   SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0);
   SDValue Mul = DAG->getNode(ISD::MUL, DL, Int32VT, Add, Sub);
@@ -271,42 +263,6 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
   SDValue CCUMinLikeULE = DAG->getSelectCC(DL, Op0, Op1, Op0, Op1, ISD::SETULE);
   SDValue CCUMinLikeUGE = DAG->getSelectCC(DL, Op0, Op1, Op1, Op0, ISD::SETUGE);
 
-  SDValue UMaxNonNeg = DAG->getNode(ISD::UMAX, DL, Int32VT, NonNeg0, NonNeg1);
-  SDValue UMinNonNeg = DAG->getNode(ISD::UMIN, DL, Int32VT, NonNeg0, NonNeg1);
-  SDValue SMaxNonNeg = DAG->getNode(ISD::SMAX, DL, Int32VT, NonNeg0, NonNeg1);
-  SDValue SMinNonNeg = DAG->getNode(ISD::SMIN, DL, Int32VT, NonNeg0, NonNeg1);
-  SDValue UMaxNeg = DAG->getNode(ISD::UMAX, DL, Int32VT, Neg0, Neg1);
-  SDValue UMinNeg = DAG->getNode(ISD::UMIN, DL, Int32VT, Neg0, Neg1);
-  SDValue SMaxNeg = DAG->getNode(ISD::SMAX, DL, Int32VT, Neg0, Neg1);
-  SDValue SMinNeg = DAG->getNode(ISD::SMIN, DL, Int32VT, Neg0, Neg1);
-  SDValue UMaxDiffSign = DAG->getNode(ISD::UMAX, DL, Int32VT, Neg0, NonNeg1);
-  SDValue UMinDiffSign = DAG->getNode(ISD::UMIN, DL, Int32VT, Neg0, NonNeg1);
-  SDValue SMaxDiffSign = DAG->getNode(ISD::SMAX, DL, Int32VT, Neg0, NonNeg1);
-  SDValue SMinDiffSign = DAG->getNode(ISD::SMIN, DL, Int32VT, Neg0, NonNeg1);
-
-  SDValue ICMP_NN_UGT =
-      DAG->getSetCC(DL, MVT::i1, NonNeg0, NonNeg1, ISD::SETUGT);
-  SDValue ICMP_NN_ULT =
-      DAG->getSetCC(DL, MVT::i1, NonNeg0, NonNeg1, ISD::SETULT);
-  SDValue ICMP_NN_GT = DAG->getSetCC(DL, MVT::i1, NonNeg0, NonNeg1, ISD::SETGT);
-  SDValue ICMP_NN_LT = DAG->getSetCC(DL, MVT::i1, NonNeg0, NonNeg1, ISD::SETLT);
-  SDValue ICMP_N_UGT = DAG->getSetCC(DL, MVT::i1, Neg0, Neg1, ISD::SETUGT);
-  SDValue ICMP_N_ULT = DAG->getSetCC(DL, MVT::i1, Neg0, Neg1, ISD::SETULT);
-  SDValue ICMP_N_GT = DAG->getSetCC(DL, MVT::i1, Neg0, Neg1, ISD::SETGT);
-  SDValue ICMP_N_LT = DAG->getSetCC(DL, MVT::i1, Neg0, Neg1, ISD::SETLT);
-  SDValue UMaxLikeNN_UGT =
-      DAG->getSelect(DL, MVT::i32, ICMP_NN_UGT, NonNeg0, NonNeg1);
-  SDValue UMinLikeNN_ULT =
-      DAG->getSelect(DL, MVT::i32, ICMP_NN_ULT, NonNeg0, NonNeg1);
-  SDValue SMaxLikeNN_GT =
-      DAG->getSelect(DL, MVT::i32, ICMP_NN_GT, NonNeg0, NonNeg1);
-  SDValue SMinLikeNN_LT =
-      DAG->getSelect(DL, MVT::i32, ICMP_NN_LT, NonNeg0, NonNeg1);
-  SDValue UMaxLikeN_UGT = DAG->getSelect(DL, MVT::i32, ICMP_N_UGT, Neg0, Neg1);
-  SDValue UMinLikeN_ULT = DAG->getSelect(DL, MVT::i32, ICMP_N_ULT, Neg0, Neg1);
-  SDValue SMaxLikeN_GT = DAG->getSelect(DL, MVT::i32, ICMP_N_GT, Neg0, Neg1);
-  SDValue SMinLikeN_LT = DAG->getSelect(DL, MVT::i32, ICMP_N_LT, Neg0, Neg1);
-
   SDValue SFAdd = DAG->getNode(ISD::STRICT_FADD, DL, {Float32VT, MVT::Other},
                                {DAG->getEntryNode(), Op2, Op2});
 
@@ -414,59 +370,6 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
   EXPECT_TRUE(sd_match(CCUMinLikeULT, m_UMinLike(m_Value(), m_Value())));
   EXPECT_TRUE(sd_match(CCUMinLikeULE, m_UMinLike(m_Value(), m_Value())));
 
-  EXPECT_TRUE(sd_match(UMaxNonNeg, DAG.get(),
-                       m_UMaxLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(UMaxNonNeg, DAG.get(),
-                       m_SMaxLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(UMinNonNeg, DAG.get(),
-                       m_UMinLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(UMinNonNeg, DAG.get(),
-                       m_SMinLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-
-  EXPECT_TRUE(sd_match(SMaxNonNeg, DAG.get(),
-                       m_SMaxLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(SMaxNonNeg, DAG.get(),
-                       m_UMaxLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(SMinNonNeg, DAG.get(),
-                       m_SMinLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(SMinNonNeg, DAG.get(),
-                       m_UMinLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-
-  EXPECT_TRUE(sd_match(UMaxNeg, DAG.get(),
-                       m_UMaxLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(UMaxNeg, DAG.get(),
-                       m_SMaxLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(UMinNeg, DAG.get(),
-                       m_UMinLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(UMinNeg, DAG.get(),
-                       m_SMinLike(m_Specific(Neg0), m_Specific(Neg1))));
-
-  EXPECT_TRUE(sd_match(SMaxNeg, DAG.get(),
-                       m_SMaxLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(SMaxNeg, DAG.get(),
-                       m_UMaxLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(SMinNeg, DAG.get(),
-                       m_SMinLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(SMinNeg, DAG.get(),
-                       m_UMinLike(m_Specific(Neg0), m_Specific(Neg1))));
-
-  EXPECT_TRUE(sd_match(UMaxLikeNN_UGT, DAG.get(),
-                       m_SMaxLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(UMinLikeNN_ULT, DAG.get(),
-                       m_SMinLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(SMaxLikeNN_GT, DAG.get(),
-                       m_UMaxLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(SMinLikeNN_LT, DAG.get(),
-                       m_UMinLike(m_Specific(NonNeg0), m_Specific(NonNeg1))));
-  EXPECT_TRUE(sd_match(UMaxLikeN_UGT, DAG.get(),
-                       m_SMaxLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(UMinLikeN_ULT, DAG.get(),
-                       m_SMinLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(SMaxLikeN_GT, DAG.get(),
-                       m_UMaxLike(m_Specific(Neg0), m_Specific(Neg1))));
-  EXPECT_TRUE(sd_match(SMinLikeN_LT, DAG.get(),
-                       m_UMinLike(m_Specific(Neg0), m_Specific(Neg1))));
-
   EXPECT_FALSE(
       sd_match(UMax, DAG.get(), m_SMaxLike(m_Specific(Op0), m_Specific(Op1))));
   EXPECT_FALSE(
@@ -476,15 +379,6 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) {
   EXPECT_FALSE(
       sd_match(SMin, DAG.get(), m_UMinLike(m_Specific(Op0), m_Specific(Op1))));
 
-  EXPECT_FALSE(sd_match(UMaxDiffSign, DAG.get(),
-                        m_SMaxLike(m_Specific(Neg0), m_Specific(NonNeg1))));
-  EXPECT_FALSE(sd_match(UMinDiffSign, DAG.get(),
-                        m_SMinLike(m_Specific(Neg0), m_Specific(NonNeg1))));
-  EXPECT_FALSE(sd_match(SMaxDiffSign, DAG.get(),
-                        m_UMaxLike(m_Specific(Neg0), m_Specific(NonNeg1))));
-  EXPECT_FALSE(sd_match(SMinDiffSign, DAG.get(),
-                        m_UMinLike(m_Specific(Neg0), m_Specific(NonNeg1))));
-
   SDValue BindVal;
   // By default, it matches any of the results.
   EXPECT_TRUE(sd_match(PartsDiff, m_Sub(m_SpecificOpc(ISD::SMUL_LOHI),


        


More information about the llvm-commits mailing list