MIPatternMatch.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //==------ llvm/CodeGen/GlobalISel/MIPatternMatch.h -------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. /// \file
  14. /// Contains matchers for matching SSA Machine Instructions.
  15. ///
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
  18. #define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
  19. #include "llvm/ADT/APInt.h"
  20. #include "llvm/CodeGen/GlobalISel/Utils.h"
  21. #include "llvm/CodeGen/MachineRegisterInfo.h"
  22. #include "llvm/IR/InstrTypes.h"
  23. namespace llvm {
  24. namespace MIPatternMatch {
  25. template <typename Reg, typename Pattern>
  26. bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P) {
  27. return P.match(MRI, R);
  28. }
  29. template <typename Pattern>
  30. bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI, Pattern &&P) {
  31. return P.match(MRI, &MI);
  32. }
  33. // TODO: Extend for N use.
  34. template <typename SubPatternT> struct OneUse_match {
  35. SubPatternT SubPat;
  36. OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
  37. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  38. return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg);
  39. }
  40. };
  41. template <typename SubPat>
  42. inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
  43. return SP;
  44. }
  45. template <typename SubPatternT> struct OneNonDBGUse_match {
  46. SubPatternT SubPat;
  47. OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {}
  48. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  49. return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
  50. }
  51. };
  52. template <typename SubPat>
  53. inline OneNonDBGUse_match<SubPat> m_OneNonDBGUse(const SubPat &SP) {
  54. return SP;
  55. }
  56. template <typename ConstT>
  57. inline Optional<ConstT> matchConstant(Register, const MachineRegisterInfo &);
  58. template <>
  59. inline Optional<APInt> matchConstant(Register Reg,
  60. const MachineRegisterInfo &MRI) {
  61. return getIConstantVRegVal(Reg, MRI);
  62. }
  63. template <>
  64. inline Optional<int64_t> matchConstant(Register Reg,
  65. const MachineRegisterInfo &MRI) {
  66. return getIConstantVRegSExtVal(Reg, MRI);
  67. }
  68. template <typename ConstT> struct ConstantMatch {
  69. ConstT &CR;
  70. ConstantMatch(ConstT &C) : CR(C) {}
  71. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  72. if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
  73. CR = *MaybeCst;
  74. return true;
  75. }
  76. return false;
  77. }
  78. };
  79. inline ConstantMatch<APInt> m_ICst(APInt &Cst) {
  80. return ConstantMatch<APInt>(Cst);
  81. }
  82. inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
  83. return ConstantMatch<int64_t>(Cst);
  84. }
  85. struct GCstAndRegMatch {
  86. Optional<ValueAndVReg> &ValReg;
  87. GCstAndRegMatch(Optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
  88. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  89. ValReg = getIConstantVRegValWithLookThrough(Reg, MRI);
  90. return ValReg ? true : false;
  91. }
  92. };
  93. inline GCstAndRegMatch m_GCst(Optional<ValueAndVReg> &ValReg) {
  94. return GCstAndRegMatch(ValReg);
  95. }
  96. struct GFCstAndRegMatch {
  97. Optional<FPValueAndVReg> &FPValReg;
  98. GFCstAndRegMatch(Optional<FPValueAndVReg> &FPValReg) : FPValReg(FPValReg) {}
  99. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  100. FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI);
  101. return FPValReg ? true : false;
  102. }
  103. };
  104. inline GFCstAndRegMatch m_GFCst(Optional<FPValueAndVReg> &FPValReg) {
  105. return GFCstAndRegMatch(FPValReg);
  106. }
  107. struct GFCstOrSplatGFCstMatch {
  108. Optional<FPValueAndVReg> &FPValReg;
  109. GFCstOrSplatGFCstMatch(Optional<FPValueAndVReg> &FPValReg)
  110. : FPValReg(FPValReg) {}
  111. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  112. return (FPValReg = getFConstantSplat(Reg, MRI)) ||
  113. (FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI));
  114. };
  115. };
  116. inline GFCstOrSplatGFCstMatch
  117. m_GFCstOrSplat(Optional<FPValueAndVReg> &FPValReg) {
  118. return GFCstOrSplatGFCstMatch(FPValReg);
  119. }
  120. /// Matcher for a specific constant value.
  121. struct SpecificConstantMatch {
  122. int64_t RequestedVal;
  123. SpecificConstantMatch(int64_t RequestedVal) : RequestedVal(RequestedVal) {}
  124. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  125. int64_t MatchedVal;
  126. return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal;
  127. }
  128. };
  129. /// Matches a constant equal to \p RequestedValue.
  130. inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
  131. return SpecificConstantMatch(RequestedValue);
  132. }
  133. /// Matcher for a specific constant splat.
  134. struct SpecificConstantSplatMatch {
  135. int64_t RequestedVal;
  136. SpecificConstantSplatMatch(int64_t RequestedVal)
  137. : RequestedVal(RequestedVal) {}
  138. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  139. return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
  140. /* AllowUndef */ false);
  141. }
  142. };
  143. /// Matches a constant splat of \p RequestedValue.
  144. inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
  145. return SpecificConstantSplatMatch(RequestedValue);
  146. }
  147. /// Matcher for a specific constant or constant splat.
  148. struct SpecificConstantOrSplatMatch {
  149. int64_t RequestedVal;
  150. SpecificConstantOrSplatMatch(int64_t RequestedVal)
  151. : RequestedVal(RequestedVal) {}
  152. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  153. int64_t MatchedVal;
  154. if (mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal)
  155. return true;
  156. return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
  157. /* AllowUndef */ false);
  158. }
  159. };
  160. /// Matches a \p RequestedValue constant or a constant splat of \p
  161. /// RequestedValue.
  162. inline SpecificConstantOrSplatMatch
  163. m_SpecificICstOrSplat(int64_t RequestedValue) {
  164. return SpecificConstantOrSplatMatch(RequestedValue);
  165. }
  166. ///{
  167. /// Convenience matchers for specific integer values.
  168. inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); }
  169. inline SpecificConstantMatch m_AllOnesInt() {
  170. return SpecificConstantMatch(-1);
  171. }
  172. ///}
  173. // TODO: Rework this for different kinds of MachineOperand.
  174. // Currently assumes the Src for a match is a register.
  175. // We might want to support taking in some MachineOperands and call getReg on
  176. // that.
  177. struct operand_type_match {
  178. bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
  179. bool match(const MachineRegisterInfo &MRI, MachineOperand *MO) {
  180. return MO->isReg();
  181. }
  182. };
  183. inline operand_type_match m_Reg() { return operand_type_match(); }
  184. /// Matching combinators.
  185. template <typename... Preds> struct And {
  186. template <typename MatchSrc>
  187. bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
  188. return true;
  189. }
  190. };
  191. template <typename Pred, typename... Preds>
  192. struct And<Pred, Preds...> : And<Preds...> {
  193. Pred P;
  194. And(Pred &&p, Preds &&... preds)
  195. : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
  196. }
  197. template <typename MatchSrc>
  198. bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
  199. return P.match(MRI, src) && And<Preds...>::match(MRI, src);
  200. }
  201. };
  202. template <typename... Preds> struct Or {
  203. template <typename MatchSrc>
  204. bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
  205. return false;
  206. }
  207. };
  208. template <typename Pred, typename... Preds>
  209. struct Or<Pred, Preds...> : Or<Preds...> {
  210. Pred P;
  211. Or(Pred &&p, Preds &&... preds)
  212. : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
  213. template <typename MatchSrc>
  214. bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
  215. return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
  216. }
  217. };
  218. template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
  219. return And<Preds...>(std::forward<Preds>(preds)...);
  220. }
  221. template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
  222. return Or<Preds...>(std::forward<Preds>(preds)...);
  223. }
  224. template <typename BindTy> struct bind_helper {
  225. static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
  226. VR = V;
  227. return true;
  228. }
  229. };
  230. template <> struct bind_helper<MachineInstr *> {
  231. static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
  232. Register Reg) {
  233. MI = MRI.getVRegDef(Reg);
  234. if (MI)
  235. return true;
  236. return false;
  237. }
  238. static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
  239. MachineInstr *Inst) {
  240. MI = Inst;
  241. return MI;
  242. }
  243. };
  244. template <> struct bind_helper<LLT> {
  245. static bool bind(const MachineRegisterInfo &MRI, LLT Ty, Register Reg) {
  246. Ty = MRI.getType(Reg);
  247. if (Ty.isValid())
  248. return true;
  249. return false;
  250. }
  251. };
  252. template <> struct bind_helper<const ConstantFP *> {
  253. static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
  254. Register Reg) {
  255. F = getConstantFPVRegVal(Reg, MRI);
  256. if (F)
  257. return true;
  258. return false;
  259. }
  260. };
  261. template <typename Class> struct bind_ty {
  262. Class &VR;
  263. bind_ty(Class &V) : VR(V) {}
  264. template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
  265. return bind_helper<Class>::bind(MRI, VR, V);
  266. }
  267. };
  268. inline bind_ty<Register> m_Reg(Register &R) { return R; }
  269. inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
  270. inline bind_ty<LLT> m_Type(LLT Ty) { return Ty; }
  271. inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
  272. inline operand_type_match m_Pred() { return operand_type_match(); }
  273. // Helper for matching G_FCONSTANT
  274. inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
  275. // General helper for all the binary generic MI such as G_ADD/G_SUB etc
  276. template <typename LHS_P, typename RHS_P, unsigned Opcode,
  277. bool Commutable = false>
  278. struct BinaryOp_match {
  279. LHS_P L;
  280. RHS_P R;
  281. BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
  282. template <typename OpTy>
  283. bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
  284. MachineInstr *TmpMI;
  285. if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
  286. if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
  287. return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
  288. R.match(MRI, TmpMI->getOperand(2).getReg())) ||
  289. (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
  290. L.match(MRI, TmpMI->getOperand(2).getReg())));
  291. }
  292. }
  293. return false;
  294. }
  295. };
  296. // Helper for (commutative) binary generic MI that checks Opcode.
  297. template <typename LHS_P, typename RHS_P, bool Commutable = false>
  298. struct BinaryOpc_match {
  299. unsigned Opc;
  300. LHS_P L;
  301. RHS_P R;
  302. BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
  303. : Opc(Opcode), L(LHS), R(RHS) {}
  304. template <typename OpTy>
  305. bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
  306. MachineInstr *TmpMI;
  307. if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
  308. if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
  309. TmpMI->getNumOperands() == 3) {
  310. return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
  311. R.match(MRI, TmpMI->getOperand(2).getReg())) ||
  312. (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
  313. L.match(MRI, TmpMI->getOperand(2).getReg())));
  314. }
  315. }
  316. return false;
  317. }
  318. };
  319. template <typename LHS, typename RHS>
  320. inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
  321. const RHS &R) {
  322. return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
  323. }
  324. template <typename LHS, typename RHS>
  325. inline BinaryOpc_match<LHS, RHS, true>
  326. m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
  327. return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
  328. }
  329. template <typename LHS, typename RHS>
  330. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>
  331. m_GAdd(const LHS &L, const RHS &R) {
  332. return BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>(L, R);
  333. }
  334. template <typename LHS, typename RHS>
  335. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_PTR_ADD, false>
  336. m_GPtrAdd(const LHS &L, const RHS &R) {
  337. return BinaryOp_match<LHS, RHS, TargetOpcode::G_PTR_ADD, false>(L, R);
  338. }
  339. template <typename LHS, typename RHS>
  340. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB> m_GSub(const LHS &L,
  341. const RHS &R) {
  342. return BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB>(L, R);
  343. }
  344. template <typename LHS, typename RHS>
  345. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>
  346. m_GMul(const LHS &L, const RHS &R) {
  347. return BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>(L, R);
  348. }
  349. template <typename LHS, typename RHS>
  350. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>
  351. m_GFAdd(const LHS &L, const RHS &R) {
  352. return BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>(L, R);
  353. }
  354. template <typename LHS, typename RHS>
  355. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>
  356. m_GFMul(const LHS &L, const RHS &R) {
  357. return BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>(L, R);
  358. }
  359. template <typename LHS, typename RHS>
  360. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>
  361. m_GFSub(const LHS &L, const RHS &R) {
  362. return BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>(L, R);
  363. }
  364. template <typename LHS, typename RHS>
  365. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>
  366. m_GAnd(const LHS &L, const RHS &R) {
  367. return BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>(L, R);
  368. }
  369. template <typename LHS, typename RHS>
  370. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_XOR, true>
  371. m_GXor(const LHS &L, const RHS &R) {
  372. return BinaryOp_match<LHS, RHS, TargetOpcode::G_XOR, true>(L, R);
  373. }
  374. template <typename LHS, typename RHS>
  375. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true> m_GOr(const LHS &L,
  376. const RHS &R) {
  377. return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true>(L, R);
  378. }
  379. template <typename LHS, typename RHS>
  380. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>
  381. m_GShl(const LHS &L, const RHS &R) {
  382. return BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>(L, R);
  383. }
  384. template <typename LHS, typename RHS>
  385. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_LSHR, false>
  386. m_GLShr(const LHS &L, const RHS &R) {
  387. return BinaryOp_match<LHS, RHS, TargetOpcode::G_LSHR, false>(L, R);
  388. }
  389. template <typename LHS, typename RHS>
  390. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ASHR, false>
  391. m_GAShr(const LHS &L, const RHS &R) {
  392. return BinaryOp_match<LHS, RHS, TargetOpcode::G_ASHR, false>(L, R);
  393. }
  394. template <typename LHS, typename RHS>
  395. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SMAX, false>
  396. m_GSMax(const LHS &L, const RHS &R) {
  397. return BinaryOp_match<LHS, RHS, TargetOpcode::G_SMAX, false>(L, R);
  398. }
  399. template <typename LHS, typename RHS>
  400. inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SMIN, false>
  401. m_GSMin(const LHS &L, const RHS &R) {
  402. return BinaryOp_match<LHS, RHS, TargetOpcode::G_SMIN, false>(L, R);
  403. }
  404. // Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
  405. template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
  406. SrcTy L;
  407. UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
  408. template <typename OpTy>
  409. bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
  410. MachineInstr *TmpMI;
  411. if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
  412. if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
  413. return L.match(MRI, TmpMI->getOperand(1).getReg());
  414. }
  415. }
  416. return false;
  417. }
  418. };
  419. template <typename SrcTy>
  420. inline UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>
  421. m_GAnyExt(const SrcTy &Src) {
  422. return UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>(Src);
  423. }
  424. template <typename SrcTy>
  425. inline UnaryOp_match<SrcTy, TargetOpcode::G_SEXT> m_GSExt(const SrcTy &Src) {
  426. return UnaryOp_match<SrcTy, TargetOpcode::G_SEXT>(Src);
  427. }
  428. template <typename SrcTy>
  429. inline UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT> m_GZExt(const SrcTy &Src) {
  430. return UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT>(Src);
  431. }
  432. template <typename SrcTy>
  433. inline UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT> m_GFPExt(const SrcTy &Src) {
  434. return UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT>(Src);
  435. }
  436. template <typename SrcTy>
  437. inline UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC> m_GTrunc(const SrcTy &Src) {
  438. return UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC>(Src);
  439. }
  440. template <typename SrcTy>
  441. inline UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>
  442. m_GBitcast(const SrcTy &Src) {
  443. return UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>(Src);
  444. }
  445. template <typename SrcTy>
  446. inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>
  447. m_GPtrToInt(const SrcTy &Src) {
  448. return UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>(Src);
  449. }
  450. template <typename SrcTy>
  451. inline UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>
  452. m_GIntToPtr(const SrcTy &Src) {
  453. return UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>(Src);
  454. }
  455. template <typename SrcTy>
  456. inline UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>
  457. m_GFPTrunc(const SrcTy &Src) {
  458. return UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>(Src);
  459. }
  460. template <typename SrcTy>
  461. inline UnaryOp_match<SrcTy, TargetOpcode::G_FABS> m_GFabs(const SrcTy &Src) {
  462. return UnaryOp_match<SrcTy, TargetOpcode::G_FABS>(Src);
  463. }
  464. template <typename SrcTy>
  465. inline UnaryOp_match<SrcTy, TargetOpcode::G_FNEG> m_GFNeg(const SrcTy &Src) {
  466. return UnaryOp_match<SrcTy, TargetOpcode::G_FNEG>(Src);
  467. }
  468. template <typename SrcTy>
  469. inline UnaryOp_match<SrcTy, TargetOpcode::COPY> m_Copy(SrcTy &&Src) {
  470. return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
  471. }
  472. template <typename SrcTy>
  473. inline UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT> m_GFSqrt(const SrcTy &Src) {
  474. return UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT>(Src);
  475. }
  476. // General helper for generic MI compares, i.e. G_ICMP and G_FCMP
  477. // TODO: Allow checking a specific predicate.
  478. template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode>
  479. struct CompareOp_match {
  480. Pred_P P;
  481. LHS_P L;
  482. RHS_P R;
  483. CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
  484. : P(Pred), L(LHS), R(RHS) {}
  485. template <typename OpTy>
  486. bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
  487. MachineInstr *TmpMI;
  488. if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
  489. return false;
  490. auto TmpPred =
  491. static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
  492. if (!P.match(MRI, TmpPred))
  493. return false;
  494. return L.match(MRI, TmpMI->getOperand(2).getReg()) &&
  495. R.match(MRI, TmpMI->getOperand(3).getReg());
  496. }
  497. };
  498. template <typename Pred, typename LHS, typename RHS>
  499. inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
  500. m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
  501. return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>(P, L, R);
  502. }
  503. template <typename Pred, typename LHS, typename RHS>
  504. inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>
  505. m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
  506. return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>(P, L, R);
  507. }
  508. // Helper for checking if a Reg is of specific type.
  509. struct CheckType {
  510. LLT Ty;
  511. CheckType(const LLT Ty) : Ty(Ty) {}
  512. bool match(const MachineRegisterInfo &MRI, Register Reg) {
  513. return MRI.getType(Reg) == Ty;
  514. }
  515. };
  516. inline CheckType m_SpecificType(LLT Ty) { return Ty; }
  517. template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
  518. struct TernaryOp_match {
  519. Src0Ty Src0;
  520. Src1Ty Src1;
  521. Src2Ty Src2;
  522. TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
  523. : Src0(Src0), Src1(Src1), Src2(Src2) {}
  524. template <typename OpTy>
  525. bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
  526. MachineInstr *TmpMI;
  527. if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
  528. if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
  529. return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
  530. Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
  531. Src2.match(MRI, TmpMI->getOperand(3).getReg()));
  532. }
  533. }
  534. return false;
  535. }
  536. };
  537. template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
  538. inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
  539. TargetOpcode::G_INSERT_VECTOR_ELT>
  540. m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
  541. return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
  542. TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
  543. }
  544. template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
  545. inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>
  546. m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
  547. return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>(
  548. Src0, Src1, Src2);
  549. }
  550. /// Matches a register negated by a G_SUB.
  551. /// G_SUB 0, %negated_reg
  552. template <typename SrcTy>
  553. inline BinaryOp_match<SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB>
  554. m_Neg(const SrcTy &&Src) {
  555. return m_GSub(m_ZeroInt(), Src);
  556. }
  557. /// Matches a register not-ed by a G_XOR.
  558. /// G_XOR %not_reg, -1
  559. template <typename SrcTy>
  560. inline BinaryOp_match<SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true>
  561. m_Not(const SrcTy &&Src) {
  562. return m_GXor(Src, m_AllOnesInt());
  563. }
  564. } // namespace MIPatternMatch
  565. } // namespace llvm
  566. #endif
  567. #ifdef __GNUC__
  568. #pragma GCC diagnostic pop
  569. #endif