diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 46372c78263a1..92cb79d54afc2 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1185,7 +1185,7 @@ inline BinaryOp_match m_AShr(const LHS &L, } template + unsigned WrapFlags = 0, bool Commutable = false> struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; @@ -1203,7 +1203,9 @@ struct OverflowingBinaryOp_match { if ((WrapFlags & OverflowingBinaryOperator::NoSignedWrap) && !Op->hasNoSignedWrap()) return false; - return L.match(Op->getOperand(0)) && R.match(Op->getOperand(1)); + return (L.match(Op->getOperand(0)) && R.match(Op->getOperand(1))) || + (Commutable && L.match(Op->getOperand(1)) && + R.match(Op->getOperand(0))); } return false; } @@ -1250,6 +1252,16 @@ m_NUWAdd(const LHS &L, const RHS &R) { OverflowingBinaryOperator::NoUnsignedWrap>( L, R); } + +template +inline OverflowingBinaryOp_match< + LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap, true> +m_c_NUWAdd(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match(L, R); +} + template inline OverflowingBinaryOp_match diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index a0b873de2d586..4d0c2e4220fec 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -948,6 +948,16 @@ TEST_F(PatternMatchTest, OverflowingBinOps) { EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); MatchL = MatchR = nullptr; + + EXPECT_TRUE( + m_c_NUWAdd(m_Specific(L), m_Specific(R)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_TRUE( + m_c_NUWAdd(m_Specific(R), m_Specific(L)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE( + m_c_NUWAdd(m_Specific(R), m_ZeroInt()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE( + m_NUWAdd(m_Specific(R), m_Specific(L)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_TRUE( m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R))); EXPECT_EQ(L, MatchL);