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
768template <typename SrcTy>
772
773template <typename SrcTy>
777
778template <typename SrcTy>
780 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
781}
782
783template <typename SrcTy>
787
788template <typename SrcTy>
790m_GFFloor(const SrcTy &Src) {
792}
793
794// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
795// TODO: Allow checking a specific predicate.
796template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
797 bool Commutable = false>
799 Pred_P P;
800 LHS_P L;
801 RHS_P R;
802
803 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
804 : P(Pred), L(LHS), R(RHS) {}
805
806 template <typename OpTy>
807 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
808 MachineInstr *TmpMI;
809 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
810 return false;
811
812 auto TmpPred =
813 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
814 if (!P.match(MRI, TmpPred))
815 return false;
816 Register LHS = TmpMI->getOperand(2).getReg();
817 Register RHS = TmpMI->getOperand(3).getReg();
818 if (L.match(MRI, LHS) && R.match(MRI, RHS))
819 return true;
820 // NOTE: When trying the alternative operand ordering
821 // with a commutative operation, it is imperative to always run
822 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
823 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
824 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
825 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
826 return true;
827 return false;
828 }
829};
830
831template <typename LHS_P, typename Test_P, unsigned Opcode>
833 LHS_P L;
834 Test_P T;
835
836 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
837
838 template <typename OpTy>
839 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
840 MachineInstr *TmpMI;
841 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
842 return false;
843
844 Register LHS = TmpMI->getOperand(1).getReg();
845 if (!L.match(MRI, LHS))
846 return false;
847
848 FPClassTest TmpClass =
849 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
850 if (T.match(MRI, TmpClass))
851 return true;
852
853 return false;
854 }
855};
856
857template <typename Pred, typename LHS, typename RHS>
859m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
861}
862
863template <typename Pred, typename LHS, typename RHS>
865m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
867}
868
869/// G_ICMP matcher that also matches commuted compares.
870/// E.g.
871///
872/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
873///
874/// Could match both of:
875///
876/// icmp ugt (add x, y) (sub a, b)
877/// icmp ult (sub a, b) (add x, y)
878template <typename Pred, typename LHS, typename RHS>
880m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
882}
883
884/// G_FCMP matcher that also matches commuted compares.
885/// E.g.
886///
887/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
888///
889/// Could match both of:
890///
891/// fcmp ogt (fadd x, y) (fmul a, b)
892/// fcmp olt (fmul a, b) (fadd x, y)
893template <typename Pred, typename LHS, typename RHS>
895m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
897}
898
899/// Matches the register and immediate used in a fpclass test
900/// G_IS_FPCLASS %val, 96
901template <typename LHS, typename Test>
906
907// Helper for checking if a Reg is of specific type.
908struct CheckType {
910 CheckType(const LLT Ty) : Ty(Ty) {}
911
913 return MRI.getType(Reg) == Ty;
914 }
915};
916
917inline CheckType m_SpecificType(LLT Ty) { return Ty; }
918
919template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
921 Src0Ty Src0;
922 Src1Ty Src1;
923 Src2Ty Src2;
924
925 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
926 : Src0(Src0), Src1(Src1), Src2(Src2) {}
927 template <typename OpTy>
928 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
929 MachineInstr *TmpMI;
930 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
931 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
932 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
933 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
934 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
935 }
936 }
937 return false;
938 }
939};
940template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
941inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
942 TargetOpcode::G_INSERT_VECTOR_ELT>
943m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
944 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
945 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
946}
947
948template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
950m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
952 Src0, Src1, Src2);
953}
954
955/// Matches a register negated by a G_SUB.
956/// G_SUB 0, %negated_reg
957template <typename SrcTy>
959m_Neg(const SrcTy &&Src) {
960 return m_GSub(m_ZeroInt(), Src);
961}
962
963/// Matches a register not-ed by a G_XOR.
964/// G_XOR %not_reg, -1
965template <typename SrcTy>
967m_Not(const SrcTy &&Src) {
968 return m_GXor(Src, m_AllOnesInt());
969}
970
971} // namespace MIPatternMatch
972} // namespace llvm
973
974#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:235
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
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:1028
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: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)
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)
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)