LLVM 23.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) {
81 return getIConstantVRegVal(Reg, MRI);
82}
83
84template <>
85inline std::optional<int64_t> matchConstant(Register Reg,
86 const MachineRegisterInfo &MRI) {
87 return getIConstantVRegSExtVal(Reg, 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) {
116 return getIConstantSplatVal(Reg, 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) {}
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())
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 *> {
367 static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
368 Register Reg) {
369 MI = MRI.getVRegDef(Reg);
370 if (MI)
371 return true;
372 return false;
373 }
374 static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
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) {
406 F = getConstantFPVRegVal(Reg, MRI);
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) {
451 return deferred_helper<Class>::match(MRI, VR, 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
764template <typename SrcTy>
766m_GFFloor(const SrcTy &Src) {
768}
769
770// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
771// TODO: Allow checking a specific predicate.
772template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
773 bool Commutable = false>
775 Pred_P P;
776 LHS_P L;
777 RHS_P R;
778
779 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
780 : P(Pred), L(LHS), R(RHS) {}
781
782 template <typename OpTy>
783 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
784 MachineInstr *TmpMI;
785 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
786 return false;
787
788 auto TmpPred =
789 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
790 if (!P.match(MRI, TmpPred))
791 return false;
792 Register LHS = TmpMI->getOperand(2).getReg();
793 Register RHS = TmpMI->getOperand(3).getReg();
794 if (L.match(MRI, LHS) && R.match(MRI, RHS))
795 return true;
796 // NOTE: When trying the alternative operand ordering
797 // with a commutative operation, it is imperative to always run
798 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
799 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
800 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
801 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
802 return true;
803 return false;
804 }
805};
806
807template <typename LHS_P, typename Test_P, unsigned Opcode>
809 LHS_P L;
810 Test_P T;
811
812 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
813
814 template <typename OpTy>
815 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
816 MachineInstr *TmpMI;
817 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
818 return false;
819
820 Register LHS = TmpMI->getOperand(1).getReg();
821 if (!L.match(MRI, LHS))
822 return false;
823
824 FPClassTest TmpClass =
825 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
826 if (T.match(MRI, TmpClass))
827 return true;
828
829 return false;
830 }
831};
832
833template <typename Pred, typename LHS, typename RHS>
835m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
837}
838
839template <typename Pred, typename LHS, typename RHS>
841m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
843}
844
845/// G_ICMP matcher that also matches commuted compares.
846/// E.g.
847///
848/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
849///
850/// Could match both of:
851///
852/// icmp ugt (add x, y) (sub a, b)
853/// icmp ult (sub a, b) (add x, y)
854template <typename Pred, typename LHS, typename RHS>
856m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
858}
859
860/// G_FCMP matcher that also matches commuted compares.
861/// E.g.
862///
863/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
864///
865/// Could match both of:
866///
867/// fcmp ogt (fadd x, y) (fmul a, b)
868/// fcmp olt (fmul a, b) (fadd x, y)
869template <typename Pred, typename LHS, typename RHS>
871m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
873}
874
875/// Matches the register and immediate used in a fpclass test
876/// G_IS_FPCLASS %val, 96
877template <typename LHS, typename Test>
882
883// Helper for checking if a Reg is of specific type.
884struct CheckType {
886 CheckType(const LLT Ty) : Ty(Ty) {}
887
889 return MRI.getType(Reg) == Ty;
890 }
891};
892
893inline CheckType m_SpecificType(LLT Ty) { return Ty; }
894
895template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
897 Src0Ty Src0;
898 Src1Ty Src1;
899 Src2Ty Src2;
900
901 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
902 : Src0(Src0), Src1(Src1), Src2(Src2) {}
903 template <typename OpTy>
904 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
905 MachineInstr *TmpMI;
906 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
907 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
908 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
909 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
910 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
911 }
912 }
913 return false;
914 }
915};
916template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
917inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
918 TargetOpcode::G_INSERT_VECTOR_ELT>
919m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
920 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
921 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
922}
923
924template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
926m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
928 Src0, Src1, Src2);
929}
930
931/// Matches a register negated by a G_SUB.
932/// G_SUB 0, %negated_reg
933template <typename SrcTy>
935m_Neg(const SrcTy &&Src) {
936 return m_GSub(m_ZeroInt(), Src);
937}
938
939/// Matches a register not-ed by a G_XOR.
940/// G_XOR %not_reg, -1
941template <typename SrcTy>
943m_Not(const SrcTy &&Src) {
944 return m_GXor(Src, m_AllOnesInt());
945}
946
947} // namespace MIPatternMatch
948} // namespace llvm
949
950#endif
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:54
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:1503
static bool isSameValue(const APInt &I1, const APInt &I2, bool SignedCompare=false)
Determine if two APInts have the same value, after zero-extending or sign-extending (if SignedCompare...
Definition APInt.h:555
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1016
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:420
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,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
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::G_FFLOOR > m_GFFloor(const SrcTy &Src)
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)
auto 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:460
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:293
LLVM_ABI std::optional< APInt > getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1383
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:313
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:1416
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:446
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:1342
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:432
LLVM_ABI std::optional< int64_t > getIConstantSplatSExtVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1401
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
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)