HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Pie
|
9.0.0_r8
下载
查看原文件
收藏
根目录
prebuilts
clang
host
linux-x86
clang-4579689
include
llvm
IR
PatternMatch.h
//===- PatternMatch.h - Match on the LLVM IR --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file provides a simple and efficient mechanism for performing general // tree-based pattern matches on the LLVM IR. The power of these routines is // that it allows you to write concise patterns that are expressive and easy to // understand. The other major advantage of this is that it allows you to // trivially capture/bind elements in the pattern to variables. For example, // you can do something like this: // // Value *Exp = ... // Value *X, *Y; ConstantInt *C1, *C2; // (X & C1) | (Y & C2) // if (match(Exp, m_Or(m_And(m_Value(X), m_ConstantInt(C1)), // m_And(m_Value(Y), m_ConstantInt(C2))))) { // ... Pattern is matched and variables are bound ... // } // // This is primarily useful to things like the instruction combiner, but can // also be useful for static analysis tools or code generators. // //===----------------------------------------------------------------------===// #ifndef LLVM_IR_PATTERNMATCH_H #define LLVM_IR_PATTERNMATCH_H #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include
namespace llvm { namespace PatternMatch { template
bool match(Val *V, const Pattern &P) { return const_cast
(P).match(V); } template
struct OneUse_match { SubPattern_t SubPattern; OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} template
bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); } }; template
inline OneUse_match
m_OneUse(const T &SubPattern) { return SubPattern; } template
struct class_match { template
bool match(ITy *V) { return isa
(V); } }; /// \brief Match an arbitrary value and ignore it. inline class_match
m_Value() { return class_match
(); } /// \brief Match an arbitrary binary operation and ignore it. inline class_match
m_BinOp() { return class_match
(); } /// \brief Matches any compare instruction and ignore it. inline class_match
m_Cmp() { return class_match
(); } /// \brief Match an arbitrary ConstantInt and ignore it. inline class_match
m_ConstantInt() { return class_match
(); } /// \brief Match an arbitrary undef constant. inline class_match
m_Undef() { return class_match
(); } /// \brief Match an arbitrary Constant and ignore it. inline class_match
m_Constant() { return class_match
(); } /// Matching combinators template
struct match_combine_or { LTy L; RTy R; match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} template
bool match(ITy *V) { if (L.match(V)) return true; if (R.match(V)) return true; return false; } }; template
struct match_combine_and { LTy L; RTy R; match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} template
bool match(ITy *V) { if (L.match(V)) if (R.match(V)) return true; return false; } }; /// Combine two pattern matchers matching L || R template
inline match_combine_or
m_CombineOr(const LTy &L, const RTy &R) { return match_combine_or
(L, R); } /// Combine two pattern matchers matching L && R template
inline match_combine_and
m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and
(L, R); } struct match_zero { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isNullValue(); return false; } }; /// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } struct match_neg_zero { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isNegativeZeroValue(); return false; } }; /// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero but not positive /// zero inline match_neg_zero m_NegZero() { return match_neg_zero(); } struct match_any_zero { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isZeroValue(); return false; } }; /// \brief - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero and positive zero inline match_any_zero m_AnyZero() { return match_any_zero(); } struct match_nan { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isNaN(); return false; } }; /// Match an arbitrary NaN constant. This includes quiet and signalling nans. inline match_nan m_NaN() { return match_nan(); } struct match_one { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isOneValue(); return false; } }; /// \brief Match an integer 1 or a vector with all elements equal to 1. inline match_one m_One() { return match_one(); } struct match_all_ones { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isAllOnesValue(); return false; } }; /// \brief Match an integer or vector with all bits set to true. inline match_all_ones m_AllOnes() { return match_all_ones(); } struct match_sign_mask { template
bool match(ITy *V) { if (const auto *C = dyn_cast
(V)) return C->isMinSignedValue(); return false; } }; /// \brief Match an integer or vector with only the sign bit(s) set. inline match_sign_mask m_SignMask() { return match_sign_mask(); } struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} template
bool match(ITy *V) { if (auto *CI = dyn_cast
(V)) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) if (const auto *C = dyn_cast
(V)) if (auto *CI = dyn_cast_or_null
(C->getSplatValue())) { Res = &CI->getValue(); return true; } return false; } }; // Either constexpr if or renaming ConstantFP::getValueAPF to // ConstantFP::getValue is needed to do it via single template // function for both apint/apfloat. struct apfloat_match { const APFloat *&Res; apfloat_match(const APFloat *&R) : Res(R) {} template
bool match(ITy *V) { if (auto *CI = dyn_cast
(V)) { Res = &CI->getValueAPF(); return true; } if (V->getType()->isVectorTy()) if (const auto *C = dyn_cast
(V)) if (auto *CI = dyn_cast_or_null
(C->getSplatValue())) { Res = &CI->getValueAPF(); return true; } return false; } }; /// \brief Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } /// \brief Match a ConstantFP or splatted ConstantVector, binding the /// specified pointer to the contained APFloat. inline apfloat_match m_APFloat(const APFloat *&Res) { return Res; } template
struct constantint_match { template
bool match(ITy *V) { if (const auto *CI = dyn_cast
(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) return CIV == static_cast
(Val); // If Val is negative, and CI is shorter than it, truncate to the right // number of bits. If it is larger, then we have to sign extend. Just // compare their negated values. return -CIV == -Val; } return false; } }; /// \brief Match a ConstantInt with a specific value. template
inline constantint_match
m_ConstantInt() { return constantint_match
(); } /// \brief This helper class is used to match scalar and vector constants that /// satisfy a specified predicate. template
struct cst_pred_ty : public Predicate { template
bool match(ITy *V) { if (const auto *CI = dyn_cast
(V)) return this->isValue(CI->getValue()); if (V->getType()->isVectorTy()) if (const auto *C = dyn_cast
(V)) if (const auto *CI = dyn_cast_or_null
(C->getSplatValue())) return this->isValue(CI->getValue()); return false; } }; /// \brief This helper class is used to match scalar and vector constants that /// satisfy a specified predicate, and bind them to an APInt. template
struct api_pred_ty : public Predicate { const APInt *&Res; api_pred_ty(const APInt *&R) : Res(R) {} template
bool match(ITy *V) { if (const auto *CI = dyn_cast
(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) if (const auto *C = dyn_cast
(V)) if (auto *CI = dyn_cast_or_null
(C->getSplatValue())) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } return false; } }; struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; /// \brief Match an integer or vector power of 2. inline cst_pred_ty
m_Power2() { return cst_pred_ty
(); } inline api_pred_ty
m_Power2(const APInt *&V) { return V; } struct is_maxsignedvalue { bool isValue(const APInt &C) { return C.isMaxSignedValue(); } }; inline cst_pred_ty
m_MaxSignedValue() { return cst_pred_ty
(); } inline api_pred_ty
m_MaxSignedValue(const APInt *&V) { return V; } template
struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} template
bool match(ITy *V) { if (auto *CV = dyn_cast
(V)) { VR = CV; return true; } return false; } }; /// \brief Match a value, capturing it if we match. inline bind_ty
m_Value(Value *&V) { return V; } inline bind_ty
m_Value(const Value *&V) { return V; } /// \brief Match an instruction, capturing it if we match. inline bind_ty
m_Instruction(Instruction *&I) { return I; } /// \brief Match a binary operator, capturing it if we match. inline bind_ty
m_BinOp(BinaryOperator *&I) { return I; } /// \brief Match a ConstantInt, capturing the value if we match. inline bind_ty
m_ConstantInt(ConstantInt *&CI) { return CI; } /// \brief Match a Constant, capturing the value if we match. inline bind_ty
m_Constant(Constant *&C) { return C; } /// \brief Match a ConstantFP, capturing the value if we match. inline bind_ty
m_ConstantFP(ConstantFP *&C) { return C; } /// \brief Match a specified Value*. struct specificval_ty { const Value *Val; specificval_ty(const Value *V) : Val(V) {} template
bool match(ITy *V) { return V == Val; } }; /// \brief Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } /// \brief Match a specified floating point value or vector of all elements of /// that value. struct specific_fpval { double Val; specific_fpval(double V) : Val(V) {} template
bool match(ITy *V) { if (const auto *CFP = dyn_cast
(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) if (const auto *C = dyn_cast
(V)) if (auto *CFP = dyn_cast_or_null
(C->getSplatValue())) return CFP->isExactlyValue(Val); return false; } }; /// \brief Match a specific floating point value or vector with all elements /// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } /// \brief Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} template
bool match(ITy *V) { if (const auto *CV = dyn_cast
(V)) if (CV->getValue().ule(UINT64_MAX)) { VR = CV->getZExtValue(); return true; } return false; } }; /// \brief Match a specified integer value or vector of all elements of that // value. struct specific_intval { uint64_t Val; specific_intval(uint64_t V) : Val(V) {} template
bool match(ITy *V) { const auto *CI = dyn_cast
(V); if (!CI && V->getType()->isVectorTy()) if (const auto *C = dyn_cast
(V)) CI = dyn_cast_or_null
(C->getSplatValue()); return CI && CI->getValue() == Val; } }; /// \brief 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); } /// \brief 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; } //===----------------------------------------------------------------------===// // Matcher for any binary operator. // template
struct AnyBinaryOp_match { LHS_t L; RHS_t R; AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template
bool match(OpTy *V) { if (auto *I = dyn_cast
(V)) return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || (Commutable && R.match(I->getOperand(0)) && L.match(I->getOperand(1))); return false; } }; template
inline AnyBinaryOp_match
m_BinOp(const LHS &L, const RHS &R) { return AnyBinaryOp_match
(L, R); } //===----------------------------------------------------------------------===// // Matchers for specific binary operators. // template
struct BinaryOp_match { LHS_t L; RHS_t R; BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template
bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { auto *I = cast
(V); 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
(V)) 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; } }; template
inline BinaryOp_match
m_Add(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_FAdd(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_Sub(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_FSub(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_Mul(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_FMul(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_UDiv(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_SDiv(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_FDiv(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_URem(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_SRem(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_FRem(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_And(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_Or(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_Xor(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_Shl(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_LShr(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
inline BinaryOp_match
m_AShr(const LHS &L, const RHS &R) { return BinaryOp_match
(L, R); } template
struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template
bool match(OpTy *V) { if (auto *Op = dyn_cast
(V)) { if (Op->getOpcode() != Opcode) return false; if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && !Op->hasNoUnsignedWrap()) return false; if (WrapFlags & OverflowingBinaryOperator::NoSignedWrap && !Op->hasNoSignedWrap()) return false; return L.match(Op->getOperand(0)) && R.match(Op->getOperand(1)); } return false; } }; template
inline OverflowingBinaryOp_match
m_NSWAdd(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NSWSub(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NSWMul(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NSWShl(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NUWAdd(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NUWSub(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NUWMul(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } template
inline OverflowingBinaryOp_match
m_NUWShl(const LHS &L, const RHS &R) { return OverflowingBinaryOp_match
( L, R); } //===----------------------------------------------------------------------===// // Class that matches a group of binary opcodes. // template
struct BinOpPred_match : Predicate { LHS_t L; RHS_t R; BinOpPred_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template
bool match(OpTy *V) { if (auto *I = dyn_cast
(V)) return this->isOpType(I->getOpcode()) && L.match(I->getOperand(0)) && R.match(I->getOperand(1)); if (auto *CE = dyn_cast
(V)) return this->isOpType(CE->getOpcode()) && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; struct is_shift_op { bool isOpType(unsigned Opcode) { return Instruction::isShift(Opcode); } }; struct is_right_shift_op { bool isOpType(unsigned Opcode) { return Opcode == Instruction::LShr || Opcode == Instruction::AShr; } }; struct is_logical_shift_op { bool isOpType(unsigned Opcode) { return Opcode == Instruction::LShr || Opcode == Instruction::Shl; } }; struct is_bitwiselogic_op { bool isOpType(unsigned Opcode) { return Instruction::isBitwiseLogicOp(Opcode); } }; struct is_idiv_op { bool isOpType(unsigned Opcode) { return Opcode == Instruction::SDiv || Opcode == Instruction::UDiv; } }; /// \brief Matches shift operations. template
inline BinOpPred_match
m_Shift(const LHS &L, const RHS &R) { return BinOpPred_match
(L, R); } /// \brief Matches logical shift operations. template
inline BinOpPred_match
m_Shr(const LHS &L, const RHS &R) { return BinOpPred_match
(L, R); } /// \brief Matches logical shift operations. template
inline BinOpPred_match
m_LogicalShift(const LHS &L, const RHS &R) { return BinOpPred_match
(L, R); } /// \brief Matches bitwise logic operations. template
inline BinOpPred_match
m_BitwiseLogic(const LHS &L, const RHS &R) { return BinOpPred_match
(L, R); } /// \brief Matches integer division operations. template
inline BinOpPred_match
m_IDiv(const LHS &L, const RHS &R) { return BinOpPred_match
(L, R); } //===----------------------------------------------------------------------===// // Class that matches exact binary ops. // template
struct Exact_match { SubPattern_t SubPattern; Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} template
bool match(OpTy *V) { if (auto *PEO = dyn_cast
(V)) return PEO->isExact() && SubPattern.match(V); return false; } }; template
inline Exact_match
m_Exact(const T &SubPattern) { return SubPattern; } //===----------------------------------------------------------------------===// // Matchers for CmpInst classes // template
struct CmpClass_match { PredicateTy &Predicate; LHS_t L; RHS_t R; CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) : Predicate(Pred), L(LHS), R(RHS) {} template
bool match(OpTy *V) { if (auto *I = dyn_cast
(V)) 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; } return false; } }; template
inline CmpClass_match
m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { return CmpClass_match
(Pred, L, R); } template
inline CmpClass_match
m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { return CmpClass_match
(Pred, L, R); } template
inline CmpClass_match
m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { return CmpClass_match
(Pred, L, R); } //===----------------------------------------------------------------------===// // Matchers for SelectInst classes // template
struct SelectClass_match { Cond_t C; LHS_t L; RHS_t R; SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS) : C(Cond), L(LHS), R(RHS) {} template
bool match(OpTy *V) { if (auto *I = dyn_cast
(V)) return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) && R.match(I->getOperand(2)); return false; } }; template
inline SelectClass_match
m_Select(const Cond &C, const LHS &L, const RHS &R) { return SelectClass_match
(C, L, R); } /// \brief This matches a select of two constants, e.g.: /// m_SelectCst<-1, 0>(m_Value(V)) template
inline SelectClass_match
, constantint_match
> m_SelectCst(const Cond &C) { return m_Select(C, m_ConstantInt
(), m_ConstantInt
()); } //===----------------------------------------------------------------------===// // Matchers for CastInst classes // template
struct CastClass_match { Op_t Op; CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} template
bool match(OpTy *V) { if (auto *O = dyn_cast
(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; } }; /// \brief Matches BitCast. template
inline CastClass_match
m_BitCast(const OpTy &Op) { return CastClass_match
(Op); } /// \brief Matches PtrToInt. template
inline CastClass_match
m_PtrToInt(const OpTy &Op) { return CastClass_match
(Op); } /// \brief Matches Trunc. template
inline CastClass_match
m_Trunc(const OpTy &Op) { return CastClass_match
(Op); } /// \brief Matches SExt. template
inline CastClass_match
m_SExt(const OpTy &Op) { return CastClass_match
(Op); } /// \brief Matches ZExt. template
inline CastClass_match
m_ZExt(const OpTy &Op) { return CastClass_match