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#include <tuple>
24#include <utility>
25
26namespace llvm {
27namespace MIPatternMatch {
28
29template <typename Reg, typename Pattern>
30[[nodiscard]] bool mi_match(Reg R, const MachineRegisterInfo &MRI,
31 Pattern &&P) {
32 return P.match(MRI, R);
33}
34
35template <typename Pattern>
36[[nodiscard]] bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI,
37 Pattern &&P) {
38 return P.match(MRI, &MI);
39}
40
41template <typename Pattern>
42[[nodiscard]] bool mi_match(const MachineInstr &MI,
43 const MachineRegisterInfo &MRI, Pattern &&P) {
44 return P.match(MRI, &MI);
45}
46
47// TODO: Extend for N use.
48template <typename SubPatternT> struct OneUse_match {
49 SubPatternT SubPat;
50 OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
51
53 return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
54 }
55};
56
57template <typename SubPat>
58inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
59 return SP;
60}
61
62template <typename ConstT>
63inline std::optional<ConstT> matchConstant(Register,
64 const MachineRegisterInfo &);
65
66template <>
67inline std::optional<APInt> matchConstant(Register Reg,
68 const MachineRegisterInfo &MRI) {
70}
71
72template <>
73inline std::optional<int64_t> matchConstant(Register Reg,
74 const MachineRegisterInfo &MRI) {
76}
77
78template <typename ConstT> struct ConstantMatch {
79 ConstT &CR;
80 ConstantMatch(ConstT &C) : CR(C) {}
82 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
83 CR = std::move(*MaybeCst);
84 return true;
85 }
86 return false;
87 }
88};
89
91 return ConstantMatch<APInt>(Cst);
92}
93inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
94 return ConstantMatch<int64_t>(Cst);
95}
96
97template <typename ConstT>
98inline std::optional<ConstT> matchConstantSplat(Register,
99 const MachineRegisterInfo &);
100
101template <>
102inline std::optional<APInt> matchConstantSplat(Register Reg,
103 const MachineRegisterInfo &MRI) {
105}
106
107template <>
108inline std::optional<int64_t>
112
113template <typename ConstT> struct ICstOrSplatMatch {
114 ConstT &CR;
115 ICstOrSplatMatch(ConstT &C) : CR(C) {}
117 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
118 CR = std::move(*MaybeCst);
119 return true;
120 }
121
122 if (auto MaybeCstSplat = matchConstantSplat<ConstT>(Reg, MRI)) {
123 CR = std::move(*MaybeCstSplat);
124 return true;
125 }
126
127 return false;
128 };
129};
130
134
136 return ICstOrSplatMatch<int64_t>(Cst);
137}
138
140 std::optional<ValueAndVReg> &ValReg;
141 GCstAndRegMatch(std::optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
146};
147
148inline GCstAndRegMatch m_GCst(std::optional<ValueAndVReg> &ValReg) {
149 return GCstAndRegMatch(ValReg);
150}
151
153 std::optional<FPValueAndVReg> &FPValReg;
154 GFCstAndRegMatch(std::optional<FPValueAndVReg> &FPValReg)
155 : FPValReg(FPValReg) {}
160};
161
162inline GFCstAndRegMatch m_GFCst(std::optional<FPValueAndVReg> &FPValReg) {
163 return GFCstAndRegMatch(FPValReg);
164}
165
167 std::optional<FPValueAndVReg> &FPValReg;
168 GFCstOrSplatGFCstMatch(std::optional<FPValueAndVReg> &FPValReg)
169 : FPValReg(FPValReg) {}
174};
175
177m_GFCstOrSplat(std::optional<FPValueAndVReg> &FPValReg) {
178 return GFCstOrSplatGFCstMatch(FPValReg);
179}
180
181/// Matches an FP constant whose value satisfies the given predicate.
182template <typename Pred> struct GFCstPredMatch {
186 if (const ConstantFP *FPImm = getConstantFPVRegVal(Reg, MRI))
187 return P(FPImm->getValueAPF());
188 return false;
189 }
190};
191template <typename Pred> GFCstPredMatch(Pred) -> GFCstPredMatch<Pred>;
192
193/// Matches a floating-point positive zero.
194inline auto m_PosZeroFP() {
195 return GFCstPredMatch([](const APFloat &V) { return V.isPosZero(); });
196}
197
198/// Matcher for a specific constant value.
204 APInt MatchedVal;
205 if (mi_match(Reg, MRI, m_ICst(MatchedVal)))
206 return APInt::isSameValue(MatchedVal, RequestedVal,
207 /*SignedCompare=*/true);
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
224 bool match(int64_t Imm) const { return Imm == RequestedVal; }
225};
226
227/// Matches an immediate operand equal to \p RequestedValue.
228inline SpecificImmMatch m_SpecificImm(int64_t RequestedValue) {
229 return SpecificImmMatch(RequestedValue);
230}
231
233 int64_t &ImmOut;
235 bool match(int64_t Imm) const {
236 ImmOut = Imm;
237 return true;
238 }
239};
240
241/// Binds an immediate operand's value.
242inline BindImmMatch m_Imm(int64_t &Imm) { return BindImmMatch(Imm); }
243
244/// Matches an integer constant with all bits set, regardless of width.
247 APInt MatchedVal;
248 return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal.isAllOnes();
249 }
250};
251
252inline AllOnesConstantMatch m_AllOnes() { return {}; }
253
254/// Matcher for a specific constant splat.
264
265/// Matches a constant splat of \p RequestedValue.
267m_SpecificICstSplat(const APInt &RequestedValue) {
268 return SpecificConstantSplatMatch(RequestedValue);
269}
270
271inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
273 APInt(64, RequestedValue, /* isSigned */ true));
274}
275
276/// Matcher for a specific constant or constant splat.
282 APInt MatchedVal;
283 if (mi_match(Reg, MRI, m_ICst(MatchedVal))) {
284 if (APInt::isSameValue(MatchedVal, RequestedVal, /*SignedCompare=*/true))
285 return true;
286 }
288 /* AllowUndef */ false);
289 }
290};
291
292/// Matches a \p RequestedValue constant or a constant splat of \p
293/// RequestedValue.
295m_SpecificICstOrSplat(const APInt &RequestedValue) {
296 return SpecificConstantOrSplatMatch(RequestedValue);
297}
298
300m_SpecificICstOrSplat(int64_t RequestedValue) {
302 APInt(64, RequestedValue, /* isSigned */ true));
303}
304
305/// Convenience matchers for specific integer values.
312
313/// Matcher for a specific register.
321
322/// Matches a register only if it is equal to \p RequestedReg.
324 return SpecificRegisterMatch(RequestedReg);
325}
326
327// TODO: Rework this for different kinds of MachineOperand.
328// Currently assumes the Src for a match is a register.
329// We might want to support taking in some MachineOperands and call getReg on
330// that.
331
333 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
335 return MO->isReg();
336 }
337};
338
340
341/// Matching combinators.
342template <typename... Preds> struct And {
343 template <typename MatchSrc>
344 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
345 return true;
346 }
347};
348
349template <typename Pred, typename... Preds>
350struct And<Pred, Preds...> : And<Preds...> {
352 And(Pred &&p, Preds &&... preds)
353 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
354 }
355 template <typename MatchSrc>
356 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
357 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
358 }
359};
360
361template <typename... Preds> struct Or {
362 template <typename MatchSrc>
363 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
364 return false;
365 }
366};
367
368template <typename Pred, typename... Preds>
369struct Or<Pred, Preds...> : Or<Preds...> {
371 Or(Pred &&p, Preds &&... preds)
372 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
373 template <typename MatchSrc>
374 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
375 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
376 }
377};
378
379template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
380 return And<Preds...>(std::forward<Preds>(preds)...);
381}
382
383template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
384 return Or<Preds...>(std::forward<Preds>(preds)...);
385}
386
387template <typename BindTy> struct bind_helper {
388 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
389 VR = V;
390 return true;
391 }
392};
393
394template <> struct bind_helper<MachineInstr *> {
396 Register Reg) {
397 MI = MRI.getVRegDef(Reg);
398 if (MI)
399 return true;
400 return false;
401 }
403 MachineInstr *Inst) {
404 MI = Inst;
405 return MI;
406 }
407};
408
409template <> struct bind_helper<const MachineInstr *> {
410 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
411 Register Reg) {
412 MI = MRI.getVRegDef(Reg);
413 return MI;
414 }
415 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
416 const MachineInstr *Inst) {
417 MI = Inst;
418 return MI;
419 }
420};
421
422template <> struct bind_helper<LLT> {
423 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
424 Ty = MRI.getType(Reg);
425 if (Ty.isValid())
426 return true;
427 return false;
428 }
429};
430
431template <> struct bind_helper<const ConstantFP *> {
432 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
433 Register Reg) {
435 if (F)
436 return true;
437 return false;
438 }
439};
440
441template <typename Class> struct bind_ty {
442 Class &VR;
443
444 bind_ty(Class &V) : VR(V) {}
445
446 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
448 }
449};
450
451inline bind_ty<Register> m_Reg(Register &R) { return R; }
454 return MI;
455}
456inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
460
461/// Wraps a MIFlags output for use as an optional trailing operand of an
462/// instruction matcher (e.g. m_GPtrAdd(L, R, m_MIFlags(Flags))). On a
463/// successful match the matched instruction's flags are written to \p Flags.
467
468inline MIFlagsRef m_MIFlags(uint32_t &Flags) { return {Flags}; }
469
470/// Optional trailing operand for a load matcher (e.g. m_GLoad(m_Reg(Ptr),
471/// m_MMO(MMO))) that binds the matched instruction's MachineMemOperand.
472struct MMORef {
474};
475
476inline MMORef m_MMO(const MachineMemOperand *&MMO) { return {MMO}; }
477
478template <typename BindTy> struct deferred_helper {
479 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
480 return VR == V;
481 }
482};
483
484template <> struct deferred_helper<LLT> {
485 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
486 return VT == MRI.getType(R);
487 }
488};
489
490template <typename Class> struct deferred_ty {
491 Class &VR;
492
493 deferred_ty(Class &V) : VR(V) {}
494
495 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
497 }
498};
499
500/// Similar to m_SpecificReg/Type, but the specific value to match originated
501/// from an earlier sub-pattern in the same mi_match expression. For example,
502/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
503/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
504/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
506inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
507
510 MachineInstr *TmpMI;
511 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
512 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
513 return false;
514 }
515};
516
518
519/// Binds the defining instruction of \p Reg if it is a \p Class. Prefer the
520/// named helpers below so the opcode is spelled out at the call site.
521template <typename Class> struct GInstrBind {
522 Class *&Inst;
523
524 GInstrBind(Class *&Inst) : Inst(Inst) {}
526 MachineInstr *TmpMI;
527 if (mi_match(Reg, MRI, m_MInstr(TmpMI))) {
528 if (auto *Cst = dyn_cast<Class>(TmpMI)) {
529 Inst = Cst;
530 return true;
531 }
532 }
533 return false;
534 }
535};
536
537/// Match a literal G_CONSTANT instruction (no look-through of splats or
538/// copies).
539inline GInstrBind<GConstant> m_GConstant(GConstant *&Inst) { return Inst; }
541 return Inst;
542}
543
544/// Match a literal G_CONSTANT or G_FCONSTANT, binding its raw bits to \p Bits
545/// (the integer value, or the float reinterpreted as an integer).
549 MachineInstr *MI = MRI.getVRegDef(Reg);
550 if (MI->getOpcode() == TargetOpcode::G_CONSTANT) {
551 Bits = MI->getOperand(1).getCImm()->getValue();
552 return true;
553 }
554 if (MI->getOpcode() == TargetOpcode::G_FCONSTANT) {
555 Bits = MI->getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
556 return true;
557 }
558 return false;
559 }
560};
561
563 return {Bits};
564}
565
566/// Match a load of type \p Class, matching its pointer operand and optionally
567/// binding the instruction and/or its MachineMemOperand.
568template <typename Class, typename PtrP> struct LoadOp_match {
569 PtrP Ptr;
570 Class **InstOut = nullptr;
571 const MachineMemOperand **MMOOut = nullptr;
572
573 LoadOp_match(const PtrP &Ptr) : Ptr(Ptr) {}
574 LoadOp_match(const PtrP &Ptr, MMORef MMO) : Ptr(Ptr), MMOOut(&MMO.MMO) {}
575 LoadOp_match(Class *&Inst, const PtrP &Ptr) : Ptr(Ptr), InstOut(&Inst) {}
576 LoadOp_match(Class *&Inst, const PtrP &Ptr, MMORef MMO)
577 : Ptr(Ptr), InstOut(&Inst), MMOOut(&MMO.MMO) {}
578
579 template <typename OpTy>
581 MachineInstr *TmpMI;
582 if (!mi_match(Op, MRI, m_MInstr(TmpMI)))
583 return false;
584 auto *Load = dyn_cast<Class>(TmpMI);
585 if (!Load || !Ptr.match(MRI, Load->getPointerReg()))
586 return false;
587 if (InstOut)
588 *InstOut = Load;
589 if (MMOOut)
590 *MMOOut = &Load->getMMO();
591 return true;
592 }
593};
594
595template <typename PtrP>
598}
599template <typename PtrP>
601 const PtrP &Ptr) {
602 return LoadOp_match<GAnyLoad, PtrP>(Inst, Ptr);
603}
604template <typename PtrP>
605inline LoadOp_match<GAnyLoad, PtrP> m_GAnyLoad(GAnyLoad *&Inst, const PtrP &Ptr,
606 MMORef MMO) {
607 return LoadOp_match<GAnyLoad, PtrP>(Inst, Ptr, MMO);
608}
609template <typename PtrP>
610inline LoadOp_match<GLoad, PtrP> m_GLoad(const PtrP &Ptr) {
611 return LoadOp_match<GLoad, PtrP>(Ptr);
612}
613template <typename PtrP>
614inline LoadOp_match<GLoad, PtrP> m_GLoad(const PtrP &Ptr, MMORef MMO) {
615 return LoadOp_match<GLoad, PtrP>(Ptr, MMO);
616}
617
620 return {Inst, m_Reg()};
621}
624 return {Inst, m_Reg()};
625}
626
628 MMORef MMO) {
629 return {Inst, m_Reg(), MMO};
630}
632 MMORef MMO) {
633 return {Inst, m_Reg(), MMO};
634}
635
636/// Instruction binders for ops with no operand-form matcher (constant-immediate
637/// or variadic-source ops).
638inline GInstrBind<GUnmerge> m_GUnmerge(GUnmerge *&Inst) { return Inst; }
639inline GInstrBind<GVScale> m_GVScale(GVScale *&Inst) { return Inst; }
641 return Inst;
642}
644 return Inst;
645}
646
647/// Binds the defining instruction of \p Reg if it is a GIntrinsic (any of the
648/// four G_INTRINSIC* opcodes).
649inline GInstrBind<GIntrinsic> m_GIntrinsic(GIntrinsic *&Inst) { return Inst; }
651 return Inst;
652}
653
654/// Matches a GIntrinsic with a specific intrinsic ID and optionally, matchers
655/// for its leading arguments.
656template <Intrinsic::ID IntrID, typename... OpMatchers>
658 std::tuple<OpMatchers...> Operands;
659
660 GIntrinsic_match(const OpMatchers &...Ops) : Operands(Ops...) {}
661
662 template <typename OpTy>
664 MachineInstr *TmpMI;
665 if (!mi_match(Op, MRI, m_MInstr(TmpMI)))
666 return false;
667 auto *GI = dyn_cast<GIntrinsic>(TmpMI);
668 if (!GI || !GI->is(IntrID))
669 return false;
670 return matchOperands(MRI, *GI, std::index_sequence_for<OpMatchers...>{});
671 }
672
673private:
674 template <size_t... Is>
675 bool matchOperands(const MachineRegisterInfo &MRI, GIntrinsic &GI,
676 std::index_sequence<Is...>) {
677 // Intrinsic arguments follow the ID operand.
678 unsigned FirstArg = GI.getNumExplicitDefs() + 1;
679 return (std::get<Is>(Operands).match(
680 MRI, GI.getOperand(FirstArg + Is).getReg()) &&
681 ...);
682 }
683};
684
685template <Intrinsic::ID IntrID, typename... OpMatchers>
686inline GIntrinsic_match<IntrID, OpMatchers...>
687m_GIntrinsic(const OpMatchers &...Ops) {
688 return GIntrinsic_match<IntrID, OpMatchers...>(Ops...);
689}
690
691/// Matches a G_SHUFFLE_VECTOR, binding its two source operands and its mask.
692template <typename Src1Ty, typename Src2Ty> struct ShuffleVectorMatch {
693 Src1Ty Src1;
694 Src2Ty Src2;
696
697 ShuffleVectorMatch(const Src1Ty &Src1, const Src2Ty &Src2,
699 : Src1(Src1), Src2(Src2), Mask(Mask) {}
701 MachineInstr *TmpMI;
702 if (!mi_match(Reg, MRI, m_MInstr(TmpMI)))
703 return false;
704 auto *Shuf = dyn_cast<GShuffleVector>(TmpMI);
705 if (!Shuf || !Src1.match(MRI, Shuf->getSrc1Reg()) ||
706 !Src2.match(MRI, Shuf->getSrc2Reg()))
707 return false;
708 Mask = Shuf->getMask();
709 return true;
710 }
711};
712
713template <typename Src1Ty, typename Src2Ty>
715m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef<int> &Mask) {
716 return ShuffleVectorMatch<Src1Ty, Src2Ty>(Src1, Src2, Mask);
717}
718
719/// Matches a G_FRAME_INDEX, binding its frame index.
721 int &FI;
723 MachineInstr *TmpMI;
724 if (mi_match(Reg, MRI, m_MInstr(TmpMI)) &&
725 TmpMI->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
726 FI = TmpMI->getOperand(1).getIndex();
727 return true;
728 }
729 return false;
730 }
731};
732
733inline GFrameIndexMatch m_GFrameIndex(int &FI) { return {FI}; }
734
735// Helper for matching G_FCONSTANT
737
738// General helper for all the binary generic MI such as G_ADD/G_SUB etc
739template <typename LHS_P, typename RHS_P, unsigned Opcode,
740 bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
742 LHS_P L;
743 RHS_P R;
744 // Optional output: when set, receives the matched instruction's flags.
745 uint32_t *FlagsOut = nullptr;
746
747 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
748 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS, MIFlagsRef FlagsOut)
749 : L(LHS), R(RHS), FlagsOut(&FlagsOut.Flags) {}
750 template <typename OpTy>
752 const MachineInstr *TmpMI;
753 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
754 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
755 if ((TmpMI->getFlags() & Flags) != Flags)
756 return false;
757 if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
758 !R.match(MRI, TmpMI->getOperand(2).getReg())) &&
759 // NOTE: When trying the alternative operand ordering
760 // with a commutative operation, it is imperative to always run
761 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
762 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
763 // expected.
764 (!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
765 !R.match(MRI, TmpMI->getOperand(1).getReg())))
766 return false;
767 if (FlagsOut)
768 *FlagsOut = TmpMI->getFlags();
769 return true;
770 }
771 }
772 return false;
773 }
774};
775
776// Helper for (commutative) binary generic MI that checks Opcode.
777template <typename LHS_P, typename RHS_P, bool Commutable = false>
779 unsigned Opc;
780 LHS_P L;
781 RHS_P R;
782
783 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
784 : Opc(Opcode), L(LHS), R(RHS) {}
785 template <typename OpTy>
787 MachineInstr *TmpMI;
788 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
789 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
790 TmpMI->getNumOperands() == 3) {
791 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
792 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
793 // NOTE: When trying the alternative operand ordering
794 // with a commutative operation, it is imperative to always run
795 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
796 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
797 // expected.
798 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
799 R.match(MRI, TmpMI->getOperand(1).getReg())));
800 }
801 }
802 return false;
803 }
804};
805
806template <typename LHS, typename RHS>
807inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
808 const RHS &R) {
809 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
810}
811
812template <typename LHS, typename RHS>
814m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
815 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
816}
817
818template <typename LHS, typename RHS>
820m_GAdd(const LHS &L, const RHS &R) {
822}
823
824template <typename LHS, typename RHS>
829
830template <typename LHS, typename RHS>
836
837template <typename LHS, typename RHS>
842
843template <typename LHS, typename RHS>
845m_GPtrAdd(const LHS &L, const RHS &R, MIFlagsRef Flags) {
847}
848
849template <typename LHS, typename RHS>
854
855template <typename LHS, typename RHS>
857m_GSub(const LHS &L, const RHS &R, MIFlagsRef Flags) {
859}
860
861template <typename LHS, typename RHS>
863m_GMul(const LHS &L, const RHS &R) {
865}
866
867template <typename LHS, typename RHS>
869m_GFAdd(const LHS &L, const RHS &R) {
871}
872
873template <typename LHS, typename RHS>
875m_GFMul(const LHS &L, const RHS &R) {
877}
878
879template <typename LHS, typename RHS>
881m_GFSub(const LHS &L, const RHS &R) {
883}
884
885template <typename LHS, typename RHS>
887m_GAnd(const LHS &L, const RHS &R) {
889}
890
891template <typename LHS, typename RHS>
893m_GXor(const LHS &L, const RHS &R) {
895}
896
897template <typename LHS, typename RHS>
902
903template <typename LHS, typename RHS>
904inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
906m_GDisjointOr(const LHS &L, const RHS &R) {
907 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
909}
910
911template <typename LHS, typename RHS>
912inline auto m_GAddLike(const LHS &L, const RHS &R) {
913 return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
914}
915
916template <typename LHS, typename RHS>
918m_GShl(const LHS &L, const RHS &R) {
920}
921
922template <typename LHS, typename RHS>
924m_GLShr(const LHS &L, const RHS &R) {
926}
927
928template <typename LHS, typename RHS>
930m_GAShr(const LHS &L, const RHS &R) {
932}
933
934template <typename LHS, typename RHS>
936m_GSMax(const LHS &L, const RHS &R) {
938}
939
940template <typename LHS, typename RHS>
942m_GSMin(const LHS &L, const RHS &R) {
944}
945
946template <typename LHS, typename RHS>
948m_GUMax(const LHS &L, const RHS &R) {
950}
951
952template <typename LHS, typename RHS>
954m_GUMin(const LHS &L, const RHS &R) {
956}
957
958// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
959template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
960 SrcTy L;
961
962 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
963 template <typename OpTy>
965 MachineInstr *TmpMI;
966 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
967 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
968 return L.match(MRI, TmpMI->getOperand(1).getReg());
969 }
970 }
971 return false;
972 }
973};
974
975template <typename SrcTy>
977m_GAnyExt(const SrcTy &Src) {
979}
980
981template <typename SrcTy>
985
986template <typename SrcTy>
990
991template <typename SrcTy>
995
996template <typename SrcTy>
1000
1001template <typename SrcTy>
1003m_GBitcast(const SrcTy &Src) {
1005}
1006
1007template <typename SrcTy>
1009m_GPtrToInt(const SrcTy &Src) {
1011}
1012
1013template <typename SrcTy>
1015m_GIntToPtr(const SrcTy &Src) {
1017}
1018
1019template <typename SrcTy>
1021m_GFPTrunc(const SrcTy &Src) {
1023}
1024
1025/// Matches an op that binds a source operand and an immediate operand with
1026/// sub-matchers (e.g. G_SEXT_INREG, G_ASSERT_ZEXT).
1027template <typename SrcTy, typename ImmTy, unsigned Opcode>
1029 SrcTy L;
1030 ImmTy Imm;
1031
1032 SrcImmOp_match(const SrcTy &LHS, const ImmTy &Imm) : L(LHS), Imm(Imm) {}
1033 template <typename OpTy>
1035 MachineInstr *TmpMI;
1036 return mi_match(Op, MRI, m_MInstr(TmpMI)) && TmpMI->getOpcode() == Opcode &&
1037 L.match(MRI, TmpMI->getOperand(1).getReg()) &&
1038 Imm.match(TmpMI->getOperand(2).getImm());
1039 }
1040};
1041
1042/// Matches any immediate operand.
1044 bool match(int64_t) const { return true; }
1045};
1046
1047/// Matches a G_SEXT_INREG, binding its source and immediate width.
1048template <typename SrcTy>
1050m_GSExtInReg(const SrcTy &Src) {
1051 return {Src, AnyImmMatch()};
1052}
1053
1054template <typename SrcTy, typename ImmTy>
1056m_GSExtInReg(const SrcTy &Src, const ImmTy &Imm) {
1057 return {Src, Imm};
1058}
1059
1060/// Matches a G_ASSERT_ZEXT, binding its source and immediate bit width.
1061template <typename SrcTy>
1063m_GAssertZext(const SrcTy &Src) {
1064 return {Src, AnyImmMatch()};
1065}
1066
1067template <typename SrcTy, typename ImmTy>
1069m_GAssertZext(const SrcTy &Src, const ImmTy &Imm) {
1070 return {Src, Imm};
1071}
1072
1073template <typename SrcTy>
1077
1078template <typename SrcTy>
1082
1083template <typename SrcTy>
1085 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
1086}
1087
1088template <typename SrcTy>
1092
1093template <typename SrcTy>
1095m_GFFloor(const SrcTy &Src) {
1097}
1098
1099// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
1100// TODO: Allow checking a specific predicate.
1101template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
1102 bool Commutable = false>
1104 Pred_P P;
1105 LHS_P L;
1106 RHS_P R;
1107
1108 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
1109 : P(Pred), L(LHS), R(RHS) {}
1110
1111 template <typename OpTy>
1113 MachineInstr *TmpMI;
1114 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
1115 return false;
1116
1117 auto TmpPred =
1118 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
1119 if (!P.match(MRI, TmpPred))
1120 return false;
1121 Register LHS = TmpMI->getOperand(2).getReg();
1122 Register RHS = TmpMI->getOperand(3).getReg();
1123 if (L.match(MRI, LHS) && R.match(MRI, RHS))
1124 return true;
1125 // NOTE: When trying the alternative operand ordering
1126 // with a commutative operation, it is imperative to always run
1127 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
1128 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
1129 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
1130 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
1131 return true;
1132 return false;
1133 }
1134};
1135
1136template <typename LHS_P, typename Test_P, unsigned Opcode>
1138 LHS_P L;
1139 Test_P T;
1140
1141 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
1142
1143 template <typename OpTy>
1145 MachineInstr *TmpMI;
1146 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
1147 return false;
1148
1149 Register LHS = TmpMI->getOperand(1).getReg();
1150 if (!L.match(MRI, LHS))
1151 return false;
1152
1153 FPClassTest TmpClass =
1154 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
1155 if (T.match(MRI, TmpClass))
1156 return true;
1157
1158 return false;
1159 }
1160};
1161
1162template <typename Pred, typename LHS, typename RHS>
1164m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
1166}
1167
1168template <typename Pred, typename LHS, typename RHS>
1170m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
1172}
1173
1174/// G_ICMP matcher that also matches commuted compares.
1175/// E.g.
1176///
1177/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
1178///
1179/// Could match both of:
1180///
1181/// icmp ugt (add x, y) (sub a, b)
1182/// icmp ult (sub a, b) (add x, y)
1183template <typename Pred, typename LHS, typename RHS>
1185m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
1187}
1188
1189/// G_FCMP matcher that also matches commuted compares.
1190/// E.g.
1191///
1192/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
1193///
1194/// Could match both of:
1195///
1196/// fcmp ogt (fadd x, y) (fmul a, b)
1197/// fcmp olt (fmul a, b) (fadd x, y)
1198template <typename Pred, typename LHS, typename RHS>
1200m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
1202}
1203
1204/// Matches the register and immediate used in a fpclass test
1205/// G_IS_FPCLASS %val, 96
1206template <typename LHS, typename Test>
1211
1212// Helper for checking if a Reg is of specific type.
1215 CheckType(const LLT Ty) : Ty(Ty) {}
1216
1218 return MRI.getType(Reg) == Ty;
1219 }
1220};
1221
1222inline CheckType m_SpecificType(LLT Ty) { return Ty; }
1223
1224template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
1226 Src0Ty Src0;
1227 Src1Ty Src1;
1228 Src2Ty Src2;
1229
1230 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
1231 : Src0(Src0), Src1(Src1), Src2(Src2) {}
1232 template <typename OpTy>
1234 MachineInstr *TmpMI;
1235 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
1236 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
1237 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
1238 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
1239 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
1240 }
1241 }
1242 return false;
1243 }
1244};
1245template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
1246inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
1247 TargetOpcode::G_INSERT_VECTOR_ELT>
1248m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
1249 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
1250 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
1251}
1252
1253template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
1255m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
1257 Src0, Src1, Src2);
1258}
1259
1260/// Matches a register negated by a G_SUB.
1261/// G_SUB 0, %negated_reg
1262template <typename SrcTy>
1264m_Neg(const SrcTy &&Src) {
1265 return m_GSub(m_ZeroInt(), Src);
1266}
1267
1268/// Matches a register not-ed by a G_XOR.
1269/// G_XOR %not_reg, -1
1270template <typename SrcTy>
1272m_Not(const SrcTy &&Src) {
1273 return m_GXor(Src, m_AllOnesInt());
1274}
1275
1276} // namespace MIPatternMatch
1277} // namespace llvm
1278
1279#endif
SDValue Pred
aarch64 promote const
uint64_t Imm
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
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
Register Reg
#define T
#define P(N)
MachineRegisterInfo & MRI
SI Fold Operands
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:230
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:367
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:550
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:196
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
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 any generic load, including sign/zero extending variants.
Represents a G_BUILD_VECTOR.
Represents a G_CONCAT_VECTORS.
Represents a G_CONSTANT.
Represents a call to an intrinsic.
Represents a G_SEXTLOAD.
Represents a G_UNMERGE_VALUES.
Represents a vscale.
Represents a G_ZEXTLOAD.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitDefs() const
Returns the number of non-implicit definitions.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
unsigned getNumDefs() const
Returns the total number of definitions.
A description of a memory reference used in the backend.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
operand_type_match m_Reg()
GInstrBind< GConstant > m_GConstant(GConstant *&Inst)
Match a literal G_CONSTANT instruction (no look-through of splats or copies).
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
std::optional< ConstT > matchConstantSplat(Register, const MachineRegisterInfo &)
GInstrBind< GBuildVector > m_GBuildVector(GBuildVector *&Inst)
auto m_GAddLike(const LHS &L, const RHS &R)
SrcImmOp_match< SrcTy, AnyImmMatch, TargetOpcode::G_ASSERT_ZEXT > m_GAssertZext(const SrcTy &Src)
Matches a G_ASSERT_ZEXT, binding its source and immediate bit width.
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)
LoadOp_match< GLoad, PtrP > m_GLoad(const PtrP &Ptr)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
MIFlagsRef m_MIFlags(uint32_t &Flags)
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)
LoadOp_match< GZExtLoad, operand_type_match > m_GZExtLoad(GZExtLoad *&Inst)
LoadOp_match< GSExtLoad, operand_type_match > m_GSExtLoad(GSExtLoad *&Inst)
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)
auto m_PosZeroFP()
Matches a floating-point positive zero.
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()
GInstrBind< GVScale > m_GVScale(GVScale *&Inst)
SpecificImmMatch m_SpecificImm(int64_t RequestedValue)
Matches an immediate operand equal to RequestedValue.
GInstrBind< GConcatVectors > m_GConcatVectors(GConcatVectors *&Inst)
AllOnesConstantMatch m_AllOnes()
GConstantBitsMatch m_GConstantOrFConstantBits(APInt &Bits)
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)
GFCstPredMatch(Pred) -> GFCstPredMatch< Pred >
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)
BindImmMatch m_Imm(int64_t &Imm)
Binds an immediate operand's value.
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
MMORef m_MMO(const MachineMemOperand *&MMO)
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)
GFrameIndexMatch m_GFrameIndex(int &FI)
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.
LoadOp_match< GAnyLoad, PtrP > m_GAnyLoad(const PtrP &Ptr)
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)
ShuffleVectorMatch< Src1Ty, Src2Ty > m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef< int > &Mask)
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)
GInstrBind< GIntrinsic > m_GIntrinsic(GIntrinsic *&Inst)
Binds the defining instruction of Reg if it is a GIntrinsic (any of the four G_INTRINSIC* opcodes).
bind_ty< LLT > m_Type(LLT &Ty)
BinaryOp_match< LHS, RHS, TargetOpcode::G_SMAX, true > m_GSMax(const LHS &L, const RHS &R)
SrcImmOp_match< SrcTy, AnyImmMatch, TargetOpcode::G_SEXT_INREG > m_GSExtInReg(const SrcTy &Src)
Matches a G_SEXT_INREG, binding its source and immediate width.
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:483
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:1413
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
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:1446
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:1372
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:1431
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
Matches an integer constant with all bits set, regardless of width.
bool match(const MachineRegisterInfo &MRI, Register Reg)
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
Matching combinators.
bool match(const MachineRegisterInfo &MRI, MatchSrc &&src)
Matches any immediate operand.
BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS)
BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS, MIFlagsRef FlagsOut)
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)
Match a literal G_CONSTANT or G_FCONSTANT, binding its raw bits to Bits (the integer value,...
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
Matches an FP constant whose value satisfies the given predicate.
bool match(const MachineRegisterInfo &MRI, Register Reg)
Matches a G_FRAME_INDEX, binding its frame index.
bool match(const MachineRegisterInfo &MRI, Register Reg)
Binds the defining instruction of Reg if it is a Class.
bool match(const MachineRegisterInfo &MRI, Register Reg)
Matches a GIntrinsic with a specific intrinsic ID and optionally, matchers for its leading arguments.
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
GIntrinsic_match(const OpMatchers &...Ops)
std::tuple< OpMatchers... > Operands
bool match(const MachineRegisterInfo &MRI, Register Reg)
bool match(const MachineRegisterInfo &MRI, Register Reg)
Match a load of type Class, matching its pointer operand and optionally binding the instruction and/o...
LoadOp_match(Class *&Inst, const PtrP &Ptr, MMORef MMO)
const MachineMemOperand ** MMOOut
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
LoadOp_match(const PtrP &Ptr, MMORef MMO)
LoadOp_match(Class *&Inst, const PtrP &Ptr)
Wraps a MIFlags output for use as an optional trailing operand of an instruction matcher (e....
Optional trailing operand for a load matcher (e.g.
const MachineMemOperand *& MMO
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_SHUFFLE_VECTOR, binding its two source operands and its mask.
bool match(const MachineRegisterInfo &MRI, Register Reg)
ShuffleVectorMatch(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef< int > &Mask)
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)
Matches an op that binds a source operand and an immediate operand with sub-matchers (e....
SrcImmOp_match(const SrcTy &LHS, const ImmTy &Imm)
bool match(const MachineRegisterInfo &MRI, OpTy &&Op)
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)