X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FPatternMatch.h;h=fda925f5a9a8c2fe4b712df4618c0538a60a4423;hb=38b06447615440f935008a2141bd0a1fe078d437;hp=4d745d6c2e41e4e41b4e8d7aeb213844d417b1da;hpb=0ec0b539a75e8896636530bddce47f5be14abd19;p=oota-llvm.git diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index 4d745d6c2e4..fda925f5a9a 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -2,15 +2,15 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// 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 is allows to you +// 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: // @@ -46,9 +46,48 @@ struct leaf_ty { bool match(ITy *V) { return isa(V); } }; +/// m_Value() - Match an arbitrary value and ignore it. inline leaf_ty m_Value() { return leaf_ty(); } +/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. inline leaf_ty m_ConstantInt() { return leaf_ty(); } +template +struct constantint_ty { + template + bool match(ITy *V) { + if (const ConstantInt *CI = dyn_cast(V)) { + const APInt &CIV = CI->getValue(); + if (Val >= 0) + return CIV == 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; + } +}; + +/// m_ConstantInt(int64_t) - Match a ConstantInt with a specific value +/// and ignore it. +template +inline constantint_ty m_ConstantInt() { + return constantint_ty(); +} + +struct zero_ty { + template + bool match(ITy *V) { + if (const Constant *C = dyn_cast(V)) + return C->isNullValue(); + return false; + } +}; + +/// m_Zero() - Match an arbitrary zero/null constant. +inline zero_ty m_Zero() { return zero_ty(); } + + template struct bind_ty { Class *&VR; @@ -64,14 +103,32 @@ struct bind_ty { } }; +/// m_Value - Match a value, capturing it if we match. inline bind_ty m_Value(Value *&V) { return V; } + +/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } +/// specificval_ty - 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; + } +}; + +/// m_Specific - Match if we have a specific specified value. +inline specificval_ty m_Specific(const Value *V) { return V; } + + //===----------------------------------------------------------------------===// // Matchers for specific binary operators. // -template struct BinaryOp_match { LHS_t L; @@ -81,7 +138,7 @@ struct BinaryOp_match { template bool match(OpTy *V) { - if (V->getValueType() == Value::InstructionVal + Opcode) { + if (V->getValueID() == Value::InstructionVal + Opcode) { ConcreteTy *I = cast(V); return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && R.match(I->getOperand(1)); @@ -99,12 +156,24 @@ inline BinaryOp_match m_Add(const LHS &L, 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) { @@ -112,15 +181,45 @@ inline BinaryOp_match m_Mul(const LHS &L, } template -inline BinaryOp_match m_Div(const LHS &L, +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); + 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_Rem(const LHS &L, +inline BinaryOp_match m_FRem(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); + return BinaryOp_match(L, R); } template @@ -142,15 +241,55 @@ inline BinaryOp_match m_Xor(const LHS &L, } template -inline BinaryOp_match m_Shl(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); +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_Shr(const LHS &L, const RHS &R) { - return BinaryOp_match(L, R); +inline BinaryOp_match m_AShr(const LHS &L, + const RHS &R) { + return BinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for either AShr or LShr .. for convenience +// +template +struct Shr_match { + LHS_t L; + RHS_t R; + + Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Instruction::LShr || + V->getValueID() == Value::InstructionVal + Instruction::AShr) { + ConcreteTy *I = cast(V); + return (I->getOpcode() == Instruction::AShr || + I->getOpcode() == Instruction::LShr) && + L.match(I->getOperand(0)) && + R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast(V)) + return (CE->getOpcode() == Instruction::LShr || + CE->getOpcode() == Instruction::AShr) && + L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); + return false; + } +}; + +template +inline Shr_match m_Shr(const LHS &L, const RHS &R) { + return Shr_match(L, R); } //===----------------------------------------------------------------------===// @@ -159,19 +298,22 @@ inline BinaryOp_match struct BinaryOpClass_match { - OpcType &Opcode; + OpcType *Opcode; LHS_t L; RHS_t R; BinaryOpClass_match(OpcType &Op, const LHS_t &LHS, const RHS_t &RHS) - : Opcode(Op), L(LHS), R(RHS) {} + : Opcode(&Op), L(LHS), R(RHS) {} + BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS) + : Opcode(0), L(LHS), R(RHS) {} template bool match(OpTy *V) { if (Class *I = dyn_cast(V)) if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { - Opcode = I->getOpcode(); + if (Opcode) + *Opcode = I->getOpcode(); return true; } #if 0 // Doesn't handle constantexprs yet! @@ -184,61 +326,126 @@ struct BinaryOpClass_match { }; template -inline BinaryOpClass_match -m_SetCond(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { - return BinaryOpClass_match(Op, L, R); +inline BinaryOpClass_match +m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { + return BinaryOpClass_match(Op, L, R); } template -inline BinaryOpClass_match -m_Shift(Instruction::OtherOps &Op, const LHS &L, const RHS &R) { - return BinaryOpClass_match(Op, L, R); +inline BinaryOpClass_match +m_Shift(const LHS &L, const RHS &R) { + return BinaryOpClass_match(L, R); +} + +//===----------------------------------------------------------------------===// +// 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 (Class *I = dyn_cast(V)) + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { + Predicate = I->getPredicate(); + return true; + } + return false; + } +}; + +template +inline CmpClass_match +m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); } template -inline BinaryOpClass_match -m_Shift(const LHS &L, const RHS &R) { - Instruction::OtherOps Op; - return BinaryOpClass_match(Op, L, R); +inline CmpClass_match +m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); } //===----------------------------------------------------------------------===// -// Matchers for unary operators +// Matchers for SelectInst classes // -template -struct neg_match { +template +struct SelectClass_match { + Cond_t C; LHS_t L; + RHS_t R; - neg_match(const LHS_t &LHS) : L(LHS) {} + 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 (Instruction *I = dyn_cast(V)) - if (I->getOpcode() == Instruction::Sub) - return matchIfNeg(I->getOperand(0), I->getOperand(1)); - if (ConstantExpr *CE = dyn_cast(V)) - if (CE->getOpcode() == Instruction::Sub) - return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast(V)) - return L.match(ConstantExpr::getNeg(CI)); + if (SelectInst *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && + L.match(I->getOperand(1)) && + R.match(I->getOperand(2)); return false; } -private: - bool matchIfNeg(Value *LHS, Value *RHS) { - if (!LHS->getType()->isFloatingPoint()) - return LHS == Constant::getNullValue(LHS->getType()) && L.match(RHS); - else - return LHS == ConstantFP::get(LHS->getType(), -0.0) && L.match(RHS); +}; + +template +inline SelectClass_match +m_Select(const Cond &C, const LHS &L, const RHS &R) { + return SelectClass_match(C, L, R); +} + +/// m_SelectCst - This matches a select of two constants, e.g.: +/// m_SelectCst(m_Value(V), -1, 0) +template +inline SelectClass_match, constantint_ty > +m_SelectCst(const Cond &C) { + return SelectClass_match, + constantint_ty >(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 (Class *I = dyn_cast(V)) + return Op.match(I->getOperand(0)); + return false; } }; -template -inline neg_match m_Neg(const LHS &L) { return L; } +template +inline CastClass_match m_Cast(const OpTy &Op) { + return CastClass_match(Op); +} + +//===----------------------------------------------------------------------===// +// Matchers for unary operators +// template struct not_match { @@ -260,10 +467,14 @@ struct not_match { } private: bool matchIfNot(Value *LHS, Value *RHS) { - if (ConstantIntegral *CI = dyn_cast(RHS)) + if (ConstantInt *CI = dyn_cast(RHS)) return CI->isAllOnesValue() && L.match(LHS); - else if (ConstantIntegral *CI = dyn_cast(LHS)) + if (ConstantInt *CI = dyn_cast(LHS)) return CI->isAllOnesValue() && L.match(RHS); + if (ConstantVector *CV = dyn_cast(RHS)) + return CV->isAllOnesValue() && L.match(LHS); + if (ConstantVector *CV = dyn_cast(LHS)) + return CV->isAllOnesValue() && L.match(RHS); return false; } }; @@ -272,36 +483,62 @@ template inline not_match m_Not(const LHS &L) { return L; } -template -struct cast_match { - Op_t Op; - const Type **DestTy; - - cast_match(const Op_t &op, const Type **destTy) : Op(op), DestTy(destTy) {} - +template +struct neg_match { + LHS_t L; + + neg_match(const LHS_t &LHS) : L(LHS) {} + template bool match(OpTy *V) { - if (CastInst *I = dyn_cast(V)) { - if (DestTy) *DestTy = I->getType(); - return Op.match(I->getOperand(0)); - } else if (ConstantExpr *CE = dyn_cast(V)) { - if (CE->getOpcode() == Instruction::Cast) { - if (DestTy) *DestTy = I->getType(); - return Op.match(CE->getOperand(0)); - } - } + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::Sub) + return matchIfNeg(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Sub) + return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); + if (ConstantInt *CI = dyn_cast(V)) + return L.match(ConstantExpr::getNeg(CI)); return false; } +private: + bool matchIfNeg(Value *LHS, Value *RHS) { + return LHS == ConstantExpr::getZeroValueForNegationExpr(LHS->getType()) && + L.match(RHS); + } }; -template -inline cast_match m_Cast(const Op_t &Op, const Type *&Ty) { - return cast_match(Op, &Ty); -} -template -inline cast_match m_Cast(const Op_t &Op) { - return cast_match(Op, 0); -} +template +inline neg_match m_Neg(const LHS &L) { return L; } + + +template +struct fneg_match { + LHS_t L; + + fneg_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::FSub) + return matchIfFNeg(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::FSub) + return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); + if (ConstantFP *CF = dyn_cast(V)) + return L.match(ConstantExpr::getFNeg(CF)); + return false; + } +private: + bool matchIfFNeg(Value *LHS, Value *RHS) { + return LHS == ConstantExpr::getZeroValueForNegationExpr(LHS->getType()) && + L.match(RHS); + } +}; + +template +inline fneg_match m_FNeg(const LHS &L) { return L; } //===----------------------------------------------------------------------===// @@ -331,13 +568,11 @@ struct brc_match { }; template -inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F){ +inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { return brc_match(C, T, F); } - -}} // end llvm::match - +} // end namespace PatternMatch +} // end namespace llvm #endif -