123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //==------ llvm/CodeGen/GlobalISel/MIPatternMatch.h -------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- /// Contains matchers for matching SSA Machine Instructions.
- ///
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
- #define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
- #include "llvm/ADT/APInt.h"
- #include "llvm/CodeGen/GlobalISel/Utils.h"
- #include "llvm/CodeGen/MachineRegisterInfo.h"
- #include "llvm/IR/InstrTypes.h"
- namespace llvm {
- namespace MIPatternMatch {
- template <typename Reg, typename Pattern>
- bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P) {
- return P.match(MRI, R);
- }
- template <typename Pattern>
- bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI, Pattern &&P) {
- return P.match(MRI, &MI);
- }
- // TODO: Extend for N use.
- template <typename SubPatternT> struct OneUse_match {
- SubPatternT SubPat;
- OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg);
- }
- };
- template <typename SubPat>
- inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
- return SP;
- }
- template <typename SubPatternT> struct OneNonDBGUse_match {
- SubPatternT SubPat;
- OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
- }
- };
- template <typename SubPat>
- inline OneNonDBGUse_match<SubPat> m_OneNonDBGUse(const SubPat &SP) {
- return SP;
- }
- template <typename ConstT>
- inline Optional<ConstT> matchConstant(Register, const MachineRegisterInfo &);
- template <>
- inline Optional<APInt> matchConstant(Register Reg,
- const MachineRegisterInfo &MRI) {
- return getIConstantVRegVal(Reg, MRI);
- }
- template <>
- inline Optional<int64_t> matchConstant(Register Reg,
- const MachineRegisterInfo &MRI) {
- return getIConstantVRegSExtVal(Reg, MRI);
- }
- template <typename ConstT> struct ConstantMatch {
- ConstT &CR;
- ConstantMatch(ConstT &C) : CR(C) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
- CR = *MaybeCst;
- return true;
- }
- return false;
- }
- };
- inline ConstantMatch<APInt> m_ICst(APInt &Cst) {
- return ConstantMatch<APInt>(Cst);
- }
- inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
- return ConstantMatch<int64_t>(Cst);
- }
- struct GCstAndRegMatch {
- Optional<ValueAndVReg> &ValReg;
- GCstAndRegMatch(Optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- ValReg = getIConstantVRegValWithLookThrough(Reg, MRI);
- return ValReg ? true : false;
- }
- };
- inline GCstAndRegMatch m_GCst(Optional<ValueAndVReg> &ValReg) {
- return GCstAndRegMatch(ValReg);
- }
- struct GFCstAndRegMatch {
- Optional<FPValueAndVReg> &FPValReg;
- GFCstAndRegMatch(Optional<FPValueAndVReg> &FPValReg) : FPValReg(FPValReg) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI);
- return FPValReg ? true : false;
- }
- };
- inline GFCstAndRegMatch m_GFCst(Optional<FPValueAndVReg> &FPValReg) {
- return GFCstAndRegMatch(FPValReg);
- }
- struct GFCstOrSplatGFCstMatch {
- Optional<FPValueAndVReg> &FPValReg;
- GFCstOrSplatGFCstMatch(Optional<FPValueAndVReg> &FPValReg)
- : FPValReg(FPValReg) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- return (FPValReg = getFConstantSplat(Reg, MRI)) ||
- (FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI));
- };
- };
- inline GFCstOrSplatGFCstMatch
- m_GFCstOrSplat(Optional<FPValueAndVReg> &FPValReg) {
- return GFCstOrSplatGFCstMatch(FPValReg);
- }
- /// Matcher for a specific constant value.
- struct SpecificConstantMatch {
- int64_t RequestedVal;
- SpecificConstantMatch(int64_t RequestedVal) : RequestedVal(RequestedVal) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- int64_t MatchedVal;
- return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal;
- }
- };
- /// Matches a constant equal to \p RequestedValue.
- inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
- return SpecificConstantMatch(RequestedValue);
- }
- /// Matcher for a specific constant splat.
- struct SpecificConstantSplatMatch {
- int64_t RequestedVal;
- SpecificConstantSplatMatch(int64_t RequestedVal)
- : RequestedVal(RequestedVal) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
- /* AllowUndef */ false);
- }
- };
- /// Matches a constant splat of \p RequestedValue.
- inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
- return SpecificConstantSplatMatch(RequestedValue);
- }
- /// Matcher for a specific constant or constant splat.
- struct SpecificConstantOrSplatMatch {
- int64_t RequestedVal;
- SpecificConstantOrSplatMatch(int64_t RequestedVal)
- : RequestedVal(RequestedVal) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- int64_t MatchedVal;
- if (mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal)
- return true;
- return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
- /* AllowUndef */ false);
- }
- };
- /// Matches a \p RequestedValue constant or a constant splat of \p
- /// RequestedValue.
- inline SpecificConstantOrSplatMatch
- m_SpecificICstOrSplat(int64_t RequestedValue) {
- return SpecificConstantOrSplatMatch(RequestedValue);
- }
- ///{
- /// Convenience matchers for specific integer values.
- inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); }
- inline SpecificConstantMatch m_AllOnesInt() {
- return SpecificConstantMatch(-1);
- }
- ///}
- // TODO: Rework this for different kinds of MachineOperand.
- // Currently assumes the Src for a match is a register.
- // We might want to support taking in some MachineOperands and call getReg on
- // that.
- struct operand_type_match {
- bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
- bool match(const MachineRegisterInfo &MRI, MachineOperand *MO) {
- return MO->isReg();
- }
- };
- inline operand_type_match m_Reg() { return operand_type_match(); }
- /// Matching combinators.
- template <typename... Preds> struct And {
- template <typename MatchSrc>
- bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
- return true;
- }
- };
- template <typename Pred, typename... Preds>
- struct And<Pred, Preds...> : And<Preds...> {
- Pred P;
- And(Pred &&p, Preds &&... preds)
- : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
- }
- template <typename MatchSrc>
- bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
- return P.match(MRI, src) && And<Preds...>::match(MRI, src);
- }
- };
- template <typename... Preds> struct Or {
- template <typename MatchSrc>
- bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
- return false;
- }
- };
- template <typename Pred, typename... Preds>
- struct Or<Pred, Preds...> : Or<Preds...> {
- Pred P;
- Or(Pred &&p, Preds &&... preds)
- : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
- template <typename MatchSrc>
- bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
- return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
- }
- };
- template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
- return And<Preds...>(std::forward<Preds>(preds)...);
- }
- template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
- return Or<Preds...>(std::forward<Preds>(preds)...);
- }
- template <typename BindTy> struct bind_helper {
- static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
- VR = V;
- return true;
- }
- };
- template <> struct bind_helper<MachineInstr *> {
- static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
- Register Reg) {
- MI = MRI.getVRegDef(Reg);
- if (MI)
- return true;
- return false;
- }
- static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
- MachineInstr *Inst) {
- MI = Inst;
- return MI;
- }
- };
- template <> struct bind_helper<LLT> {
- static bool bind(const MachineRegisterInfo &MRI, LLT Ty, Register Reg) {
- Ty = MRI.getType(Reg);
- if (Ty.isValid())
- return true;
- return false;
- }
- };
- template <> struct bind_helper<const ConstantFP *> {
- static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
- Register Reg) {
- F = getConstantFPVRegVal(Reg, MRI);
- if (F)
- return true;
- return false;
- }
- };
- template <typename Class> struct bind_ty {
- Class &VR;
- bind_ty(Class &V) : VR(V) {}
- template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
- return bind_helper<Class>::bind(MRI, VR, V);
- }
- };
- inline bind_ty<Register> m_Reg(Register &R) { return R; }
- inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
- inline bind_ty<LLT> m_Type(LLT Ty) { return Ty; }
- inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
- inline operand_type_match m_Pred() { return operand_type_match(); }
- // Helper for matching G_FCONSTANT
- inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
- // General helper for all the binary generic MI such as G_ADD/G_SUB etc
- template <typename LHS_P, typename RHS_P, unsigned Opcode,
- bool Commutable = false>
- struct BinaryOp_match {
- LHS_P L;
- RHS_P R;
- BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
- template <typename OpTy>
- bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
- MachineInstr *TmpMI;
- if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
- if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
- return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
- R.match(MRI, TmpMI->getOperand(2).getReg())) ||
- (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
- L.match(MRI, TmpMI->getOperand(2).getReg())));
- }
- }
- return false;
- }
- };
- // Helper for (commutative) binary generic MI that checks Opcode.
- template <typename LHS_P, typename RHS_P, bool Commutable = false>
- struct BinaryOpc_match {
- unsigned Opc;
- LHS_P L;
- RHS_P R;
- BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
- : Opc(Opcode), L(LHS), R(RHS) {}
- template <typename OpTy>
- bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
- MachineInstr *TmpMI;
- if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
- if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
- TmpMI->getNumOperands() == 3) {
- return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
- R.match(MRI, TmpMI->getOperand(2).getReg())) ||
- (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
- L.match(MRI, TmpMI->getOperand(2).getReg())));
- }
- }
- return false;
- }
- };
- template <typename LHS, typename RHS>
- inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
- const RHS &R) {
- return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOpc_match<LHS, RHS, true>
- m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
- return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>
- m_GAdd(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_PTR_ADD, false>
- m_GPtrAdd(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_PTR_ADD, false>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB> m_GSub(const LHS &L,
- const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>
- m_GMul(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>
- m_GFAdd(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>
- m_GFMul(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>
- m_GFSub(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>
- m_GAnd(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_XOR, true>
- m_GXor(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_XOR, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true> m_GOr(const LHS &L,
- const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>
- m_GShl(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_LSHR, false>
- m_GLShr(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_LSHR, false>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ASHR, false>
- m_GAShr(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_ASHR, false>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SMAX, false>
- m_GSMax(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_SMAX, false>(L, R);
- }
- template <typename LHS, typename RHS>
- inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SMIN, false>
- m_GSMin(const LHS &L, const RHS &R) {
- return BinaryOp_match<LHS, RHS, TargetOpcode::G_SMIN, false>(L, R);
- }
- // Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
- template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
- SrcTy L;
- UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
- template <typename OpTy>
- bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
- MachineInstr *TmpMI;
- if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
- if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
- return L.match(MRI, TmpMI->getOperand(1).getReg());
- }
- }
- return false;
- }
- };
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>
- m_GAnyExt(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_SEXT> m_GSExt(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_SEXT>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT> m_GZExt(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT> m_GFPExt(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC> m_GTrunc(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>
- m_GBitcast(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>
- m_GPtrToInt(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>
- m_GIntToPtr(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>
- m_GFPTrunc(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_FABS> m_GFabs(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_FABS>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_FNEG> m_GFNeg(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_FNEG>(Src);
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::COPY> m_Copy(SrcTy &&Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
- }
- template <typename SrcTy>
- inline UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT> m_GFSqrt(const SrcTy &Src) {
- return UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT>(Src);
- }
- // General helper for generic MI compares, i.e. G_ICMP and G_FCMP
- // TODO: Allow checking a specific predicate.
- template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode>
- struct CompareOp_match {
- Pred_P P;
- LHS_P L;
- RHS_P R;
- CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
- : P(Pred), L(LHS), R(RHS) {}
- template <typename OpTy>
- bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
- MachineInstr *TmpMI;
- if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
- return false;
- auto TmpPred =
- static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
- if (!P.match(MRI, TmpPred))
- return false;
- return L.match(MRI, TmpMI->getOperand(2).getReg()) &&
- R.match(MRI, TmpMI->getOperand(3).getReg());
- }
- };
- template <typename Pred, typename LHS, typename RHS>
- inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
- m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
- return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>(P, L, R);
- }
- template <typename Pred, typename LHS, typename RHS>
- inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>
- m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
- return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>(P, L, R);
- }
- // Helper for checking if a Reg is of specific type.
- struct CheckType {
- LLT Ty;
- CheckType(const LLT Ty) : Ty(Ty) {}
- bool match(const MachineRegisterInfo &MRI, Register Reg) {
- return MRI.getType(Reg) == Ty;
- }
- };
- inline CheckType m_SpecificType(LLT Ty) { return Ty; }
- template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
- struct TernaryOp_match {
- Src0Ty Src0;
- Src1Ty Src1;
- Src2Ty Src2;
- TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
- : Src0(Src0), Src1(Src1), Src2(Src2) {}
- template <typename OpTy>
- bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
- MachineInstr *TmpMI;
- if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
- if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
- return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
- Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
- Src2.match(MRI, TmpMI->getOperand(3).getReg()));
- }
- }
- return false;
- }
- };
- template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
- inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
- TargetOpcode::G_INSERT_VECTOR_ELT>
- m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
- return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
- TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
- }
- template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
- inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>
- m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
- return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>(
- Src0, Src1, Src2);
- }
- /// Matches a register negated by a G_SUB.
- /// G_SUB 0, %negated_reg
- template <typename SrcTy>
- inline BinaryOp_match<SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB>
- m_Neg(const SrcTy &&Src) {
- return m_GSub(m_ZeroInt(), Src);
- }
- /// Matches a register not-ed by a G_XOR.
- /// G_XOR %not_reg, -1
- template <typename SrcTy>
- inline BinaryOp_match<SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true>
- m_Not(const SrcTy &&Src) {
- return m_GXor(Src, m_AllOnesInt());
- }
- } // namespace MIPatternMatch
- } // namespace llvm
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|