//===----------------------------------------------------------------------===//
// Matcher for any binary operator.
//
-template <typename LHS_t, typename RHS_t> struct AnyBinaryOp_match {
+template <typename LHS_t, typename RHS_t, bool Commutable = false>
+struct AnyBinaryOp_match {
LHS_t L;
RHS_t R;
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<BinaryOperator>(V))
- return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
+ return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
+ (Commutable && R.match(I->getOperand(0)) &&
+ L.match(I->getOperand(1)));
return false;
}
};
// Matchers for specific binary operators.
//
-template <typename LHS_t, typename RHS_t, unsigned Opcode>
+template <typename LHS_t, typename RHS_t, unsigned Opcode,
+ bool Commutable = false>
struct BinaryOp_match {
LHS_t L;
RHS_t R;
template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opcode) {
auto *I = cast<BinaryOperator>(V);
- return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
+ return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
+ (Commutable && R.match(I->getOperand(0)) &&
+ L.match(I->getOperand(1)));
}
if (auto *CE = dyn_cast<ConstantExpr>(V))
- return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
- R.match(CE->getOperand(1));
+ return CE->getOpcode() == Opcode &&
+ ((L.match(CE->getOperand(0)) && R.match(CE->getOperand(1))) ||
+ (Commutable && R.match(CE->getOperand(0)) &&
+ L.match(CE->getOperand(1))));
return false;
}
};
// Matchers for CmpInst classes
//
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
+template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+ bool Commutable = false>
struct CmpClass_match {
PredicateTy &Predicate;
LHS_t L;
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V))
- if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
+ if ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) ||
+ (Commutable && R.match(I->getOperand(0)) &&
+ L.match(I->getOperand(1)))) {
Predicate = I->getPredicate();
return true;
}
// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y).
//
-template <typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
+template <typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t,
+ bool Commutable = false>
struct MaxMin_match {
LHS_t L;
RHS_t R;
if (!Pred_t::match(Pred))
return false;
// It does! Bind the operands.
- return L.match(LHS) && R.match(RHS);
+ return (L.match(LHS) && R.match(RHS)) ||
+ (Commutable && R.match(LHS) && L.match(RHS));
}
};
//
/// \brief Matches a BinaryOperator with LHS and RHS in either order.
-template<typename LHS, typename RHS>
-inline match_combine_or<AnyBinaryOp_match<LHS, RHS>,
- AnyBinaryOp_match<RHS, LHS>>
-m_c_BinOp(const LHS &L, const RHS &R) {
- return m_CombineOr(m_BinOp(L, R), m_BinOp(R, L));
+template <typename LHS, typename RHS>
+inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
+ return AnyBinaryOp_match<LHS, RHS, true>(L, R);
}
/// \brief Matches an ICmp with a predicate over LHS and RHS in either order.
/// Does not swap the predicate.
-template<typename LHS, typename RHS>
-inline match_combine_or<CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>,
- CmpClass_match<RHS, LHS, ICmpInst, ICmpInst::Predicate>>
+template <typename LHS, typename RHS>
+inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return m_CombineOr(m_ICmp(Pred, L, R), m_ICmp(Pred, R, L));
+ return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Pred, L,
+ R);
}
/// \brief Matches a Add with LHS and RHS in either order.
-template<typename LHS, typename RHS>
-inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Add>,
- BinaryOp_match<RHS, LHS, Instruction::Add>>
-m_c_Add(const LHS &L, const RHS &R) {
- return m_CombineOr(m_Add(L, R), m_Add(R, L));
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Add, true> m_c_Add(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::Add, true>(L, R);
}
/// \brief Matches a Mul with LHS and RHS in either order.
-template<typename LHS, typename RHS>
-inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Mul>,
- BinaryOp_match<RHS, LHS, Instruction::Mul>>
-m_c_Mul(const LHS &L, const RHS &R) {
- return m_CombineOr(m_Mul(L, R), m_Mul(R, L));
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Mul, true> m_c_Mul(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::Mul, true>(L, R);
}
/// \brief Matches an And with LHS and RHS in either order.
-template<typename LHS, typename RHS>
-inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::And>,
- BinaryOp_match<RHS, LHS, Instruction::And>>
-m_c_And(const LHS &L, const RHS &R) {
- return m_CombineOr(m_And(L, R), m_And(R, L));
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::And, true> m_c_And(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::And, true>(L, R);
}
/// \brief Matches an Or with LHS and RHS in either order.
-template<typename LHS, typename RHS>
-inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Or>,
- BinaryOp_match<RHS, LHS, Instruction::Or>>
-m_c_Or(const LHS &L, const RHS &R) {
- return m_CombineOr(m_Or(L, R), m_Or(R, L));
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Or, true> m_c_Or(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::Or, true>(L, R);
}
/// \brief Matches an Xor with LHS and RHS in either order.
-template<typename LHS, typename RHS>
-inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Xor>,
- BinaryOp_match<RHS, LHS, Instruction::Xor>>
-m_c_Xor(const LHS &L, const RHS &R) {
- return m_CombineOr(m_Xor(L, R), m_Xor(R, L));
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Xor, true> m_c_Xor(const LHS &L,
+ const RHS &R) {
+ return BinaryOp_match<LHS, RHS, Instruction::Xor, true>(L, R);
}
/// Matches an SMin with LHS and RHS in either order.
template <typename LHS, typename RHS>
-inline match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>,
- MaxMin_match<ICmpInst, RHS, LHS, smin_pred_ty>>
+inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty, true>
m_c_SMin(const LHS &L, const RHS &R) {
- return m_CombineOr(m_SMin(L, R), m_SMin(R, L));
+ return MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty, true>(L, R);
}
/// Matches an SMax with LHS and RHS in either order.
template <typename LHS, typename RHS>
-inline match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>,
- MaxMin_match<ICmpInst, RHS, LHS, smax_pred_ty>>
+inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty, true>
m_c_SMax(const LHS &L, const RHS &R) {
- return m_CombineOr(m_SMax(L, R), m_SMax(R, L));
+ return MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty, true>(L, R);
}
/// Matches a UMin with LHS and RHS in either order.
template <typename LHS, typename RHS>
-inline match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>,
- MaxMin_match<ICmpInst, RHS, LHS, umin_pred_ty>>
+inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty, true>
m_c_UMin(const LHS &L, const RHS &R) {
- return m_CombineOr(m_UMin(L, R), m_UMin(R, L));
+ return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty, true>(L, R);
}
/// Matches a UMax with LHS and RHS in either order.
template <typename LHS, typename RHS>
-inline match_combine_or<MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>,
- MaxMin_match<ICmpInst, RHS, LHS, umax_pred_ty>>
+inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>
m_c_UMax(const LHS &L, const RHS &R) {
- return m_CombineOr(m_UMax(L, R), m_UMax(R, L));
+ return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>(L, R);
}
} // end namespace PatternMatch