LLVM 22.0.0git
MIPatternMatch.h
Go to the documentation of this file.
1//==------ llvm/CodeGen/GlobalISel/MIPatternMatch.h -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// Contains matchers for matching SSA Machine Instructions.
10///
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
14#define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
15
16#include "llvm/ADT/APInt.h"
22#include "llvm/IR/InstrTypes.h"
23
24namespace llvm {
25namespace MIPatternMatch {
26
27template <typename Reg, typename Pattern>
28[[nodiscard]] bool mi_match(Reg R, const MachineRegisterInfo &MRI,
29 Pattern &&P) {
30 return P.match(MRI, R);
31}
32
33template <typename Pattern>
34[[nodiscard]] bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI,
35 Pattern &&P) {
36 return P.match(MRI, &MI);
37}
38
39template <typename Pattern>
40[[nodiscard]] bool mi_match(const MachineInstr &MI,
41 const MachineRegisterInfo &MRI, Pattern &&P) {
42 return P.match(MRI, &MI);
43}
44
45// TODO: Extend for N use.
46template <typename SubPatternT> struct OneUse_match {
47 SubPatternT SubPat;
48 OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
49
51 return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg);
52 }
53};
54
55template <typename SubPat>
56inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
57 return SP;
58}
59
60template <typename SubPatternT> struct OneNonDBGUse_match {
61 SubPatternT SubPat;
62 OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {}
63
65 return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
66 }
67};
68
69template <typename SubPat>
71 return SP;
72}
73
74template <typename ConstT>
75inline std::optional<ConstT> matchConstant(Register,
76 const MachineRegisterInfo &);
77
78template <>
79inline std::optional<APInt> matchConstant(Register Reg,
80 const MachineRegisterInfo &MRI) {
82}
83
84template <>
85inline std::optional<int64_t> matchConstant(Register Reg,
86 const MachineRegisterInfo &MRI) {
88}
89
90template <typename ConstT> struct ConstantMatch {
91 ConstT &CR;
92 ConstantMatch(ConstT &C) : CR(C) {}
94 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
95 CR = *MaybeCst;
96 return true;
97 }
98 return false;
99 }
100};
101
103 return ConstantMatch<APInt>(Cst);
104}
105inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
106 return ConstantMatch<int64_t>(Cst);
107}
108
109template <typename ConstT>
110inline std::optional<ConstT> matchConstantSplat(Register,
111 const MachineRegisterInfo &);
112
113template <>
114inline std::optional<APInt> matchConstantSplat(Register Reg,
115 const MachineRegisterInfo &MRI) {
117}
118
119template <>
120inline std::optional<int64_t>
123}
124
125template <typename ConstT> struct ICstOrSplatMatch {
126 ConstT &CR;
127 ICstOrSplatMatch(ConstT &C) : CR(C) {}
129 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
130 CR = *MaybeCst;
131 return true;
132 }
133
134 if (auto MaybeCstSplat = matchConstantSplat<ConstT>(Reg, MRI)) {
135 CR = *MaybeCstSplat;
136 return true;
137 }
138
139 return false;
140 };
141};
142
144 return ICstOrSplatMatch<APInt>(Cst);
145}
146
148 return ICstOrSplatMatch<int64_t>(Cst);
149}
150
152 std::optional<ValueAndVReg> &ValReg;
153 GCstAndRegMatch(std::optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
156 return ValReg ? true : false;
157 }
158};
159
160inline GCstAndRegMatch m_GCst(std::optional<ValueAndVReg> &ValReg) {
161 return GCstAndRegMatch(ValReg);
162}
163
165 std::optional<FPValueAndVReg> &FPValReg;
166 GFCstAndRegMatch(std::optional<FPValueAndVReg> &FPValReg)
167 : FPValReg(FPValReg) {}
170 return FPValReg ? true : false;
171 }
172};
173
174inline GFCstAndRegMatch m_GFCst(std::optional<FPValueAndVReg> &FPValReg) {
175 return GFCstAndRegMatch(FPValReg);
176}
177
179 std::optional<FPValueAndVReg> &FPValReg;
180 GFCstOrSplatGFCstMatch(std::optional<FPValueAndVReg> &FPValReg)
181 : FPValReg(FPValReg) {}
183 return (FPValReg = getFConstantSplat(Reg, MRI)) ||
185 };
186};
187
189m_GFCstOrSplat(std::optional<FPValueAndVReg> &FPValReg) {
190 return GFCstOrSplatGFCstMatch(FPValReg);
191}
192
193/// Matcher for a specific constant value.
199 APInt MatchedVal;
200 if (mi_match(Reg, MRI, m_ICst(MatchedVal))) {
201 if (MatchedVal.getBitWidth() > RequestedVal.getBitWidth())
203 else
204 MatchedVal = MatchedVal.sext(RequestedVal.getBitWidth());
205
206 return APInt::isSameValue(MatchedVal, RequestedVal);
207 }
208 return false;
209 }
210};
211
212/// Matches a constant equal to \p RequestedValue.
214 return SpecificConstantMatch(std::move(RequestedValue));
215}
216
217inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
218 return SpecificConstantMatch(APInt(64, RequestedValue, /* isSigned */ true));
219}
220
221/// Matcher for a specific constant splat.
228 /* AllowUndef */ false);
229 }
230};
231
232/// Matches a constant splat of \p RequestedValue.
234 return SpecificConstantSplatMatch(std::move(RequestedValue));
235}
236
237inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
239 APInt(64, RequestedValue, /* isSigned */ true));
240}
241
242/// Matcher for a specific constant or constant splat.
248 APInt MatchedVal;
249 if (mi_match(Reg, MRI, m_ICst(MatchedVal))) {
250 if (MatchedVal.getBitWidth() > RequestedVal.getBitWidth())
252 else
253 MatchedVal = MatchedVal.sext(RequestedVal.getBitWidth());
254
255 if (APInt::isSameValue(MatchedVal, RequestedVal))
256 return true;
257 }
259 /* AllowUndef */ false);
260 }
261};
262
263/// Matches a \p RequestedValue constant or a constant splat of \p
264/// RequestedValue.
267 return SpecificConstantOrSplatMatch(std::move(RequestedValue));
268}
269
271m_SpecificICstOrSplat(int64_t RequestedValue) {
273 APInt(64, RequestedValue, /* isSigned */ true));
274}
275
276/// Convenience matchers for specific integer values.
279}
282}
283
284/// Matcher for a specific register.
289 return Reg == RequestedReg;
290 }
291};
292
293/// Matches a register only if it is equal to \p RequestedReg.
295 return SpecificRegisterMatch(RequestedReg);
296}
297
298// TODO: Rework this for different kinds of MachineOperand.
299// Currently assumes the Src for a match is a register.
300// We might want to support taking in some MachineOperands and call getReg on
301// that.
302
304 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
306 return MO->isReg();
307 }
308};
309
311
312/// Matching combinators.
313template <typename... Preds> struct And {
314 template <typename MatchSrc>
315 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
316 return true;
317 }
318};
319
320template <typename Pred, typename... Preds>
321struct And<Pred, Preds...> : And<Preds...> {
322 Pred P;
323 And(Pred &&p, Preds &&... preds)
324 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
325 }
326 template <typename MatchSrc>
327 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
328 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
329 }
330};
331
332template <typename... Preds> struct Or {
333 template <typename MatchSrc>
334 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
335 return false;
336 }
337};
338
339template <typename Pred, typename... Preds>
340struct Or<Pred, Preds...> : Or<Preds...> {
341 Pred P;
342 Or(Pred &&p, Preds &&... preds)
343 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
344 template <typename MatchSrc>
345 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
346 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
347 }
348};
349
350template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
351 return And<Preds...>(std::forward<Preds>(preds)...);
352}
353
354template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
355 return Or<Preds...>(std::forward<Preds>(preds)...);
356}
357
358template <typename BindTy> struct bind_helper {
359 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
360 VR = V;
361 return true;
362 }
363};
364
365template <> struct bind_helper<MachineInstr *> {
367 Register Reg) {
368 MI = MRI.getVRegDef(Reg);
369 if (MI)
370 return true;
371 return false;
372 }
374 MachineInstr *Inst) {
375 MI = Inst;
376 return MI;
377 }
378};
379
380template <> struct bind_helper<const MachineInstr *> {
381 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
382 Register Reg) {
383 MI = MRI.getVRegDef(Reg);
384 return MI;
385 }
386 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
387 const MachineInstr *Inst) {
388 MI = Inst;
389 return MI;
390 }
391};
392
393template <> struct bind_helper<LLT> {
394 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
395 Ty = MRI.getType(Reg);
396 if (Ty.isValid())
397 return true;
398 return false;
399 }
400};
401
402template <> struct bind_helper<const ConstantFP *> {
403 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
404 Register Reg) {
406 if (F)
407 return true;
408 return false;
409 }
410};
411
412template <typename Class> struct bind_ty {
413 Class &VR;
414
415 bind_ty(Class &V) : VR(V) {}
416
417 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
418 return bind_helper<Class>::bind(MRI, VR, V);
419 }
420};
421
422inline bind_ty<Register> m_Reg(Register &R) { return R; }
425 return MI;
426}
427inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
431
432template <typename BindTy> struct deferred_helper {
433 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
434 return VR == V;
435 }
436};
437
438template <> struct deferred_helper<LLT> {
439 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
440 return VT == MRI.getType(R);
441 }
442};
443
444template <typename Class> struct deferred_ty {
445 Class &VR;
446
447 deferred_ty(Class &V) : VR(V) {}
448
449 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
451 }
452};
453
454/// Similar to m_SpecificReg/Type, but the specific value to match originated
455/// from an earlier sub-pattern in the same mi_match expression. For example,
456/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
457/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
458/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
460inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
461
464 MachineInstr *TmpMI;
465 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
466 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
467 return false;
468 }
469};
470
472
473// Helper for matching G_FCONSTANT
475
476// General helper for all the binary generic MI such as G_ADD/G_SUB etc
477template <typename LHS_P, typename RHS_P, unsigned Opcode,
478 bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
480 LHS_P L;
481 RHS_P R;
482
483 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
484 template <typename OpTy>
485 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
486 const MachineInstr *TmpMI;
487 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
488 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
489 if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
490 !R.match(MRI, TmpMI->getOperand(2).getReg())) &&
491 // NOTE: When trying the alternative operand ordering
492 // with a commutative operation, it is imperative to always run
493 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
494 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
495 // expected.
496 (!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
497 !R.match(MRI, TmpMI->getOperand(1).getReg())))
498 return false;
499 return (TmpMI->getFlags() & Flags) == Flags;
500 }
501 }
502 return false;
503 }
504};
505
506// Helper for (commutative) binary generic MI that checks Opcode.
507template <typename LHS_P, typename RHS_P, bool Commutable = false>
509 unsigned Opc;
510 LHS_P L;
511 RHS_P R;
512
513 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
514 : Opc(Opcode), L(LHS), R(RHS) {}
515 template <typename OpTy>
516 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
517 MachineInstr *TmpMI;
518 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
519 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
520 TmpMI->getNumOperands() == 3) {
521 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
522 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
523 // NOTE: When trying the alternative operand ordering
524 // with a commutative operation, it is imperative to always run
525 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
526 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
527 // expected.
528 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
529 R.match(MRI, TmpMI->getOperand(1).getReg())));
530 }
531 }
532 return false;
533 }
534};
535
536template <typename LHS, typename RHS>
537inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
538 const RHS &R) {
539 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
540}
541
542template <typename LHS, typename RHS>
544m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
545 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
546}
547
548template <typename LHS, typename RHS>
550m_GAdd(const LHS &L, const RHS &R) {
552}
553
554template <typename LHS, typename RHS>
556m_GBuildVector(const LHS &L, const RHS &R) {
558}
559
560template <typename LHS, typename RHS>
562m_GBuildVectorTrunc(const LHS &L, const RHS &R) {
564 R);
565}
566
567template <typename LHS, typename RHS>
569m_GPtrAdd(const LHS &L, const RHS &R) {
571}
572
573template <typename LHS, typename RHS>
575 const RHS &R) {
577}
578
579template <typename LHS, typename RHS>
581m_GMul(const LHS &L, const RHS &R) {
583}
584
585template <typename LHS, typename RHS>
587m_GFAdd(const LHS &L, const RHS &R) {
589}
590
591template <typename LHS, typename RHS>
593m_GFMul(const LHS &L, const RHS &R) {
595}
596
597template <typename LHS, typename RHS>
599m_GFSub(const LHS &L, const RHS &R) {
601}
602
603template <typename LHS, typename RHS>
605m_GAnd(const LHS &L, const RHS &R) {
607}
608
609template <typename LHS, typename RHS>
611m_GXor(const LHS &L, const RHS &R) {
613}
614
615template <typename LHS, typename RHS>
617 const RHS &R) {
619}
620
621template <typename LHS, typename RHS>
622inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
624m_GDisjointOr(const LHS &L, const RHS &R) {
625 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
627}
628
629template <typename LHS, typename RHS>
630inline auto m_GAddLike(const LHS &L, const RHS &R) {
631 return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
632}
633
634template <typename LHS, typename RHS>
636m_GShl(const LHS &L, const RHS &R) {
638}
639
640template <typename LHS, typename RHS>
642m_GLShr(const LHS &L, const RHS &R) {
644}
645
646template <typename LHS, typename RHS>
648m_GAShr(const LHS &L, const RHS &R) {
650}
651
652template <typename LHS, typename RHS>
654m_GSMax(const LHS &L, const RHS &R) {
656}
657
658template <typename LHS, typename RHS>
660m_GSMin(const LHS &L, const RHS &R) {
662}
663
664template <typename LHS, typename RHS>
666m_GUMax(const LHS &L, const RHS &R) {
668}
669
670template <typename LHS, typename RHS>
672m_GUMin(const LHS &L, const RHS &R) {
674}
675
676// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
677template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
678 SrcTy L;
679
680 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
681 template <typename OpTy>
682 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
683 MachineInstr *TmpMI;
684 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
685 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
686 return L.match(MRI, TmpMI->getOperand(1).getReg());
687 }
688 }
689 return false;
690 }
691};
692
693template <typename SrcTy>
695m_GAnyExt(const SrcTy &Src) {
697}
698
699template <typename SrcTy>
702}
703
704template <typename SrcTy>
707}
708
709template <typename SrcTy>
712}
713
714template <typename SrcTy>
717}
718
719template <typename SrcTy>
721m_GBitcast(const SrcTy &Src) {
723}
724
725template <typename SrcTy>
727m_GPtrToInt(const SrcTy &Src) {
729}
730
731template <typename SrcTy>
733m_GIntToPtr(const SrcTy &Src) {
735}
736
737template <typename SrcTy>
739m_GFPTrunc(const SrcTy &Src) {
741}
742
743template <typename SrcTy>
746}
747
748template <typename SrcTy>
751}
752
753template <typename SrcTy>
755 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
756}
757
758template <typename SrcTy>
761}
762
763// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
764// TODO: Allow checking a specific predicate.
765template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
766 bool Commutable = false>
768 Pred_P P;
769 LHS_P L;
770 RHS_P R;
771
772 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
773 : P(Pred), L(LHS), R(RHS) {}
774
775 template <typename OpTy>
776 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
777 MachineInstr *TmpMI;
778 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
779 return false;
780
781 auto TmpPred =
782 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
783 if (!P.match(MRI, TmpPred))
784 return false;
785 Register LHS = TmpMI->getOperand(2).getReg();
786 Register RHS = TmpMI->getOperand(3).getReg();
787 if (L.match(MRI, LHS) && R.match(MRI, RHS))
788 return true;
789 // NOTE: When trying the alternative operand ordering
790 // with a commutative operation, it is imperative to always run
791 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
792 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
793 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
794 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
795 return true;
796 return false;
797 }
798};
799
800template <typename LHS_P, typename Test_P, unsigned Opcode>
802 LHS_P L;
803 Test_P T;
804
805 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
806
807 template <typename OpTy>
808 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
809 MachineInstr *TmpMI;
810 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
811 return false;
812
813 Register LHS = TmpMI->getOperand(1).getReg();
814 if (!L.match(MRI, LHS))
815 return false;
816
817 FPClassTest TmpClass =
818 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
819 if (T.match(MRI, TmpClass))
820 return true;
821
822 return false;
823 }
824};
825
826template <typename Pred, typename LHS, typename RHS>
828m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
830}
831
832template <typename Pred, typename LHS, typename RHS>
834m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
836}
837
838/// G_ICMP matcher that also matches commuted compares.
839/// E.g.
840///
841/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
842///
843/// Could match both of:
844///
845/// icmp ugt (add x, y) (sub a, b)
846/// icmp ult (sub a, b) (add x, y)
847template <typename Pred, typename LHS, typename RHS>
849m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
851}
852
853/// G_FCMP matcher that also matches commuted compares.
854/// E.g.
855///
856/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
857///
858/// Could match both of:
859///
860/// fcmp ogt (fadd x, y) (fmul a, b)
861/// fcmp olt (fmul a, b) (fadd x, y)
862template <typename Pred, typename LHS, typename RHS>
864m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
866}
867
868/// Matches the register and immediate used in a fpclass test
869/// G_IS_FPCLASS %val, 96
870template <typename LHS, typename Test>
872m_GIsFPClass(const LHS &L, const Test &T) {
874}
875
876// Helper for checking if a Reg is of specific type.
877struct CheckType {
879 CheckType(const LLT Ty) : Ty(Ty) {}
880
882 return MRI.getType(Reg) == Ty;
883 }
884};
885
886inline CheckType m_SpecificType(LLT Ty) { return Ty; }
887
888template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
890 Src0Ty Src0;
891 Src1Ty Src1;
892 Src2Ty Src2;
893
894 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
895 : Src0(Src0), Src1(Src1), Src2(Src2) {}
896 template <typename OpTy>
897 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
898 MachineInstr *TmpMI;
899 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
900 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
901 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
902 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
903 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
904 }
905 }
906 return false;
907 }
908};
909template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
910inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
911 TargetOpcode::G_INSERT_VECTOR_ELT>
912m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
913 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
914 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
915}
916
917template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
919m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
921 Src0, Src1, Src2);
922}
923
924/// Matches a register negated by a G_SUB.
925/// G_SUB 0, %negated_reg
926template <typename SrcTy>
928m_Neg(const SrcTy &&Src) {
929 return m_GSub(m_ZeroInt(), Src);
930}
931
932/// Matches a register not-ed by a G_XOR.
933/// G_XOR %not_reg, -1
934template <typename SrcTy>
936m_Not(const SrcTy &&Src) {
937 return m_GXor(Src, m_AllOnesInt());
938}
939
940} // namespace MIPatternMatch
941} // namespace llvm
942
943#endif
unsigned const MachineRegisterInfo * MRI
aarch64 promote const
This file implements a class to represent arbitrary precision integral constant values and operations...
Utilities for dealing with flags related to floating point properties and mode controls.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
Register Reg
#define T
#define P(N)
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition: APInt.h:234
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1488
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition: APInt.cpp:985
static bool isSameValue(const APInt &I1, const APInt &I2)
Determine if two APInts have the same value, after zero-extending one of them (if needed!...
Definition: APInt.h:553
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition: APInt.h:200
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:678
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition: InstrTypes.h:829
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:277
This class represents an Operation in the Expression.
constexpr bool isValid() const
Definition: LowLevelType.h:146
Representation of each machine instruction.
Definition: MachineInstr.h:72
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:587
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:590
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:595
uint32_t getFlags() const
Return the MI flags bitvector.
Definition: MachineInstr.h:404
unsigned getNumDefs() const
Returns the total number of definitions.
Definition: MachineInstr.h:637
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
unsigned getPredicate() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
operand_type_match m_Reg()
std::optional< ConstT > matchConstantSplat(Register, const MachineRegisterInfo &)
auto m_GAddLike(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_BUILD_VECTOR, false > m_GBuildVector(const LHS &L, const RHS &R)
SpecificConstantOrSplatMatch m_SpecificICstOrSplat(APInt RequestedValue)
Matches a RequestedValue constant or a constant splat of RequestedValue.
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
operand_type_match m_Pred()
BinaryOp_match< LHS, RHS, TargetOpcode::G_UMIN, true > m_GUMin(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_XOR, true > m_GXor(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
deferred_ty< LLT > m_DeferredType(LLT &Ty)
UnaryOp_match< SrcTy, TargetOpcode::G_FPEXT > m_GFPExt(const SrcTy &Src)
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ConstantMatch< APInt > m_ICst(APInt &Cst)
UnaryOp_match< SrcTy, TargetOpcode::G_FSQRT > m_GFSqrt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_INTTOPTR > m_GIntToPtr(const SrcTy &Src)
SpecificConstantMatch m_AllOnesInt()
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true, MachineInstr::Disjoint > m_GDisjointOr(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ADD, true > m_GAdd(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
bind_ty< FPClassTest > m_FPClassTest(FPClassTest &T)
ImplicitDefMatch m_GImplicitDef()
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
CheckType m_SpecificType(LLT Ty)
deferred_ty< Register > m_DeferredReg(Register &R)
Similar to m_SpecificReg/Type, but the specific value to match originated from an earlier sub-pattern...
BinaryOp_match< LHS, RHS, TargetOpcode::G_UMAX, true > m_GUMax(const LHS &L, const RHS &R)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
BinaryOpc_match< LHS, RHS, true > m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R)
SpecificConstantSplatMatch m_SpecificICstSplat(APInt RequestedValue)
Matches a constant splat of RequestedValue.
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FADD, true > m_GFAdd(const LHS &L, const RHS &R)
SpecificConstantMatch m_SpecificICst(APInt RequestedValue)
Matches a constant equal to RequestedValue.
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP, true > m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R)
G_FCMP matcher that also matches commuted compares.
UnaryOp_match< SrcTy, TargetOpcode::G_PTRTOINT > m_GPtrToInt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FSUB, false > m_GFSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
TernaryOp_match< Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT > m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
SpecificRegisterMatch m_SpecificReg(Register RequestedReg)
Matches a register only if it is equal to RequestedReg.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_BUILD_VECTOR_TRUNC, false > m_GBuildVectorTrunc(const LHS &L, const RHS &R)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP, true > m_c_GICmp(const Pred &P, const LHS &L, const RHS &R)
G_ICMP matcher that also matches commuted compares.
GFCstAndRegMatch m_GFCst(std::optional< FPValueAndVReg > &FPValReg)
ClassifyOp_match< LHS, Test, TargetOpcode::G_IS_FPCLASS > m_GIsFPClass(const LHS &L, const Test &T)
Matches the register and immediate used in a fpclass test G_IS_FPCLASS val, 96.
TernaryOp_match< Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_INSERT_VECTOR_ELT > m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
And< Preds... > m_all_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMIN, true > m_GSMin(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_FABS > m_GFabs(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_FPTRUNC > m_GFPTrunc(const SrcTy &Src)
std::optional< ConstT > matchConstant(Register, const MachineRegisterInfo &)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_FMUL, true > m_GFMul(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_MUL, true > m_GMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
bind_ty< LLT > m_Type(LLT &Ty)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMAX, true > m_GSMax(const LHS &L, const RHS &R)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
Definition: PatternMatch.h:100
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:459
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition: Utils.cpp:294
LLVM_ABI std::optional< APInt > getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:1440
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
Definition: Utils.cpp:314
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI std::optional< FPValueAndVReg > getFConstantSplat(Register VReg, const MachineRegisterInfo &MRI, bool AllowUndef=true)
Returns a floating point scalar constant of a build vector splat if it exists.
Definition: Utils.cpp:1473
LLVM_ABI std::optional< FPValueAndVReg > getFConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_FCONSTANT returns it...
Definition: Utils.cpp:447
LLVM_ABI bool isBuildVectorConstantSplat(const Register Reg, const MachineRegisterInfo &MRI, int64_t SplatValue, bool AllowUndef)
Return true if the specified register is defined by G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all ...
Definition: Utils.cpp:1401
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Definition: Utils.cpp:433
LLVM_ABI std::optional< int64_t > getIConstantSplatSExtVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:1458
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
Matching combinators.
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
bool match(const MachineRegisterInfo &MRI, Register Reg)
ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
bool match(const MachineRegisterInfo &MRI, Register Reg)
bool match(const MachineRegisterInfo &MRI, Register Reg)
GCstAndRegMatch(std::optional< ValueAndVReg > &ValReg)
std::optional< ValueAndVReg > & ValReg
GFCstAndRegMatch(std::optional< FPValueAndVReg > &FPValReg)
std::optional< FPValueAndVReg > & FPValReg
bool match(const MachineRegisterInfo &MRI, Register Reg)
GFCstOrSplatGFCstMatch(std::optional< FPValueAndVReg > &FPValReg)
bool match(const MachineRegisterInfo &MRI, Register Reg)
std::optional< FPValueAndVReg > & FPValReg
bool match(const MachineRegisterInfo &MRI, Register Reg)
bool match(const MachineRegisterInfo &MRI, Register Reg)
OneNonDBGUse_match(const SubPatternT &SP)
bool match(const MachineRegisterInfo &MRI, Register Reg)
OneUse_match(const SubPatternT &SP)
bool match(const MachineRegisterInfo &MRI, Register Reg)
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
Matcher for a specific constant value.
bool match(const MachineRegisterInfo &MRI, Register Reg)
SpecificConstantMatch(const APInt RequestedVal)
Matcher for a specific constant or constant splat.
bool match(const MachineRegisterInfo &MRI, Register Reg)
Matcher for a specific constant splat.
bool match(const MachineRegisterInfo &MRI, Register Reg)
SpecificConstantSplatMatch(const APInt RequestedVal)
Matcher for a specific register.
bool match(const MachineRegisterInfo &MRI, Register Reg)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg)
static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI, Register Reg)
static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI, MachineInstr *Inst)
static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F, Register Reg)
static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI, Register Reg)
static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI, const MachineInstr *Inst)
static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V)
bool match(const MachineRegisterInfo &MRI, ITy &&V)
static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R)
static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V)
bool match(const MachineRegisterInfo &MRI, ITy &&V)
bool match(const MachineRegisterInfo &MRI, MachineOperand *MO)
bool match(const MachineRegisterInfo &MRI, Register Reg)