Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions llvm/include/llvm/IR/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <Intrinsic::ID IntrID, typename LHS, typename RHS>
struct CommutativeBinaryIntrinsic_match {
LHS L;
RHS R;

CommutativeBinaryIntrinsic_match(const LHS &L, const RHS &R) : L(L), R(R) {}

template <typename OpTy> bool match(OpTy *V) const {
const auto *II = dyn_cast<IntrinsicInst>(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 <Intrinsic::ID IntrID, typename T0, typename T1>
inline match_combine_or<typename m_Intrinsic_Ty<T0, T1>::Ty,
typename m_Intrinsic_Ty<T1, T0>::Ty>
inline CommutativeBinaryIntrinsic_match<IntrID, T0, T1>
m_c_Intrinsic(const T0 &Op0, const T1 &Op1) {
return m_CombineOr(m_Intrinsic<IntrID>(Op0, Op1),
m_Intrinsic<IntrID>(Op1, Op0));
return CommutativeBinaryIntrinsic_match<IntrID, T0, T1>(Op0, Op1);
}

/// Matches FAdd with LHS and RHS in either order.
Expand Down
27 changes: 27 additions & 0 deletions llvm/unittests/IR/PatternMatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Intrinsic::minimum>(
m_Value(tX), m_c_Intrinsic<Intrinsic::minimum>(
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.