LLVM 24.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/// Matches a G_CONSTANT and binds the defining instruction. Unlike m_ICst, this
475/// returns the instruction (not the value) and does not look through vector
476/// splats.
477template <typename Class> struct GConstantMatch {
478 Class *&Inst;
479
482 MachineInstr *TmpMI;
483 if (mi_match(Reg, MRI, m_MInstr(TmpMI))) {
484 if (auto *Cst = dyn_cast<Class>(TmpMI)) {
485 Inst = Cst;
486 return true;
487 }
488 }
489 return false;
490 }
491};
492
493inline GConstantMatch<GConstant> m_GConstant(GConstant *&Inst) { return Inst; }
495 return Inst;
496}
497
498// Helper for matching G_FCONSTANT
500
501// General helper for all the binary generic MI such as G_ADD/G_SUB etc
502template <typename LHS_P, typename RHS_P, unsigned Opcode,
503 bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
505 LHS_P L;
506 RHS_P R;
507
508 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
509 template <typename OpTy>
510 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
511 const MachineInstr *TmpMI;
512 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
513 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
514 if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
515 !R.match(MRI, TmpMI->getOperand(2).getReg())) &&
516 // NOTE: When trying the alternative operand ordering
517 // with a commutative operation, it is imperative to always run
518 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
519 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
520 // expected.
521 (!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
522 !R.match(MRI, TmpMI->getOperand(1).getReg())))
523 return false;
524 return (TmpMI->getFlags() & Flags) == Flags;
525 }
526 }
527 return false;
528 }
529};
530
531// Helper for (commutative) binary generic MI that checks Opcode.
532template <typename LHS_P, typename RHS_P, bool Commutable = false>
534 unsigned Opc;
535 LHS_P L;
536 RHS_P R;
537
538 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
539 : Opc(Opcode), L(LHS), R(RHS) {}
540 template <typename OpTy>
541 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
542 MachineInstr *TmpMI;
543 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
544 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
545 TmpMI->getNumOperands() == 3) {
546 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
547 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
548 // NOTE: When trying the alternative operand ordering
549 // with a commutative operation, it is imperative to always run
550 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
551 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
552 // expected.
553 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
554 R.match(MRI, TmpMI->getOperand(1).getReg())));
555 }
556 }
557 return false;
558 }
559};
560
561template <typename LHS, typename RHS>
562inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
563 const RHS &R) {
564 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
565}
566
567template <typename LHS, typename RHS>
569m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
570 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
571}
572
573template <typename LHS, typename RHS>
575m_GAdd(const LHS &L, const RHS &R) {
577}
578
579template <typename LHS, typename RHS>
584
585template <typename LHS, typename RHS>
591
592template <typename LHS, typename RHS>
597
598template <typename LHS, typename RHS>
603
604template <typename LHS, typename RHS>
606m_GMul(const LHS &L, const RHS &R) {
608}
609
610template <typename LHS, typename RHS>
612m_GFAdd(const LHS &L, const RHS &R) {
614}
615
616template <typename LHS, typename RHS>
618m_GFMul(const LHS &L, const RHS &R) {
620}
621
622template <typename LHS, typename RHS>
624m_GFSub(const LHS &L, const RHS &R) {
626}
627
628template <typename LHS, typename RHS>
630m_GAnd(const LHS &L, const RHS &R) {
632}
633
634template <typename LHS, typename RHS>
636m_GXor(const LHS &L, const RHS &R) {
638}
639
640template <typename LHS, typename RHS>
645
646template <typename LHS, typename RHS>
647inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
649m_GDisjointOr(const LHS &L, const RHS &R) {
650 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
652}
653
654template <typename LHS, typename RHS>
655inline auto m_GAddLike(const LHS &L, const RHS &R) {
656 return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
657}
658
659template <typename LHS, typename RHS>
661m_GShl(const LHS &L, const RHS &R) {
663}
664
665template <typename LHS, typename RHS>
667m_GLShr(const LHS &L, const RHS &R) {
669}
670
671template <typename LHS, typename RHS>
673m_GAShr(const LHS &L, const RHS &R) {
675}
676
677template <typename LHS, typename RHS>
679m_GSMax(const LHS &L, const RHS &R) {
681}
682
683template <typename LHS, typename RHS>
685m_GSMin(const LHS &L, const RHS &R) {
687}
688
689template <typename LHS, typename RHS>
691m_GUMax(const LHS &L, const RHS &R) {
693}
694
695template <typename LHS, typename RHS>
697m_GUMin(const LHS &L, const RHS &R) {
699}
700
701// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
702template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
703 SrcTy L;
704
705 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
706 template <typename OpTy>
707 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
708 MachineInstr *TmpMI;
709 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
710 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
711 return L.match(MRI, TmpMI->getOperand(1).getReg());
712 }
713 }
714 return false;
715 }
716};
717
718template <typename SrcTy>
720m_GAnyExt(const SrcTy &Src) {
722}
723
724template <typename SrcTy>
728
729template <typename SrcTy>
733
734template <typename SrcTy>
738
739template <typename SrcTy>
743
744template <typename SrcTy>
746m_GBitcast(const SrcTy &Src) {
748}
749
750template <typename SrcTy>
752m_GPtrToInt(const SrcTy &Src) {
754}
755
756template <typename SrcTy>
758m_GIntToPtr(const SrcTy &Src) {
760}
761
762template <typename SrcTy>
764m_GFPTrunc(const SrcTy &Src) {
766}
767
768/// Matches a G_SEXT_INREG, binding its source operand. G_SEXT_INREG has an
769/// extra immediate operand, so it does not fit the plain UnaryOp_match shape.
770template <typename SrcTy> struct SExtInRegMatch {
771 SrcTy L;
772
773 SExtInRegMatch(const SrcTy &LHS) : L(LHS) {}
774 template <typename OpTy>
775 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
776 MachineInstr *TmpMI;
777 if (mi_match(Op, MRI, m_MInstr(TmpMI)) &&
778 TmpMI->getOpcode() == TargetOpcode::G_SEXT_INREG)
779 return L.match(MRI, TmpMI->getOperand(1).getReg());
780 return false;
781 }
782};
783
784template <typename SrcTy>
785inline SExtInRegMatch<SrcTy> m_GSExtInReg(const SrcTy &Src) {
786 return SExtInRegMatch<SrcTy>(Src);
787}
788
789template <typename SrcTy>
793
794template <typename SrcTy>
798
799template <typename SrcTy>
801 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
802}
803
804template <typename SrcTy>
808
809template <typename SrcTy>
811m_GFFloor(const SrcTy &Src) {
813}
814
815// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
816// TODO: Allow checking a specific predicate.
817template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
818 bool Commutable = false>
820 Pred_P P;
821 LHS_P L;
822 RHS_P R;
823
824 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
825 : P(Pred), L(LHS), R(RHS) {}
826
827 template <typename OpTy>
828 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
829 MachineInstr *TmpMI;
830 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
831 return false;
832
833 auto TmpPred =
834 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
835 if (!P.match(MRI, TmpPred))
836 return false;
837 Register LHS = TmpMI->getOperand(2).getReg();
838 Register RHS = TmpMI->getOperand(3).getReg();
839 if (L.match(MRI, LHS) && R.match(MRI, RHS))
840 return true;
841 // NOTE: When trying the alternative operand ordering
842 // with a commutative operation, it is imperative to always run
843 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
844 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
845 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
846 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
847 return true;
848 return false;
849 }
850};
851
852template <typename LHS_P, typename Test_P, unsigned Opcode>
854 LHS_P L;
855 Test_P T;
856
857 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
858
859 template <typename OpTy>
860 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
861 MachineInstr *TmpMI;
862 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
863 return false;
864
865 Register LHS = TmpMI->getOperand(1).getReg();
866 if (!L.match(MRI, LHS))
867 return false;
868
869 FPClassTest TmpClass =
870 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
871 if (T.match(MRI, TmpClass))
872 return true;
873
874 return false;
875 }
876};
877
878template <typename Pred, typename LHS, typename RHS>
880m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
882}
883
884template <typename Pred, typename LHS, typename RHS>
886m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
888}
889
890/// G_ICMP matcher that also matches commuted compares.
891/// E.g.
892///
893/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
894///
895/// Could match both of:
896///
897/// icmp ugt (add x, y) (sub a, b)
898/// icmp ult (sub a, b) (add x, y)
899template <typename Pred, typename LHS, typename RHS>
901m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
903}
904
905/// G_FCMP matcher that also matches commuted compares.
906/// E.g.
907///
908/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
909///
910/// Could match both of:
911///
912/// fcmp ogt (fadd x, y) (fmul a, b)
913/// fcmp olt (fmul a, b) (fadd x, y)
914template <typename Pred, typename LHS, typename RHS>
916m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
918}
919
920/// Matches the register and immediate used in a fpclass test
921/// G_IS_FPCLASS %val, 96
922template <typename LHS, typename Test>
927
928// Helper for checking if a Reg is of specific type.
929struct CheckType {
931 CheckType(const LLT Ty) : Ty(Ty) {}
932
934 return MRI.getType(Reg) == Ty;
935 }
936};
937
938inline CheckType m_SpecificType(LLT Ty) { return Ty; }
939
940template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
942 Src0Ty Src0;
943 Src1Ty Src1;
944 Src2Ty Src2;
945
946 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
947 : Src0(Src0), Src1(Src1), Src2(Src2) {}
948 template <typename OpTy>
949 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
950 MachineInstr *TmpMI;
951 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
952 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
953 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
954 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
955 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
956 }
957 }
958 return false;
959 }
960};
961template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
962inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
963 TargetOpcode::G_INSERT_VECTOR_ELT>
964m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
965 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
966 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
967}
968
969template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
971m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
973 Src0, Src1, Src2);
974}
975
976/// Matches a register negated by a G_SUB.
977/// G_SUB 0, %negated_reg
978template <typename SrcTy>
980m_Neg(const SrcTy &&Src) {
981 return m_GSub(m_ZeroInt(), Src);
982}
983
984/// Matches a register not-ed by a G_XOR.
985/// G_XOR %not_reg, -1
986template <typename SrcTy>
988m_Not(const SrcTy &&Src) {
989 return m_GXor(Src, m_AllOnesInt());
990}
991
992} // namespace MIPatternMatch
993} // namespace llvm
994
995#endif
aarch64 promote const
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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:231
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
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:551
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1023
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:197
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
Represents a G_CONSTANT.
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 LLVM_READONLY 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
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)
GConstantMatch< GConstant > m_GConstant(GConstant *&Inst)
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)
SExtInRegMatch< SrcTy > m_GSExtInReg(const SrcTy &Src)
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:464
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:297
LLVM_ABI std::optional< APInt > getIConstantSplatVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1394
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:317
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:1427
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:450
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:1353
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:436
LLVM_ABI std::optional< int64_t > getIConstantSplatSExtVal(const Register Reg, const MachineRegisterInfo &MRI)
Definition Utils.cpp:1412
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
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)
Matches a G_CONSTANT and binds the defining instruction.
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)
Matches a G_SEXT_INREG, binding its source operand.
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
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)