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>
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
146
148 return ICstOrSplatMatch<int64_t>(Cst);
149}
150
152 std::optional<ValueAndVReg> &ValReg;
153 GCstAndRegMatch(std::optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
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) {}
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) {}
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())
202 RequestedVal = RequestedVal.sext(MatchedVal.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.
213inline SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue) {
214 return SpecificConstantMatch(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.
231
232/// Matches a constant splat of \p RequestedValue.
234m_SpecificICstSplat(const APInt &RequestedValue) {
235 return SpecificConstantSplatMatch(RequestedValue);
236}
237
238inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
240 APInt(64, RequestedValue, /* isSigned */ true));
241}
242
243/// Matcher for a specific constant or constant splat.
249 APInt MatchedVal;
250 if (mi_match(Reg, MRI, m_ICst(MatchedVal))) {
251 if (MatchedVal.getBitWidth() > RequestedVal.getBitWidth())
252 RequestedVal = RequestedVal.sext(MatchedVal.getBitWidth());
253 else
254 MatchedVal = MatchedVal.sext(RequestedVal.getBitWidth());
255
256 if (APInt::isSameValue(MatchedVal, RequestedVal))
257 return true;
258 }
260 /* AllowUndef */ false);
261 }
262};
263
264/// Matches a \p RequestedValue constant or a constant splat of \p
265/// RequestedValue.
267m_SpecificICstOrSplat(const APInt &RequestedValue) {
268 return SpecificConstantOrSplatMatch(RequestedValue);
269}
270
272m_SpecificICstOrSplat(int64_t RequestedValue) {
274 APInt(64, RequestedValue, /* isSigned */ true));
275}
276
277/// Convenience matchers for specific integer values.
284
285/// Matcher for a specific register.
293
294/// Matches a register only if it is equal to \p RequestedReg.
296 return SpecificRegisterMatch(RequestedReg);
297}
298
299// TODO: Rework this for different kinds of MachineOperand.
300// Currently assumes the Src for a match is a register.
301// We might want to support taking in some MachineOperands and call getReg on
302// that.
303
305 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
307 return MO->isReg();
308 }
309};
310
312
313/// Matching combinators.
314template <typename... Preds> struct And {
315 template <typename MatchSrc>
316 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
317 return true;
318 }
319};
320
321template <typename Pred, typename... Preds>
322struct And<Pred, Preds...> : And<Preds...> {
323 Pred P;
324 And(Pred &&p, Preds &&... preds)
325 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
326 }
327 template <typename MatchSrc>
328 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
329 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
330 }
331};
332
333template <typename... Preds> struct Or {
334 template <typename MatchSrc>
335 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
336 return false;
337 }
338};
339
340template <typename Pred, typename... Preds>
341struct Or<Pred, Preds...> : Or<Preds...> {
342 Pred P;
343 Or(Pred &&p, Preds &&... preds)
344 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
345 template <typename MatchSrc>
346 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
347 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
348 }
349};
350
351template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
352 return And<Preds...>(std::forward<Preds>(preds)...);
353}
354
355template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
356 return Or<Preds...>(std::forward<Preds>(preds)...);
357}
358
359template <typename BindTy> struct bind_helper {
360 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
361 VR = V;
362 return true;
363 }
364};
365
366template <> struct bind_helper<MachineInstr *> {
368 Register Reg) {
369 MI = MRI.getVRegDef(Reg);
370 if (MI)
371 return true;
372 return false;
373 }
375 MachineInstr *Inst) {
376 MI = Inst;
377 return MI;
378 }
379};
380
381template <> struct bind_helper<const MachineInstr *> {
382 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
383 Register Reg) {
384 MI = MRI.getVRegDef(Reg);
385 return MI;
386 }
387 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
388 const MachineInstr *Inst) {
389 MI = Inst;
390 return MI;
391 }
392};
393
394template <> struct bind_helper<LLT> {
395 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
396 Ty = MRI.getType(Reg);
397 if (Ty.isValid())
398 return true;
399 return false;
400 }
401};
402
403template <> struct bind_helper<const ConstantFP *> {
404 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
405 Register Reg) {
407 if (F)
408 return true;
409 return false;
410 }
411};
412
413template <typename Class> struct bind_ty {
414 Class &VR;
415
416 bind_ty(Class &V) : VR(V) {}
417
418 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
419 return bind_helper<Class>::bind(MRI, VR, V);
420 }
421};
422
423inline bind_ty<Register> m_Reg(Register &R) { return R; }
426 return MI;
427}
428inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
432
433template <typename BindTy> struct deferred_helper {
434 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
435 return VR == V;
436 }
437};
438
439template <> struct deferred_helper<LLT> {
440 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
441 return VT == MRI.getType(R);
442 }
443};
444
445template <typename Class> struct deferred_ty {
446 Class &VR;
447
448 deferred_ty(Class &V) : VR(V) {}
449
450 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
452 }
453};
454
455/// Similar to m_SpecificReg/Type, but the specific value to match originated
456/// from an earlier sub-pattern in the same mi_match expression. For example,
457/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
458/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
459/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
461inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
462
465 MachineInstr *TmpMI;
466 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
467 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
468 return false;
469 }
470};
471
473
474// Helper for matching G_FCONSTANT
476
477// General helper for all the binary generic MI such as G_ADD/G_SUB etc
478template <typename LHS_P, typename RHS_P, unsigned Opcode,
479 bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
481 LHS_P L;
482 RHS_P R;
483
484 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
485 template <typename OpTy>
486 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
487 const MachineInstr *TmpMI;
488 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
489 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
490 if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
491 !R.match(MRI, TmpMI->getOperand(2).getReg())) &&
492 // NOTE: When trying the alternative operand ordering
493 // with a commutative operation, it is imperative to always run
494 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
495 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
496 // expected.
497 (!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
498 !R.match(MRI, TmpMI->getOperand(1).getReg())))
499 return false;
500 return (TmpMI->getFlags() & Flags) == Flags;
501 }
502 }
503 return false;
504 }
505};
506
507// Helper for (commutative) binary generic MI that checks Opcode.
508template <typename LHS_P, typename RHS_P, bool Commutable = false>
510 unsigned Opc;
511 LHS_P L;
512 RHS_P R;
513
514 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
515 : Opc(Opcode), L(LHS), R(RHS) {}
516 template <typename OpTy>
517 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
518 MachineInstr *TmpMI;
519 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
520 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
521 TmpMI->getNumOperands() == 3) {
522 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
523 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
524 // NOTE: When trying the alternative operand ordering
525 // with a commutative operation, it is imperative to always run
526 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
527 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
528 // expected.
529 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
530 R.match(MRI, TmpMI->getOperand(1).getReg())));
531 }
532 }
533 return false;
534 }
535};
536
537template <typename LHS, typename RHS>
538inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
539 const RHS &R) {
540 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
541}
542
543template <typename LHS, typename RHS>
545m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
546 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
547}
548
549template <typename LHS, typename RHS>
551m_GAdd(const LHS &L, const RHS &R) {
553}
554
555template <typename LHS, typename RHS>
560
561template <typename LHS, typename RHS>
567
568template <typename LHS, typename RHS>
573
574template <typename LHS, typename RHS>
579
580template <typename LHS, typename RHS>
582m_GMul(const LHS &L, const RHS &R) {
584}
585
586template <typename LHS, typename RHS>
588m_GFAdd(const LHS &L, const RHS &R) {
590}
591
592template <typename LHS, typename RHS>
594m_GFMul(const LHS &L, const RHS &R) {
596}
597
598template <typename LHS, typename RHS>
600m_GFSub(const LHS &L, const RHS &R) {
602}
603
604template <typename LHS, typename RHS>
606m_GAnd(const LHS &L, const RHS &R) {
608}
609
610template <typename LHS, typename RHS>
612m_GXor(const LHS &L, const RHS &R) {
614}
615
616template <typename LHS, typename RHS>
621
622template <typename LHS, typename RHS>
623inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
625m_GDisjointOr(const LHS &L, const RHS &R) {
626 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
628}
629
630template <typename LHS, typename RHS>
631inline auto m_GAddLike(const LHS &L, const RHS &R) {
632 return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
633}
634
635template <typename LHS, typename RHS>
637m_GShl(const LHS &L, const RHS &R) {
639}
640
641template <typename LHS, typename RHS>
643m_GLShr(const LHS &L, const RHS &R) {
645}
646
647template <typename LHS, typename RHS>
649m_GAShr(const LHS &L, const RHS &R) {
651}
652
653template <typename LHS, typename RHS>
655m_GSMax(const LHS &L, const RHS &R) {
657}
658
659template <typename LHS, typename RHS>
661m_GSMin(const LHS &L, const RHS &R) {
663}
664
665template <typename LHS, typename RHS>
667m_GUMax(const LHS &L, const RHS &R) {
669}
670
671template <typename LHS, typename RHS>
673m_GUMin(const LHS &L, const RHS &R) {
675}
676
677// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
678template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
679 SrcTy L;
680
681 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
682 template <typename OpTy>
683 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
684 MachineInstr *TmpMI;
685 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
686 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
687 return L.match(MRI, TmpMI->getOperand(1).getReg());
688 }
689 }
690 return false;
691 }
692};
693
694template <typename SrcTy>
696m_GAnyExt(const SrcTy &Src) {
698}
699
700template <typename SrcTy>
704
705template <typename SrcTy>
709
710template <typename SrcTy>
714
715template <typename SrcTy>
719
720template <typename SrcTy>
722m_GBitcast(const SrcTy &Src) {
724}
725
726template <typename SrcTy>
728m_GPtrToInt(const SrcTy &Src) {
730}
731
732template <typename SrcTy>
734m_GIntToPtr(const SrcTy &Src) {
736}
737
738template <typename SrcTy>
740m_GFPTrunc(const SrcTy &Src) {
742}
743
744template <typename SrcTy>
748
749template <typename SrcTy>
753
754template <typename SrcTy>
756 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
757}
758
759template <typename SrcTy>
763
764// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
765// TODO: Allow checking a specific predicate.
766template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
767 bool Commutable = false>
769 Pred_P P;
770 LHS_P L;
771 RHS_P R;
772
773 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
774 : P(Pred), L(LHS), R(RHS) {}
775
776 template <typename OpTy>
777 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
778 MachineInstr *TmpMI;
779 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
780 return false;
781
782 auto TmpPred =
783 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
784 if (!P.match(MRI, TmpPred))
785 return false;
786 Register LHS = TmpMI->getOperand(2).getReg();
787 Register RHS = TmpMI->getOperand(3).getReg();
788 if (L.match(MRI, LHS) && R.match(MRI, RHS))
789 return true;
790 // NOTE: When trying the alternative operand ordering
791 // with a commutative operation, it is imperative to always run
792 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
793 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
794 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
795 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
796 return true;
797 return false;
798 }
799};
800
801template <typename LHS_P, typename Test_P, unsigned Opcode>
803 LHS_P L;
804 Test_P T;
805
806 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
807
808 template <typename OpTy>
809 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
810 MachineInstr *TmpMI;
811 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
812 return false;
813
814 Register LHS = TmpMI->getOperand(1).getReg();
815 if (!L.match(MRI, LHS))
816 return false;
817
818 FPClassTest TmpClass =
819 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
820 if (T.match(MRI, TmpClass))
821 return true;
822
823 return false;
824 }
825};
826
827template <typename Pred, typename LHS, typename RHS>
829m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
831}
832
833template <typename Pred, typename LHS, typename RHS>
835m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
837}
838
839/// G_ICMP matcher that also matches commuted compares.
840/// E.g.
841///
842/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
843///
844/// Could match both of:
845///
846/// icmp ugt (add x, y) (sub a, b)
847/// icmp ult (sub a, b) (add x, y)
848template <typename Pred, typename LHS, typename RHS>
850m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
852}
853
854/// G_FCMP matcher that also matches commuted compares.
855/// E.g.
856///
857/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
858///
859/// Could match both of:
860///
861/// fcmp ogt (fadd x, y) (fmul a, b)
862/// fcmp olt (fmul a, b) (fadd x, y)
863template <typename Pred, typename LHS, typename RHS>
865m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
867}
868
869/// Matches the register and immediate used in a fpclass test
870/// G_IS_FPCLASS %val, 96
871template <typename LHS, typename Test>
876
877// Helper for checking if a Reg is of specific type.
878struct CheckType {
880 CheckType(const LLT Ty) : Ty(Ty) {}
881
883 return MRI.getType(Reg) == Ty;
884 }
885};
886
887inline CheckType m_SpecificType(LLT Ty) { return Ty; }
888
889template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
891 Src0Ty Src0;
892 Src1Ty Src1;
893 Src2Ty Src2;
894
895 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
896 : Src0(Src0), Src1(Src1), Src2(Src2) {}
897 template <typename OpTy>
898 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
899 MachineInstr *TmpMI;
900 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
901 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
902 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
903 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
904 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
905 }
906 }
907 return false;
908 }
909};
910template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
911inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
912 TargetOpcode::G_INSERT_VECTOR_ELT>
913m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
914 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
915 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
916}
917
918template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
920m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
922 Src0, Src1, Src2);
923}
924
925/// Matches a register negated by a G_SUB.
926/// G_SUB 0, %negated_reg
927template <typename SrcTy>
929m_Neg(const SrcTy &&Src) {
930 return m_GSub(m_ZeroInt(), Src);
931}
932
933/// Matches a register not-ed by a G_XOR.
934/// G_XOR %not_reg, -1
935template <typename SrcTy>
937m_Not(const SrcTy &&Src) {
938 return m_GXor(Src, m_AllOnesInt());
939}
940
941} // namespace MIPatternMatch
942} // namespace llvm
943
944#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:235
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1489
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:554
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:201
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:827
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:277
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
unsigned getNumDefs() const
Returns the total number of definitions.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
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)
SpecificConstantSplatMatch m_SpecificICstSplat(const APInt &RequestedValue)
Matches 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)
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)
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)
SpecificConstantOrSplatMatch m_SpecificICstOrSplat(const APInt &RequestedValue)
Matches a RequestedValue constant or a constant splat of RequestedValue.
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.
This is an optimization pass for GlobalISel generic memory operations.
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:1441
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
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
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:1474
DWARFExpression::Operation Op
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:1400
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:1459
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
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)
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.
SpecificConstantMatch(const APInt &RequestedVal)
bool match(const MachineRegisterInfo &MRI, Register Reg)
Matcher for a specific constant or constant splat.
bool match(const MachineRegisterInfo &MRI, Register Reg)
Matcher for a specific constant splat.
SpecificConstantSplatMatch(const APInt &RequestedVal)
bool match(const MachineRegisterInfo &MRI, Register Reg)
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)