[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