diff options
Diffstat (limited to 'include/llvm/IR/PatternMatch.h')
-rw-r--r-- | include/llvm/IR/PatternMatch.h | 155 |
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); } //===----------------------------------------------------------------------===// |