summaryrefslogtreecommitdiff
path: root/include/llvm/IR/PatternMatch.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR/PatternMatch.h')
-rw-r--r--include/llvm/IR/PatternMatch.h155
1 files changed, 140 insertions, 15 deletions
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index 0f03d7cc56b8..2851b24c05ae 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -88,6 +88,25 @@ inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
/// Match an arbitrary Constant and ignore it.
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
+/// Match an arbitrary basic block value and ignore it.
+inline class_match<BasicBlock> m_BasicBlock() {
+ return class_match<BasicBlock>();
+}
+
+/// Inverting matcher
+template <typename Ty> struct match_unless {
+ Ty M;
+
+ match_unless(const Ty &Matcher) : M(Matcher) {}
+
+ template <typename ITy> bool match(ITy *V) { return !M.match(V); }
+};
+
+/// Match if the inner matcher does *NOT* match.
+template <typename Ty> inline match_unless<Ty> m_Unless(const Ty &M) {
+ return match_unless<Ty>(M);
+}
+
/// Matching combinators
template <typename LTy, typename RTy> struct match_combine_or {
LTy L;
@@ -300,6 +319,15 @@ template <typename Predicate> struct cstfp_pred_ty : public Predicate {
//
///////////////////////////////////////////////////////////////////////////////
+struct is_any_apint {
+ bool isValue(const APInt &C) { return true; }
+};
+/// Match an integer or vector with any integral constant.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_any_apint> m_AnyIntegralConstant() {
+ return cst_pred_ty<is_any_apint>();
+}
+
struct is_all_ones {
bool isValue(const APInt &C) { return C.isAllOnesValue(); }
};
@@ -388,6 +416,18 @@ inline api_pred_ty<is_power2> m_Power2(const APInt *&V) {
return V;
}
+struct is_negated_power2 {
+ bool isValue(const APInt &C) { return (-C).isPowerOf2(); }
+};
+/// Match a integer or vector negated power-of-2.
+/// For vectors, this includes constants with undefined elements.
+inline cst_pred_ty<is_negated_power2> m_NegatedPower2() {
+ return cst_pred_ty<is_negated_power2>();
+}
+inline api_pred_ty<is_negated_power2> m_NegatedPower2(const APInt *&V) {
+ return V;
+}
+
struct is_power2_or_zero {
bool isValue(const APInt &C) { return !C || C.isPowerOf2(); }
};
@@ -528,6 +568,12 @@ inline bind_ty<Constant> m_Constant(Constant *&C) { return C; }
/// Match a ConstantFP, capturing the value if we match.
inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; }
+/// Match a basic block value, capturing it if we match.
+inline bind_ty<BasicBlock> m_BasicBlock(BasicBlock *&V) { return V; }
+inline bind_ty<const BasicBlock> m_BasicBlock(const BasicBlock *&V) {
+ return V;
+}
+
/// Match a specified Value*.
struct specificval_ty {
const Value *Val;
@@ -597,11 +643,11 @@ struct bind_const_intval_ty {
};
/// Match a specified integer value or vector of all elements of that
-// value.
+/// value.
struct specific_intval {
- uint64_t Val;
+ APInt Val;
- specific_intval(uint64_t V) : Val(V) {}
+ specific_intval(APInt V) : Val(std::move(V)) {}
template <typename ITy> bool match(ITy *V) {
const auto *CI = dyn_cast<ConstantInt>(V);
@@ -609,18 +655,50 @@ struct specific_intval {
if (const auto *C = dyn_cast<Constant>(V))
CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue());
- return CI && CI->getValue() == Val;
+ return CI && APInt::isSameValue(CI->getValue(), Val);
}
};
/// Match a specific integer value or vector with all elements equal to
/// the value.
-inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); }
+inline specific_intval m_SpecificInt(APInt V) {
+ return specific_intval(std::move(V));
+}
+
+inline specific_intval m_SpecificInt(uint64_t V) {
+ return m_SpecificInt(APInt(64, V));
+}
/// Match a ConstantInt and bind to its value. This does not match
/// ConstantInts wider than 64-bits.
inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; }
+/// Match a specified basic block value.
+struct specific_bbval {
+ BasicBlock *Val;
+
+ specific_bbval(BasicBlock *Val) : Val(Val) {}
+
+ template <typename ITy> bool match(ITy *V) {
+ const auto *BB = dyn_cast<BasicBlock>(V);
+ return BB && BB == Val;
+ }
+};
+
+/// Match a specific basic block value.
+inline specific_bbval m_SpecificBB(BasicBlock *BB) {
+ return specific_bbval(BB);
+}
+
+/// A commutative-friendly version of m_Specific().
+inline deferredval_ty<BasicBlock> m_Deferred(BasicBlock *const &BB) {
+ return BB;
+}
+inline deferredval_ty<const BasicBlock>
+m_Deferred(const BasicBlock *const &BB) {
+ return BB;
+}
+
//===----------------------------------------------------------------------===//
// Matcher for any binary operator.
//
@@ -968,6 +1046,12 @@ struct is_idiv_op {
}
};
+struct is_irem_op {
+ bool isOpType(unsigned Opcode) {
+ return Opcode == Instruction::SRem || Opcode == Instruction::URem;
+ }
+};
+
/// Matches shift operations.
template <typename LHS, typename RHS>
inline BinOpPred_match<LHS, RHS, is_shift_op> m_Shift(const LHS &L,
@@ -1003,6 +1087,13 @@ inline BinOpPred_match<LHS, RHS, is_idiv_op> m_IDiv(const LHS &L,
return BinOpPred_match<LHS, RHS, is_idiv_op>(L, R);
}
+/// Matches integer remainder operations.
+template <typename LHS, typename RHS>
+inline BinOpPred_match<LHS, RHS, is_irem_op> m_IRem(const LHS &L,
+ const RHS &R) {
+ return BinOpPred_match<LHS, RHS, is_irem_op>(L, R);
+}
+
//===----------------------------------------------------------------------===//
// Class that matches exact binary ops.
//
@@ -1210,6 +1301,12 @@ inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::Trunc>(Op);
}
+template <typename OpTy>
+inline match_combine_or<CastClass_match<OpTy, Instruction::Trunc>, OpTy>
+m_TruncOrSelf(const OpTy &Op) {
+ return m_CombineOr(m_Trunc(Op), Op);
+}
+
/// Matches SExt.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) {
@@ -1223,12 +1320,33 @@ inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
}
template <typename OpTy>
+inline match_combine_or<CastClass_match<OpTy, Instruction::ZExt>, OpTy>
+m_ZExtOrSelf(const OpTy &Op) {
+ return m_CombineOr(m_ZExt(Op), Op);
+}
+
+template <typename OpTy>
+inline match_combine_or<CastClass_match<OpTy, Instruction::SExt>, OpTy>
+m_SExtOrSelf(const OpTy &Op) {
+ return m_CombineOr(m_SExt(Op), Op);
+}
+
+template <typename OpTy>
inline match_combine_or<CastClass_match<OpTy, Instruction::ZExt>,
CastClass_match<OpTy, Instruction::SExt>>
m_ZExtOrSExt(const OpTy &Op) {
return m_CombineOr(m_ZExt(Op), m_SExt(Op));
}
+template <typename OpTy>
+inline match_combine_or<
+ match_combine_or<CastClass_match<OpTy, Instruction::ZExt>,
+ CastClass_match<OpTy, Instruction::SExt>>,
+ OpTy>
+m_ZExtOrSExtOrSelf(const OpTy &Op) {
+ return m_CombineOr(m_ZExtOrSExt(Op), Op);
+}
+
/// Matches UIToFP.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
@@ -1274,27 +1392,34 @@ struct br_match {
inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); }
-template <typename Cond_t> struct brc_match {
+template <typename Cond_t, typename TrueBlock_t, typename FalseBlock_t>
+struct brc_match {
Cond_t Cond;
- BasicBlock *&T, *&F;
+ TrueBlock_t T;
+ FalseBlock_t F;
- brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f)
+ brc_match(const Cond_t &C, const TrueBlock_t &t, const FalseBlock_t &f)
: Cond(C), T(t), F(f) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *BI = dyn_cast<BranchInst>(V))
- if (BI->isConditional() && Cond.match(BI->getCondition())) {
- T = BI->getSuccessor(0);
- F = BI->getSuccessor(1);
- return true;
- }
+ if (BI->isConditional() && Cond.match(BI->getCondition()))
+ return T.match(BI->getSuccessor(0)) && F.match(BI->getSuccessor(1));
return false;
}
};
template <typename Cond_t>
-inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
- return brc_match<Cond_t>(C, T, F);
+inline brc_match<Cond_t, bind_ty<BasicBlock>, bind_ty<BasicBlock>>
+m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
+ return brc_match<Cond_t, bind_ty<BasicBlock>, bind_ty<BasicBlock>>(
+ C, m_BasicBlock(T), m_BasicBlock(F));
+}
+
+template <typename Cond_t, typename TrueBlock_t, typename FalseBlock_t>
+inline brc_match<Cond_t, TrueBlock_t, FalseBlock_t>
+m_Br(const Cond_t &C, const TrueBlock_t &T, const FalseBlock_t &F) {
+ return brc_match<Cond_t, TrueBlock_t, FalseBlock_t>(C, T, F);
}
//===----------------------------------------------------------------------===//