LLVM 20.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"
19#include "llvm/IR/InstrTypes.h"
20
21namespace llvm {
22namespace MIPatternMatch {
23
24template <typename Reg, typename Pattern>
25[[nodiscard]] bool mi_match(Reg R, const MachineRegisterInfo &MRI,
26 Pattern &&P) {
27 return P.match(MRI, R);
28}
29
30template <typename Pattern>
31[[nodiscard]] bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI,
32 Pattern &&P) {
33 return P.match(MRI, &MI);
34}
35
36// TODO: Extend for N use.
37template <typename SubPatternT> struct OneUse_match {
38 SubPatternT SubPat;
39 OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
40
42 return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg);
43 }
44};
45
46template <typename SubPat>
47inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
48 return SP;
49}
50
51template <typename SubPatternT> struct OneNonDBGUse_match {
52 SubPatternT SubPat;
53 OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {}
54
56 return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
57 }
58};
59
60template <typename SubPat>
62 return SP;
63}
64
65template <typename ConstT>
66inline std::optional<ConstT> matchConstant(Register,
67 const MachineRegisterInfo &);
68
69template <>
70inline std::optional<APInt> matchConstant(Register Reg,
71 const MachineRegisterInfo &MRI) {
73}
74
75template <>
76inline std::optional<int64_t> matchConstant(Register Reg,
77 const MachineRegisterInfo &MRI) {
79}
80
81template <typename ConstT> struct ConstantMatch {
82 ConstT &CR;
83 ConstantMatch(ConstT &C) : CR(C) {}
85 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
86 CR = *MaybeCst;
87 return true;
88 }
89 return false;
90 }
91};
92
94 return ConstantMatch<APInt>(Cst);
95}
96inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
97 return ConstantMatch<int64_t>(Cst);
98}
99
100template <typename ConstT>
101inline std::optional<ConstT> matchConstantSplat(Register,
102 const MachineRegisterInfo &);
103
104template <>
105inline std::optional<APInt> matchConstantSplat(Register Reg,
106 const MachineRegisterInfo &MRI) {
108}
109
110template <>
111inline std::optional<int64_t>
114}
115
116template <typename ConstT> struct ICstOrSplatMatch {
117 ConstT &CR;
118 ICstOrSplatMatch(ConstT &C) : CR(C) {}
120 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
121 CR = *MaybeCst;
122 return true;
123 }
124
125 if (auto MaybeCstSplat = matchConstantSplat<ConstT>(Reg, MRI)) {
126 CR = *MaybeCstSplat;
127 return true;
128 }
129
130 return false;
131 };
132};
133
135 return ICstOrSplatMatch<APInt>(Cst);
136}
137
139 return ICstOrSplatMatch<int64_t>(Cst);
140}
141
143 std::optional<ValueAndVReg> &ValReg;
144 GCstAndRegMatch(std::optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
147 return ValReg ? true : false;
148 }
149};
150
151inline GCstAndRegMatch m_GCst(std::optional<ValueAndVReg> &ValReg) {
152 return GCstAndRegMatch(ValReg);
153}
154
156 std::optional<FPValueAndVReg> &FPValReg;
157 GFCstAndRegMatch(std::optional<FPValueAndVReg> &FPValReg)
158 : FPValReg(FPValReg) {}
161 return FPValReg ? true : false;
162 }
163};
164
165inline GFCstAndRegMatch m_GFCst(std::optional<FPValueAndVReg> &FPValReg) {
166 return GFCstAndRegMatch(FPValReg);
167}
168
170 std::optional<FPValueAndVReg> &FPValReg;
171 GFCstOrSplatGFCstMatch(std::optional<FPValueAndVReg> &FPValReg)
172 : FPValReg(FPValReg) {}
174 return (FPValReg = getFConstantSplat(Reg, MRI)) ||
176 };
177};
178
179inline GFCstOrSplatGFCstMatch
180m_GFCstOrSplat(std::optional<FPValueAndVReg> &FPValReg) {
181 return GFCstOrSplatGFCstMatch(FPValReg);
182}
183
184/// Matcher for a specific constant value.
189 int64_t MatchedVal;
190 return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal;
191 }
192};
193
194/// Matches a constant equal to \p RequestedValue.
195inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
196 return SpecificConstantMatch(RequestedValue);
197}
198
199/// Matcher for a specific constant splat.
206 /* AllowUndef */ false);
207 }
208};
209
210/// Matches a constant splat of \p RequestedValue.
211inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
212 return SpecificConstantSplatMatch(RequestedValue);
213}
214
215/// Matcher for a specific constant or constant splat.
221 int64_t MatchedVal;
222 if (mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal)
223 return true;
225 /* AllowUndef */ false);
226 }
227};
228
229/// Matches a \p RequestedValue constant or a constant splat of \p
230/// RequestedValue.
231inline SpecificConstantOrSplatMatch
232m_SpecificICstOrSplat(int64_t RequestedValue) {
233 return SpecificConstantOrSplatMatch(RequestedValue);
234}
235
236///{
237/// Convenience matchers for specific integer values.
240 return SpecificConstantMatch(-1);
241}
242///}
243
244/// Matcher for a specific register.
249 return Reg == RequestedReg;
250 }
251};
252
253/// Matches a register only if it is equal to \p RequestedReg.
255 return SpecificRegisterMatch(RequestedReg);
256}
257
258// TODO: Rework this for different kinds of MachineOperand.
259// Currently assumes the Src for a match is a register.
260// We might want to support taking in some MachineOperands and call getReg on
261// that.
262
264 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
266 return MO->isReg();
267 }
268};
269
271
272/// Matching combinators.
273template <typename... Preds> struct And {
274 template <typename MatchSrc>
275 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
276 return true;
277 }
278};
279
280template <typename Pred, typename... Preds>
281struct And<Pred, Preds...> : And<Preds...> {
282 Pred P;
283 And(Pred &&p, Preds &&... preds)
284 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
285 }
286 template <typename MatchSrc>
287 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
288 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
289 }
290};
291
292template <typename... Preds> struct Or {
293 template <typename MatchSrc>
294 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
295 return false;
296 }
297};
298
299template <typename Pred, typename... Preds>
300struct Or<Pred, Preds...> : Or<Preds...> {
301 Pred P;
302 Or(Pred &&p, Preds &&... preds)
303 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
304 template <typename MatchSrc>
305 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
306 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
307 }
308};
309
310template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
311 return And<Preds...>(std::forward<Preds>(preds)...);
312}
313
314template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
315 return Or<Preds...>(std::forward<Preds>(preds)...);
316}
317
318template <typename BindTy> struct bind_helper {
319 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
320 VR = V;
321 return true;
322 }
323};
324
325template <> struct bind_helper<MachineInstr *> {
327 Register Reg) {
328 MI = MRI.getVRegDef(Reg);
329 if (MI)
330 return true;
331 return false;
332 }
334 MachineInstr *Inst) {
335 MI = Inst;
336 return MI;
337 }
338};
339
340template <> struct bind_helper<LLT> {
341 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
342 Ty = MRI.getType(Reg);
343 if (Ty.isValid())
344 return true;
345 return false;
346 }
347};
348
349template <> struct bind_helper<const ConstantFP *> {
350 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
351 Register Reg) {
353 if (F)
354 return true;
355 return false;
356 }
357};
358
359template <typename Class> struct bind_ty {
360 Class &VR;
361
362 bind_ty(Class &V) : VR(V) {}
363
364 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
365 return bind_helper<Class>::bind(MRI, VR, V);
366 }
367};
368
369inline bind_ty<Register> m_Reg(Register &R) { return R; }
371inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
374
375template <typename BindTy> struct deferred_helper {
376 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
377 return VR == V;
378 }
379};
380
381template <> struct deferred_helper<LLT> {
382 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
383 return VT == MRI.getType(R);
384 }
385};
386
387template <typename Class> struct deferred_ty {
388 Class &VR;
389
390 deferred_ty(Class &V) : VR(V) {}
391
392 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
394 }
395};
396
397/// Similar to m_SpecificReg/Type, but the specific value to match originated
398/// from an earlier sub-pattern in the same mi_match expression. For example,
399/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
400/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
401/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
403inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
404
407 MachineInstr *TmpMI;
408 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
409 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
410 return false;
411 }
412};
413
415
416// Helper for matching G_FCONSTANT
418
419// General helper for all the binary generic MI such as G_ADD/G_SUB etc
420template <typename LHS_P, typename RHS_P, unsigned Opcode,
421 bool Commutable = false>
423 LHS_P L;
424 RHS_P R;
425
426 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
427 template <typename OpTy>
428 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
429 MachineInstr *TmpMI;
430 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
431 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
432 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
433 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
434 // NOTE: When trying the alternative operand ordering
435 // with a commutative operation, it is imperative to always run
436 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
437 // (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
438 // expected.
439 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
440 R.match(MRI, TmpMI->getOperand(1).getReg())));
441 }
442 }
443 return false;
444 }
445};
446
447// Helper for (commutative) binary generic MI that checks Opcode.
448template <typename LHS_P, typename RHS_P, bool Commutable = false>
450 unsigned Opc;
451 LHS_P L;
452 RHS_P R;
453
454 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
455 : Opc(Opcode), L(LHS), R(RHS) {}
456 template <typename OpTy>
457 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
458 MachineInstr *TmpMI;
459 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
460 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
461 TmpMI->getNumOperands() == 3) {
462 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
463 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
464 // NOTE: When trying the alternative operand ordering
465 // with a commutative operation, it is imperative to always run
466 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
467 // (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as
468 // expected.
469 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
470 R.match(MRI, TmpMI->getOperand(1).getReg())));
471 }
472 }
473 return false;
474 }
475};
476
477template <typename LHS, typename RHS>
478inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
479 const RHS &R) {
480 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
481}
482
483template <typename LHS, typename RHS>
484inline BinaryOpc_match<LHS, RHS, true>
485m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
486 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
487}
488
489template <typename LHS, typename RHS>
491m_GAdd(const LHS &L, const RHS &R) {
493}
494
495template <typename LHS, typename RHS>
497m_GBuildVector(const LHS &L, const RHS &R) {
499}
500
501template <typename LHS, typename RHS>
503m_GBuildVectorTrunc(const LHS &L, const RHS &R) {
505 R);
506}
507
508template <typename LHS, typename RHS>
510m_GPtrAdd(const LHS &L, const RHS &R) {
512}
513
514template <typename LHS, typename RHS>
516 const RHS &R) {
518}
519
520template <typename LHS, typename RHS>
522m_GMul(const LHS &L, const RHS &R) {
524}
525
526template <typename LHS, typename RHS>
528m_GFAdd(const LHS &L, const RHS &R) {
530}
531
532template <typename LHS, typename RHS>
534m_GFMul(const LHS &L, const RHS &R) {
536}
537
538template <typename LHS, typename RHS>
540m_GFSub(const LHS &L, const RHS &R) {
542}
543
544template <typename LHS, typename RHS>
546m_GAnd(const LHS &L, const RHS &R) {
548}
549
550template <typename LHS, typename RHS>
552m_GXor(const LHS &L, const RHS &R) {
554}
555
556template <typename LHS, typename RHS>
558 const RHS &R) {
560}
561
562template <typename LHS, typename RHS>
564m_GShl(const LHS &L, const RHS &R) {
566}
567
568template <typename LHS, typename RHS>
570m_GLShr(const LHS &L, const RHS &R) {
572}
573
574template <typename LHS, typename RHS>
576m_GAShr(const LHS &L, const RHS &R) {
578}
579
580template <typename LHS, typename RHS>
582m_GSMax(const LHS &L, const RHS &R) {
584}
585
586template <typename LHS, typename RHS>
588m_GSMin(const LHS &L, const RHS &R) {
590}
591
592template <typename LHS, typename RHS>
594m_GUMax(const LHS &L, const RHS &R) {
596}
597
598template <typename LHS, typename RHS>
600m_GUMin(const LHS &L, const RHS &R) {
602}
603
604// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
605template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
606 SrcTy L;
607
608 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
609 template <typename OpTy>
610 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
611 MachineInstr *TmpMI;
612 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
613 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
614 return L.match(MRI, TmpMI->getOperand(1).getReg());
615 }
616 }
617 return false;
618 }
619};
620
621template <typename SrcTy>
622inline UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>
623m_GAnyExt(const SrcTy &Src) {
625}
626
627template <typename SrcTy>
630}
631
632template <typename SrcTy>
635}
636
637template <typename SrcTy>
640}
641
642template <typename SrcTy>
645}
646
647template <typename SrcTy>
648inline UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>
649m_GBitcast(const SrcTy &Src) {
651}
652
653template <typename SrcTy>
654inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>
655m_GPtrToInt(const SrcTy &Src) {
657}
658
659template <typename SrcTy>
660inline UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>
661m_GIntToPtr(const SrcTy &Src) {
663}
664
665template <typename SrcTy>
666inline UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>
667m_GFPTrunc(const SrcTy &Src) {
669}
670
671template <typename SrcTy>
674}
675
676template <typename SrcTy>
679}
680
681template <typename SrcTy>
683 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
684}
685
686template <typename SrcTy>
689}
690
691// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
692// TODO: Allow checking a specific predicate.
693template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
694 bool Commutable = false>
696 Pred_P P;
697 LHS_P L;
698 RHS_P R;
699
700 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
701 : P(Pred), L(LHS), R(RHS) {}
702
703 template <typename OpTy>
704 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
705 MachineInstr *TmpMI;
706 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
707 return false;
708
709 auto TmpPred =
710 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
711 if (!P.match(MRI, TmpPred))
712 return false;
713 Register LHS = TmpMI->getOperand(2).getReg();
714 Register RHS = TmpMI->getOperand(3).getReg();
715 if (L.match(MRI, LHS) && R.match(MRI, RHS))
716 return true;
717 // NOTE: When trying the alternative operand ordering
718 // with a commutative operation, it is imperative to always run
719 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
720 // (i.e. `R`). Otherwsie, m_DeferredReg/Type will not work as expected.
721 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
722 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
723 return true;
724 return false;
725 }
726};
727
728template <typename Pred, typename LHS, typename RHS>
729inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
730m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
732}
733
734template <typename Pred, typename LHS, typename RHS>
735inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>
736m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
738}
739
740/// G_ICMP matcher that also matches commuted compares.
741/// E.g.
742///
743/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
744///
745/// Could match both of:
746///
747/// icmp ugt (add x, y) (sub a, b)
748/// icmp ult (sub a, b) (add x, y)
749template <typename Pred, typename LHS, typename RHS>
750inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP, true>
751m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
753}
754
755/// G_FCMP matcher that also matches commuted compares.
756/// E.g.
757///
758/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
759///
760/// Could match both of:
761///
762/// fcmp ogt (fadd x, y) (fmul a, b)
763/// fcmp olt (fmul a, b) (fadd x, y)
764template <typename Pred, typename LHS, typename RHS>
765inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>
766m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
768}
769
770// Helper for checking if a Reg is of specific type.
771struct CheckType {
773 CheckType(const LLT Ty) : Ty(Ty) {}
774
776 return MRI.getType(Reg) == Ty;
777 }
778};
779
780inline CheckType m_SpecificType(LLT Ty) { return Ty; }
781
782template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
784 Src0Ty Src0;
785 Src1Ty Src1;
786 Src2Ty Src2;
787
788 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
789 : Src0(Src0), Src1(Src1), Src2(Src2) {}
790 template <typename OpTy>
791 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
792 MachineInstr *TmpMI;
793 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
794 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
795 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
796 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
797 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
798 }
799 }
800 return false;
801 }
802};
803template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
804inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
805 TargetOpcode::G_INSERT_VECTOR_ELT>
806m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
807 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
808 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
809}
810
811template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
812inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>
813m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
815 Src0, Src1, Src2);
816}
817
818/// Matches a register negated by a G_SUB.
819/// G_SUB 0, %negated_reg
820template <typename SrcTy>
822m_Neg(const SrcTy &&Src) {
823 return m_GSub(m_ZeroInt(), Src);
824}
825
826/// Matches a register not-ed by a G_XOR.
827/// G_XOR %not_reg, -1
828template <typename SrcTy>
830m_Not(const SrcTy &&Src) {
831 return m_GXor(Src, m_AllOnesInt());
832}
833
834} // namespace MIPatternMatch
835} // namespace llvm
836
837#endif
unsigned const MachineRegisterInfo * MRI
aarch64 promote const
This file implements a class to represent arbitrary precision integral constant values and operations...
basic Basic Alias true
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
unsigned Reg
#define P(N)
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:673
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition: InstrTypes.h:825
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:271
This class represents an Operation in the Expression.
constexpr bool isValid() const
Definition: LowLevelType.h:145
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:578
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
unsigned getNumDefs() const
Returns the total number of definitions.
Definition: MachineInstr.h:644
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.
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()
SpecificConstantOrSplatMatch m_SpecificICstOrSplat(int64_t RequestedValue)
Matches a RequestedValue constant or a constant splat of RequestedValue.
std::optional< ConstT > matchConstantSplat(Register, const MachineRegisterInfo &)
BinaryOp_match< LHS, RHS, TargetOpcode::G_BUILD_VECTOR, false > m_GBuildVector(const LHS &L, const RHS &R)
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
SpecificConstantMatch m_SpecificICst(int64_t RequestedValue)
Matches a constant equal to RequestedValue.
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_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)
SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue)
Matches a constant splat of RequestedValue.
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)
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)
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
const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:459
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
std::optional< APInt > getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:1400
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
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:1433
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
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:1384
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
std::optional< int64_t > getIConstantSplatSExtVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition: Utils.cpp:1418
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
Matching combinators.
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS)
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)
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)
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)
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, 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)