[llvm] c80fa23 - [DAG] SDPatternMatch m_Zero/m_One/m_AllOnes have inconsistent undef h… (#147044)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 7 07:04:58 PDT 2025
Author: woruyu
Date: 2025-07-07T15:04:54+01:00
New Revision: c80fa2364beeca4ad75125afa29de3e20b63fbd3
URL: https://github.com/llvm/llvm-project/commit/c80fa2364beeca4ad75125afa29de3e20b63fbd3
DIFF: https://github.com/llvm/llvm-project/commit/c80fa2364beeca4ad75125afa29de3e20b63fbd3.diff
LOG: [DAG] SDPatternMatch m_Zero/m_One/m_AllOnes have inconsistent undef h… (#147044)
### Summary
This PR resolves https://github.com/llvm/llvm-project/issues/146871
This PR resolves https://github.com/llvm/llvm-project/issues/140745
Refactor m_Zero/m_One/m_AllOnes all use struct template function to
match and AllowUndefs=false as default.
Added:
Modified:
llvm/include/llvm/CodeGen/SDPatternMatch.h
llvm/include/llvm/CodeGen/SelectionDAGNodes.h
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h
index 35322c32a8283..7c5cdbbeb0ca8 100644
--- a/llvm/include/llvm/CodeGen/SDPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h
@@ -1100,19 +1100,46 @@ inline SpecificInt_match m_SpecificInt(uint64_t V) {
return SpecificInt_match(APInt(64, V));
}
-inline SpecificInt_match m_Zero() { return m_SpecificInt(0U); }
-inline SpecificInt_match m_One() { return m_SpecificInt(1U); }
+struct Zero_match {
+ bool AllowUndefs;
+
+ explicit Zero_match(bool AllowUndefs) : AllowUndefs(AllowUndefs) {}
+
+ template <typename MatchContext>
+ bool match(const MatchContext &, SDValue N) const {
+ return isZeroOrZeroSplat(N, AllowUndefs);
+ }
+};
+
+struct Ones_match {
+ bool AllowUndefs;
+
+ Ones_match(bool AllowUndefs) : AllowUndefs(AllowUndefs) {}
+
+ template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
+ return isOnesOrOnesSplat(N, AllowUndefs);
+ }
+};
struct AllOnes_match {
+ bool AllowUndefs;
- AllOnes_match() = default;
+ AllOnes_match(bool AllowUndefs) : AllowUndefs(AllowUndefs) {}
template <typename MatchContext> bool match(const MatchContext &, SDValue N) {
- return isAllOnesOrAllOnesSplat(N);
+ return isAllOnesOrAllOnesSplat(N, AllowUndefs);
}
};
-inline AllOnes_match m_AllOnes() { return AllOnes_match(); }
+inline Ones_match m_One(bool AllowUndefs = false) {
+ return Ones_match(AllowUndefs);
+}
+inline Zero_match m_Zero(bool AllowUndefs = false) {
+ return Zero_match(AllowUndefs);
+}
+inline AllOnes_match m_AllOnes(bool AllowUndefs = false) {
+ return AllOnes_match(AllowUndefs);
+}
/// Match true boolean value based on the information provided by
/// TargetLowering.
@@ -1189,7 +1216,7 @@ inline CondCode_match m_SpecificCondCode(ISD::CondCode CC) {
/// Match a negate as a sub(0, v)
template <typename ValTy>
-inline BinaryOpc_match<SpecificInt_match, ValTy> m_Neg(const ValTy &V) {
+inline BinaryOpc_match<Zero_match, ValTy, false> m_Neg(const ValTy &V) {
return m_Sub(m_Zero(), V);
}
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index a3675eecfea3f..5d9937f832396 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -1937,6 +1937,16 @@ LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs = false);
/// Does not permit build vector implicit truncation.
LLVM_ABI bool isAllOnesOrAllOnesSplat(SDValue V, bool AllowUndefs = false);
+/// Return true if the value is a constant 1 integer or a splatted vector of a
+/// constant 1 integer (with no undefs).
+/// Does not permit build vector implicit truncation.
+LLVM_ABI bool isOnesOrOnesSplat(SDValue N, bool AllowUndefs = false);
+
+/// Return true if the value is a constant 0 integer or a splatted vector of a
+/// constant 0 integer (with no undefs).
+/// Does not permit build vector implicit truncation.
+LLVM_ABI bool isZeroOrZeroSplat(SDValue N, bool AllowUndefs = false);
+
/// Return true if \p V is either a integer or FP constant.
inline bool isIntOrFPConstant(SDValue V) {
return isa<ConstantSDNode>(V) || isa<ConstantFPSDNode>(V);
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index a10f9afcf96c3..e7f1fdf10719a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -4280,7 +4280,8 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
return V;
// (A - B) - 1 -> add (xor B, -1), A
- if (sd_match(N, m_Sub(m_OneUse(m_Sub(m_Value(A), m_Value(B))), m_One())))
+ if (sd_match(N, m_Sub(m_OneUse(m_Sub(m_Value(A), m_Value(B))),
+ m_One(/*AllowUndefs=*/true))))
return DAG.getNode(ISD::ADD, DL, VT, A, DAG.getNOT(DL, B, VT));
// Look for:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index a0f4c49de1547..2a8bda55fef04 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -12644,6 +12644,18 @@ bool llvm::isAllOnesOrAllOnesSplat(SDValue N, bool AllowUndefs) {
return C && C->isAllOnes() && C->getValueSizeInBits(0) == BitWidth;
}
+bool llvm::isOnesOrOnesSplat(SDValue N, bool AllowUndefs) {
+ ConstantSDNode *C = isConstOrConstSplat(N, AllowUndefs);
+ return C && APInt::isSameValue(C->getAPIntValue(),
+ APInt(C->getAPIntValue().getBitWidth(), 1));
+}
+
+bool llvm::isZeroOrZeroSplat(SDValue N, bool AllowUndefs) {
+ N = peekThroughBitcasts(N);
+ ConstantSDNode *C = isConstOrConstSplat(N, AllowUndefs, true);
+ return C && C->isZero();
+}
+
HandleSDNode::~HandleSDNode() {
DropOperands();
}
diff --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
index baee2868d2d60..dc531e6013745 100644
--- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
+++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp
@@ -825,3 +825,89 @@ TEST_F(SelectionDAGPatternMatchTest, matchReassociatableOp) {
EXPECT_FALSE(sd_match(
ORS0123, m_ReassociatableOr(m_Value(), m_Value(), m_Value(), m_Value())));
}
+
+TEST_F(SelectionDAGPatternMatchTest, MatchZeroOneAllOnes) {
+ using namespace SDPatternMatch;
+
+ SDLoc DL;
+ EVT VT = EVT::getIntegerVT(Context, 32);
+
+ // Scalar constant 0
+ SDValue Zero = DAG->getConstant(0, DL, VT);
+ EXPECT_TRUE(sd_match(Zero, DAG.get(), llvm::SDPatternMatch::m_Zero()));
+ EXPECT_FALSE(sd_match(Zero, DAG.get(), m_One()));
+ EXPECT_FALSE(sd_match(Zero, DAG.get(), m_AllOnes()));
+
+ // Scalar constant 1
+ SDValue One = DAG->getConstant(1, DL, VT);
+ EXPECT_FALSE(sd_match(One, DAG.get(), m_Zero()));
+ EXPECT_TRUE(sd_match(One, DAG.get(), m_One()));
+ EXPECT_FALSE(sd_match(One, DAG.get(), m_AllOnes()));
+
+ // Scalar constant -1
+ SDValue AllOnes =
+ DAG->getConstant(APInt::getAllOnes(VT.getSizeInBits()), DL, VT);
+ EXPECT_FALSE(sd_match(AllOnes, DAG.get(), m_Zero()));
+ EXPECT_FALSE(sd_match(AllOnes, DAG.get(), m_One()));
+ EXPECT_TRUE(sd_match(AllOnes, DAG.get(), m_AllOnes()));
+
+ EVT VecF32 = EVT::getVectorVT(Context, MVT::f32, 4);
+ EVT VecVT = EVT::getVectorVT(Context, MVT::i32, 4);
+
+ // m_Zero: splat vector of 0 → bitcast
+ {
+ SDValue SplatVal = DAG->getConstant(0, DL, MVT::i32);
+ SDValue VecSplat = DAG->getSplatBuildVector(VecVT, DL, SplatVal);
+ SDValue Bitcasted = DAG->getNode(ISD::BITCAST, DL, VecF32, VecSplat);
+ EXPECT_TRUE(sd_match(Bitcasted, DAG.get(), m_Zero()));
+ }
+
+ // m_One: splat vector of 1 → bitcast
+ {
+ SDValue SplatVal = DAG->getConstant(1, DL, MVT::i32);
+ SDValue VecSplat = DAG->getSplatBuildVector(VecVT, DL, SplatVal);
+ SDValue Bitcasted = DAG->getNode(ISD::BITCAST, DL, VecF32, VecSplat);
+ EXPECT_FALSE(sd_match(Bitcasted, DAG.get(), m_One()));
+ }
+
+ // m_AllOnes: splat vector of -1 → bitcast
+ {
+ SDValue SplatVal = DAG->getConstant(APInt::getAllOnes(32), DL, MVT::i32);
+ SDValue VecSplat = DAG->getSplatBuildVector(VecVT, DL, SplatVal);
+ SDValue Bitcasted = DAG->getNode(ISD::BITCAST, DL, VecF32, VecSplat);
+ EXPECT_TRUE(sd_match(Bitcasted, DAG.get(), m_AllOnes()));
+ }
+
+ // splat vector with one undef → default should NOT match
+ SDValue Undef = DAG->getUNDEF(MVT::i32);
+
+ {
+ // m_Zero: Undef + constant 0
+ SDValue Zero = DAG->getConstant(0, DL, MVT::i32);
+ SmallVector<SDValue, 4> Ops(4, Zero);
+ Ops[2] = Undef;
+ SDValue Vec = DAG->getBuildVector(VecVT, DL, Ops);
+ EXPECT_FALSE(sd_match(Vec, DAG.get(), m_Zero()));
+ EXPECT_TRUE(sd_match(Vec, DAG.get(), m_Zero(true)));
+ }
+
+ {
+ // m_One: Undef + constant 1
+ SDValue One = DAG->getConstant(1, DL, MVT::i32);
+ SmallVector<SDValue, 4> Ops(4, One);
+ Ops[1] = Undef;
+ SDValue Vec = DAG->getBuildVector(VecVT, DL, Ops);
+ EXPECT_FALSE(sd_match(Vec, DAG.get(), m_One()));
+ EXPECT_TRUE(sd_match(Vec, DAG.get(), m_One(true)));
+ }
+
+ {
+ // m_AllOnes: Undef + constant -1
+ SDValue AllOnes = DAG->getConstant(APInt::getAllOnes(32), DL, MVT::i32);
+ SmallVector<SDValue, 4> Ops(4, AllOnes);
+ Ops[0] = Undef;
+ SDValue Vec = DAG->getBuildVector(VecVT, DL, Ops);
+ EXPECT_FALSE(sd_match(Vec, DAG.get(), m_AllOnes()));
+ EXPECT_TRUE(sd_match(Vec, DAG.get(), m_AllOnes(true)));
+ }
+}
More information about the llvm-commits
mailing list