diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index e3ec7e1764da7..bb3d7fff5c9bc 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -3069,12 +3069,26 @@ m_c_MaxOrMin(const LHS &L, const RHS &R) { m_CombineOr(m_c_UMax(L, R), m_c_UMin(L, R))); } +template +struct CommutativeBinaryIntrinsic_match { + LHS L; + RHS R; + + CommutativeBinaryIntrinsic_match(const LHS &L, const RHS &R) : L(L), R(R) {} + + template bool match(OpTy *V) const { + const auto *II = dyn_cast(V); + if (!II || II->getIntrinsicID() != IntrID) + return false; + return (L.match(II->getArgOperand(0)) && R.match(II->getArgOperand(1))) || + (L.match(II->getArgOperand(1)) && R.match(II->getArgOperand(0))); + } +}; + template -inline match_combine_or::Ty, - typename m_Intrinsic_Ty::Ty> +inline CommutativeBinaryIntrinsic_match m_c_Intrinsic(const T0 &Op0, const T1 &Op1) { - return m_CombineOr(m_Intrinsic(Op0, Op1), - m_Intrinsic(Op1, Op0)); + return CommutativeBinaryIntrinsic_match(Op0, Op1); } /// Matches FAdd with LHS and RHS in either order. diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index 972dac82d3331..1142c559c97f8 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -2657,4 +2657,31 @@ TEST_F(PatternMatchTest, ShiftOrSelf) { EXPECT_EQ(ShAmtC, 0U); } +TEST_F(PatternMatchTest, CommutativeDeferredIntrinsicMatch) { + Value *X = ConstantFP::get(IRB.getDoubleTy(), 1.0); + Value *Y = ConstantFP::get(IRB.getDoubleTy(), 2.0); + + auto CheckMatch = [X, Y](Value *Pattern) { + Value *tX = nullptr, *tY = nullptr; + EXPECT_TRUE( + match(Pattern, m_c_Intrinsic( + m_Value(tX), m_c_Intrinsic( + m_Deferred(tX), m_Value(tY))))); + EXPECT_EQ(tX, X); + EXPECT_EQ(tY, Y); + }; + CheckMatch(IRB.CreateBinaryIntrinsic( + Intrinsic::minimum, X, + IRB.CreateBinaryIntrinsic(Intrinsic::minimum, X, Y))); + CheckMatch(IRB.CreateBinaryIntrinsic( + Intrinsic::minimum, X, + IRB.CreateBinaryIntrinsic(Intrinsic::minimum, Y, X))); + CheckMatch(IRB.CreateBinaryIntrinsic( + Intrinsic::minimum, IRB.CreateBinaryIntrinsic(Intrinsic::minimum, X, Y), + X)); + CheckMatch(IRB.CreateBinaryIntrinsic( + Intrinsic::minimum, IRB.CreateBinaryIntrinsic(Intrinsic::minimum, Y, X), + X)); +} + } // anonymous namespace.