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.hasOneUse(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 SubPatternT> struct OneNonDBGUse_match {
63 SubPatternT SubPat;
64 OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {}
65
67 return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
68 }
69};
70
71template <typename SubPat>
73 return SP;
74}
75
76template <typename ConstT>
77inline std::optional<ConstT> matchConstant(Register,
78 const MachineRegisterInfo &);
79
80template <>
81inline std::optional<APInt> matchConstant(Register Reg,
82 const MachineRegisterInfo &MRI) {
84}
85
86template <>
87inline std::optional<int64_t> matchConstant(Register Reg,
88 const MachineRegisterInfo &MRI) {
90}
91
92template <typename ConstT> struct ConstantMatch {
93 ConstT &CR;
94 ConstantMatch(ConstT &C) : CR(C) {}
96 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
97 CR = std::move(*MaybeCst);
98 return true;
99 }
100 return false;
101 }
102};
103
105 return ConstantMatch<APInt>(Cst);
106}
107inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
108 return ConstantMatch<int64_t>(Cst);
109}
110
111template <typename ConstT>
112inline std::optional<ConstT> matchConstantSplat(Register,
113 const MachineRegisterInfo &);
114
115template <>
116inline std::optional<APInt> matchConstantSplat(Register Reg,
117 const MachineRegisterInfo &MRI) {
119}
120
121template <>
122inline std::optional<int64_t>
126
127template <typename ConstT> struct ICstOrSplatMatch {
128 ConstT &CR;
129 ICstOrSplatMatch(ConstT &C) : CR(C) {}
131 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
132 CR = std::move(*MaybeCst);
133 return true;
134 }
135
136 if (auto MaybeCstSplat = matchConstantSplat<ConstT>(Reg, MRI)) {
137 CR = std::move(*MaybeCstSplat);
138 return true;
139 }
140
141 return false;
142 };
143};
144
148
150 return ICstOrSplatMatch<int64_t>(Cst);
151}
152
154 std::optional<ValueAndVReg> &ValReg;
155 GCstAndRegMatch(std::optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
160};
161
162inline GCstAndRegMatch m_GCst(std::optional<ValueAndVReg> &ValReg) {
163 return GCstAndRegMatch(ValReg);
164}
165
167 std::optional<FPValueAndVReg> &FPValReg;
168 GFCstAndRegMatch(std::optional<FPValueAndVReg> &FPValReg)
169 : FPValReg(FPValReg) {}
174};
175
176inline GFCstAndRegMatch m_GFCst(std::optional<FPValueAndVReg> &FPValReg) {
177 return GFCstAndRegMatch(FPValReg);
178}
179
181 std::optional<FPValueAndVReg> &FPValReg;
182 GFCstOrSplatGFCstMatch(std::optional<FPValueAndVReg> &FPValReg)
183 : FPValReg(FPValReg) {}
188};
189
191m_GFCstOrSplat(std::optional<FPValueAndVReg> &FPValReg) {
192 return GFCstOrSplatGFCstMatch(FPValReg);
193}
194
195/// Matches an FP constant whose value satisfies the given predicate.
196template <typename Pred> struct GFCstPredMatch {
197 Pred P;
198 GFCstPredMatch(Pred P) : P(P) {}
200 if (const ConstantFP *FPImm = getConstantFPVRegVal(Reg, MRI))
201 return P(FPImm->getValueAPF());
202 return false;
203 }
204};
205template <typename Pred> GFCstPredMatch(Pred) -> GFCstPredMatch<Pred>;
206
207/// Matches a floating-point positive zero.
208inline auto m_PosZeroFP() {
209 return GFCstPredMatch([](const APFloat &V) { return V.isPosZero(); });
210}
211
212/// Matcher for a specific constant value.
218 APInt MatchedVal;
219 if (mi_match(Reg, MRI, m_ICst(MatchedVal)))
220 return APInt::isSameValue(MatchedVal, RequestedVal,
221 /*SignedCompare=*/true);
222 return false;
223 }
224};
225
226/// Matches a constant equal to \p RequestedValue.
227inline SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue) {
228 return SpecificConstantMatch(RequestedValue);
229}
230
231inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
232 return SpecificConstantMatch(APInt(64, RequestedValue, /* isSigned */ true));
233}
234
238 bool match(int64_t Imm) const { return Imm == RequestedVal; }
239};
240
241/// Matches an immediate operand equal to \p RequestedValue.
242inline SpecificImmMatch m_SpecificImm(int64_t RequestedValue) {
243 return SpecificImmMatch(RequestedValue);
244}
245
247 int64_t &ImmOut;
249 bool match(int64_t Imm) const {
250 ImmOut = Imm;
251 return true;
252 }
253};
254
255/// Binds an immediate operand's value.
256inline BindImmMatch m_Imm(int64_t &Imm) { return BindImmMatch(Imm); }
257
258/// Matches an integer constant with all bits set, regardless of width.
261 APInt MatchedVal;
262 return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal.isAllOnes();
263 }
264};
265
266inline AllOnesConstantMatch m_AllOnes() { return {}; }
267
268/// Matcher for a specific constant splat.
278
279/// Matches a constant splat of \p RequestedValue.
281m_SpecificICstSplat(const APInt &RequestedValue) {
282 return SpecificConstantSplatMatch(RequestedValue);
283}
284
285inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
287 APInt(64, RequestedValue, /* isSigned */ true));
288}
289
290/// Matcher for a specific constant or constant splat.
296 APInt MatchedVal;
297 if (mi_match(Reg, MRI, m_ICst(MatchedVal))) {
298 if (APInt::isSameValue(MatchedVal, RequestedVal, /*SignedCompare=*/true))
299 return true;
300 }
302 /* AllowUndef */ false);
303 }
304};
305
306/// Matches a \p RequestedValue constant or a constant splat of \p
307/// RequestedValue.
309m_SpecificICstOrSplat(const APInt &RequestedValue) {
310 return SpecificConstantOrSplatMatch(RequestedValue);
311}
312
314m_SpecificICstOrSplat(int64_t RequestedValue) {
316 APInt(64, RequestedValue, /* isSigned */ true));
317}
318
319/// Convenience matchers for specific integer values.
326
327/// Matcher for a specific register.
335
336/// Matches a register only if it is equal to \p RequestedReg.
338 return SpecificRegisterMatch(RequestedReg);
339}
340
341// TODO: Rework this for different kinds of MachineOperand.
342// Currently assumes the Src for a match is a register.
343// We might want to support taking in some MachineOperands and call getReg on
344// that.
345
347 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
349 return MO->isReg();
350 }
351};
352
354
355/// Matching combinators.
356template <typename... Preds> struct And {
357 template <typename MatchSrc>
358 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
359 return true;
360 }
361};
362
363template <typename Pred, typename... Preds>
364struct And<Pred, Preds...> : And<Preds...> {
365 Pred P;
366 And(Pred &&p, Preds &&... preds)
367 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
368 }
369 template <typename MatchSrc>
370 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
371 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
372 }
373};
374
375template <typename... Preds> struct Or {
376 template <typename MatchSrc>
377 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
378 return false;
379 }
380};
381
382template <typename Pred, typename... Preds>
383struct Or<Pred, Preds...> : Or<Preds...> {
384 Pred P;
385 Or(Pred &&p, Preds &&... preds)
386 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
387 template <typename MatchSrc>
388 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
389 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
390 }
391};
392
393template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
394 return And<Preds...>(std::forward<Preds>(preds)...);
395}
396
397template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
398 return Or<Preds...>(std::forward<Preds>(preds)...);
399}
400
401template <typename BindTy> struct bind_helper {
402 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
403 VR = V;
404 return true;
405 }
406};
407
408template <> struct bind_helper<MachineInstr *> {
410 Register Reg) {
411 MI = MRI.getVRegDef(Reg);
412 if (MI)
413 return true;
414 return false;
415 }
417 MachineInstr *Inst) {
418 MI = Inst;
419 return MI;
420 }
421};
422
423template <> struct bind_helper<const MachineInstr *> {
424 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
425 Register Reg) {
426 MI = MRI.getVRegDef(Reg);
427 return MI;
428 }
429 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
430 const MachineInstr *Inst) {
431 MI = Inst;
432 return MI;
433 }
434};
435
436template <> struct bind_helper<LLT> {
437 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
438 Ty = MRI.getType(Reg);
439 if (Ty.isValid())
440 return true;
441 return false;
442 }
443};
444
445template <> struct bind_helper<const ConstantFP *> {
446 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
447 Register Reg) {
449 if (F)
450 return true;
451 return false;
452 }
453};
454
455template <typename Class> struct bind_ty {
456 Class &VR;
457
458 bind_ty(Class &V) : VR(V) {}
459
460 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
461 return bind_helper<Class>::bind(MRI, VR, V);
462 }
463};
464
465inline bind_ty<Register> m_Reg(Register &R) { return R; }
468 return MI;
469}
470inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
474
475/// Wraps a MIFlags output for use as an optional trailing operand of an
476/// instruction matcher (e.g. m_GPtrAdd(L, R, m_MIFlags(Flags))). On a
477/// successful match the matched instruction's flags are written to \p Flags.
481
482inline MIFlagsRef m_MIFlags(uint32_t &Flags) { return {Flags}; }
483
484/// Optional trailing operand for a load matcher (e.g. m_GLoad(m_Reg(Ptr),
485/// m_MMO(MMO))) that binds the matched instruction's MachineMemOperand.
486struct MMORef {
488};
489
490inline MMORef m_MMO(const MachineMemOperand *&MMO) { return {MMO}; }
491
492template <typename BindTy> struct deferred_helper {
493 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
494 return VR == V;
495 }
496};
497
498template <> struct deferred_helper<LLT> {
499 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
500 return VT == MRI.getType(R);
501 }
502};
503
504template <typename Class> struct deferred_ty {
505 Class &VR;
506
507 deferred_ty(Class &V) : VR(V) {}
508
509 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
511 }
512};
513
514/// Similar to m_SpecificReg/Type, but the specific value to match originated
515/// from an earlier sub-pattern in the same mi_match expression. For example,
516/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
517/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
518/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
520inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
521
524 MachineInstr *TmpMI;
525 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
526 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
527 return false;
528 }
529};
530
532
533/// Binds the defining instruction of \p Reg if it is a \p Class. Prefer the
534/// named helpers below so the opcode is spelled out at the call site.
535template <typename Class> struct GInstrBind {
536 Class *&Inst;
537
538 GInstrBind(Class *&Inst) : Inst(Inst) {}
540 MachineInstr *TmpMI;
541 if (mi_match(Reg, MRI, m_MInstr(TmpMI))) {
542 if (auto *Cst = dyn_cast<Class>(TmpMI)) {
543 Inst = Cst;
544 return true;
545 }
546 }
547 return false;
548 }
549};
550
551/// Match a literal G_CONSTANT instruction (no look-through of splats or
552/// copies).
553inline GInstrBind<GConstant> m_GConstant(GConstant *&Inst) { return Inst; }
555 return Inst;
556}
557
558/// Match a literal G_CONSTANT or G_FCONSTANT, binding its raw bits to \p Bits
559/// (the integer value, or the float reinterpreted as an integer).
563 MachineInstr *MI = MRI.getVRegDef(Reg);
564 if (MI->getOpcode() == TargetOpcode::G_CONSTANT) {
565 Bits = MI->getOperand(1).getCImm()->getValue();
566 return true;
567 }
568 if (MI->getOpcode() == TargetOpcode::G_FCONSTANT) {
569 Bits = MI->getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
570 return true;
571 }
572 return false;
573 }
574};
575
577 return {Bits};
578}
579
580/// Match a load of type \p Class, matching its pointer operand and optionally
581/// binding the instruction and/or its MachineMemOperand.
582template <typename Class, typename PtrP> struct LoadOp_match {
583 PtrP Ptr;
584 Class **InstOut = nullptr;
585 const MachineMemOperand **MMOOut = nullptr;
586
587 LoadOp_match(const PtrP &Ptr) : Ptr(Ptr) {}
588 LoadOp_match(const PtrP &Ptr, MMORef MMO) : Ptr(Ptr), MMOOut(&MMO.MMO) {}
589 LoadOp_match(Class *&Inst, const PtrP &Ptr) : Ptr(Ptr), InstOut(&Inst) {}
590 LoadOp_match(Class *&Inst, const PtrP &Ptr, MMORef MMO)
591 : Ptr(Ptr), InstOut(&Inst), MMOOut(&MMO.MMO) {}
592
593 template <typename OpTy>
595 MachineInstr *TmpMI;
596 if (!mi_match(Op, MRI, m_MInstr(TmpMI)))
597 return false;
598 auto *Load = dyn_cast<Class>(TmpMI);
599 if (!Load || !Ptr.match(MRI, Load->getPointerReg()))
600 return false;
601 if (InstOut)
602 *InstOut = Load;
603 if (MMOOut)
604 *MMOOut = &Load->getMMO();
605 return true;
606 }
607};
608
609template <typename PtrP>
612}
613template <typename PtrP>
615 const PtrP &Ptr) {
616 return LoadOp_match<GAnyLoad, PtrP>(Inst, Ptr);
617}
618template <typename PtrP>
619inline LoadOp_match<GAnyLoad, PtrP> m_GAnyLoad(GAnyLoad *&Inst, const PtrP &Ptr,
620 MMORef MMO) {
621 return LoadOp_match<GAnyLoad, PtrP>(Inst, Ptr, MMO);
622}
623template <typename PtrP>
624inline LoadOp_match<GLoad, PtrP> m_GLoad(const PtrP &Ptr) {
625 return LoadOp_match<GLoad, PtrP>(Ptr);
626}
627template <typename PtrP>
628inline LoadOp_match<GLoad, PtrP> m_GLoad(const PtrP &Ptr, MMORef MMO) {
629 return LoadOp_match<GLoad, PtrP>(Ptr, MMO);
630}
631
634 return {Inst, m_Reg()};
635}
638 return {Inst, m_Reg()};
639}
640
642 MMORef MMO) {
643 return {Inst, m_Reg(), MMO};
644}
646 MMORef MMO) {
647 return {Inst, m_Reg(), MMO};
648}
649
650/// Instruction binders for ops with no operand-form matcher (constant-immediate
651/// or variadic-source ops).
652inline GInstrBind<GUnmerge> m_GUnmerge(GUnmerge *&Inst) { return Inst; }
653inline GInstrBind<GVScale> m_GVScale(GVScale *&Inst) { return Inst; }
655 return Inst;
656}
658 return Inst;
659}
660
661/// Binds the defining instruction of \p Reg if it is a GIntrinsic (any of the
662/// four G_INTRINSIC* opcodes).
663inline GInstrBind<GIntrinsic> m_GIntrinsic(GIntrinsic *&Inst) { return Inst; }
665 return Inst;
666}
667
668/// Matches a GIntrinsic with a specific intrinsic ID and optionally, matchers
669/// for its leading arguments.
670template <Intrinsic::ID IntrID, typename... OpMatchers>
672 std::tuple<OpMatchers...> Operands;
673
674 GIntrinsic_match(const OpMatchers &...Ops) : Operands(Ops...) {}
675
676 template <typename OpTy>
678 MachineInstr *TmpMI;
679 if (!mi_match(Op, MRI, m_MInstr(TmpMI)))
680 return false;
681 auto *GI = dyn_cast<GIntrinsic>(TmpMI);
682 if (!GI || !GI->is(IntrID))
683 return false;
684 return matchOperands(MRI, *GI, std::index_sequence_for<OpMatchers...>{});
685 }
686
687private:
688 template <size_t... Is>
689 bool matchOperands(const MachineRegisterInfo &MRI, GIntrinsic &GI,
690 std::index_sequence<Is...>) {
691 // Intrinsic arguments follow the ID operand.
692 unsigned FirstArg = GI.getNumExplicitDefs() + 1;
693 return (std::get<Is>(Operands).match(
694 MRI, GI.getOperand(FirstArg + Is).getReg()) &&
695 ...);
696 }
697};
698
699template <Intrinsic::ID IntrID, typename... OpMatchers>
700inline GIntrinsic_match<IntrID, OpMatchers...>
701m_GIntrinsic(const OpMatchers &...Ops) {
702 return GIntrinsic_match<IntrID, OpMatchers...>(Ops...);
703}
704
705/// Matches a G_SHUFFLE_VECTOR, binding its two source operands and its mask.
706template <typename Src1Ty, typename Src2Ty> struct ShuffleVectorMatch {
707 Src1Ty Src1;
708 Src2Ty Src2;
710
711 ShuffleVectorMatch(const Src1Ty &Src1, const Src2Ty &Src2,
713 : Src1(Src1), Src2(Src2), Mask(Mask) {}
715 MachineInstr *TmpMI;
716 if (!mi_match(Reg, MRI, m_MInstr(TmpMI)))
717 return false;
718 auto *Shuf = dyn_cast<GShuffleVector>(TmpMI);
719 if (!Shuf || !Src1.match(MRI, Shuf->getSrc1Reg()) ||
720 !Src2.match(MRI, Shuf->getSrc2Reg()))
721 return false;
722 Mask = Shuf->getMask();
723 return true;
724 }
725};
726
727template <typename Src1Ty, typename Src2Ty>
729m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef<int> &Mask) {
730 return ShuffleVectorMatch<Src1Ty, Src2Ty>(Src1, Src2, Mask);
731}
732
733/// Matches a G_FRAME_INDEX, binding its frame index.
735 int &FI;
737 MachineInstr *TmpMI;
738 if (mi_match(Reg, MRI, m_MInstr(TmpMI)) &&
739 TmpMI->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
740 FI = TmpMI->getOperand(1).getIndex();
741 return true;
742 }
743 return false;
744 }
745};
746
747inline GFrameIndexMatch m_GFrameIndex(int &FI) { return {FI}; }
748
749// Helper for matching G_FCONSTANT
751
752// General helper for all the binary generic MI such as G_ADD/G_SUB etc
753template <typename LHS_P, typename RHS_P, unsigned Opcode,
754 bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
756 LHS_P L;
757 RHS_P R;
758 // Optional output: when set, receives the matched instruction's flags.
759 uint32_t *FlagsOut = nullptr;
760
761 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
762 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS, MIFlagsRef FlagsOut)
763 : L(LHS), R(RHS), FlagsOut(&FlagsOut.Flags) {}
764 template <typename OpTy>
766 const MachineInstr *TmpMI;
767 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
768 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
769 if ((TmpMI->getFlags() & Flags) != Flags)
770 return false;
771 if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
772 !R.match(MRI, TmpMI->getOperand(2).getReg())) &&
773 // NOTE: When trying the alternative operand ordering
774 // with a commutative operation, it is imperative to always run
775 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
776 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
777 // expected.
778 (!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
779 !R.match(MRI, TmpMI->getOperand(1).getReg())))
780 return false;
781 if (FlagsOut)
782 *FlagsOut = TmpMI->getFlags();
783 return true;
784 }
785 }
786 return false;
787 }
788};
789
790// Helper for (commutative) binary generic MI that checks Opcode.
791template <typename LHS_P, typename RHS_P, bool Commutable = false>
793 unsigned Opc;
794 LHS_P L;
795 RHS_P R;
796
797 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
798 : Opc(Opcode), L(LHS), R(RHS) {}
799 template <typename OpTy>
801 MachineInstr *TmpMI;
802 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
803 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
804 TmpMI->getNumOperands() == 3) {
805 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
806 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
807 // NOTE: When trying the alternative operand ordering
808 // with a commutative operation, it is imperative to always run
809 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
810 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
811 // expected.
812 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
813 R.match(MRI, TmpMI->getOperand(1).getReg())));
814 }
815 }
816 return false;
817 }
818};
819
820template <typename LHS, typename RHS>
821inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
822 const RHS &R) {
823 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
824}
825
826template <typename LHS, typename RHS>
828m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
829 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
830}
831
832template <typename LHS, typename RHS>
834m_GAdd(const LHS &L, const RHS &R) {
836}
837
838template <typename LHS, typename RHS>
843
844template <typename LHS, typename RHS>
850
851template <typename LHS, typename RHS>
856
857template <typename LHS, typename RHS>
859m_GPtrAdd(const LHS &L, const RHS &R, MIFlagsRef Flags) {
861}
862
863template <typename LHS, typename RHS>
868
869template <typename LHS, typename RHS>
871m_GSub(const LHS &L, const RHS &R, MIFlagsRef Flags) {
873}
874
875template <typename LHS, typename RHS>
877m_GMul(const LHS &L, const RHS &R) {
879}
880
881template <typename LHS, typename RHS>
883m_GFAdd(const LHS &L, const RHS &R) {
885}
886
887template <typename LHS, typename RHS>
889m_GFMul(const LHS &L, const RHS &R) {
891}
892
893template <typename LHS, typename RHS>
895m_GFSub(const LHS &L, const RHS &R) {
897}
898
899template <typename LHS, typename RHS>
901m_GAnd(const LHS &L, const RHS &R) {
903}
904
905template <typename LHS, typename RHS>
907m_GXor(const LHS &L, const RHS &R) {
909}
910
911template <typename LHS, typename RHS>
916
917template <typename LHS, typename RHS>
918inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
920m_GDisjointOr(const LHS &L, const RHS &R) {
921 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
923}
924
925template <typename LHS, typename RHS>
926inline auto m_GAddLike(const LHS &L, const RHS &R) {
927 return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
928}
929
930template <typename LHS, typename RHS>
932m_GShl(const LHS &L, const RHS &R) {
934}
935
936template <typename LHS, typename RHS>
938m_GLShr(const LHS &L, const RHS &R) {
940}
941
942template <typename LHS, typename RHS>
944m_GAShr(const LHS &L, const RHS &R) {
946}
947
948template <typename LHS, typename RHS>
950m_GSMax(const LHS &L, const RHS &R) {
952}
953
954template <typename LHS, typename RHS>
956m_GSMin(const LHS &L, const RHS &R) {
958}
959
960template <typename LHS, typename RHS>
962m_GUMax(const LHS &L, const RHS &R) {
964}
965
966template <typename LHS, typename RHS>
968m_GUMin(const LHS &L, const RHS &R) {
970}
971
972// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
973template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
974 SrcTy L;
975
976 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
977 template <typename OpTy>
979 MachineInstr *TmpMI;
980 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
981 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
982 return L.match(MRI, TmpMI->getOperand(1).getReg());
983 }
984 }
985 return false;
986 }
987};
988
989template <typename SrcTy>
991m_GAnyExt(const SrcTy &Src) {
993}
994
995template <typename SrcTy>
999
1000template <typename SrcTy>
1004
1005template <typename SrcTy>
1009
1010template <typename SrcTy>
1014
1015template <typename SrcTy>
1017m_GBitcast(const SrcTy &Src) {
1019}
1020
1021template <typename SrcTy>
1023m_GPtrToInt(const SrcTy &Src) {
1025}
1026
1027template <typename SrcTy>
1029m_GIntToPtr(const SrcTy &Src) {
1031}
1032
1033template <typename SrcTy>
1035m_GFPTrunc(const SrcTy &Src) {
1037}
1038
1039/// Matches an op that binds a source operand and an immediate operand with
1040/// sub-matchers (e.g. G_SEXT_INREG, G_ASSERT_ZEXT).
1041template <typename SrcTy, typename ImmTy, unsigned Opcode>
1043 SrcTy L;
1044 ImmTy Imm;
1045
1046 SrcImmOp_match(const SrcTy &LHS, const ImmTy &Imm) : L(LHS), Imm(Imm) {}
1047 template <typename OpTy>
1049 MachineInstr *TmpMI;
1050 return mi_match(Op, MRI, m_MInstr(TmpMI)) && TmpMI->getOpcode() == Opcode &&
1051 L.match(MRI, TmpMI->getOperand(1).getReg()) &&
1052 Imm.match(TmpMI->getOperand(2).getImm());
1053 }
1054};
1055
1056/// Matches any immediate operand.
1058 bool match(int64_t) const { return true; }
1059};
1060
1061/// Matches a G_SEXT_INREG, binding its source and immediate width.
1062template <typename SrcTy>
1064m_GSExtInReg(const SrcTy &Src) {
1065 return {Src, AnyImmMatch()};
1066}
1067
1068template <typename SrcTy, typename ImmTy>
1070m_GSExtInReg(const SrcTy &Src, const ImmTy &Imm) {
1071 return {Src, Imm};
1072}
1073
1074/// Matches a G_ASSERT_ZEXT, binding its source and immediate bit width.
1075template <typename SrcTy>
1077m_GAssertZext(const SrcTy &Src) {
1078 return {Src, AnyImmMatch()};
1079}
1080
1081template <typename SrcTy, typename ImmTy>
1083m_GAssertZext(const SrcTy &Src, const ImmTy &Imm) {
1084 return {Src, Imm};
1085}
1086
1087template <typename SrcTy>
1091
1092template <typename SrcTy>
1096
1097template <typename SrcTy>
1099 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
1100}
1101
1102template <typename SrcTy>
1106
1107template <typename SrcTy>
1109m_GFFloor(const SrcTy &Src) {
1111}
1112
1113// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
1114// TODO: Allow checking a specific predicate.
1115template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
1116 bool Commutable = false>
1118 Pred_P P;
1119 LHS_P L;
1120 RHS_P R;
1121
1122 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
1123 : P(Pred), L(LHS), R(RHS) {}
1124
1125 template <typename OpTy>
1127 MachineInstr *TmpMI;
1128 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
1129 return false;
1130
1131 auto TmpPred =
1132 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
1133 if (!P.match(MRI, TmpPred))
1134 return false;
1135 Register LHS = TmpMI->getOperand(2).getReg();
1136 Register RHS = TmpMI->getOperand(3).getReg();
1137 if (L.match(MRI, LHS) && R.match(MRI, RHS))
1138 return true;
1139 // NOTE: When trying the alternative operand ordering
1140 // with a commutative operation, it is imperative to always run
1141 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
1142 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
1143 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
1144 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
1145 return true;
1146 return false;
1147 }
1148};
1149
1150template <typename LHS_P, typename Test_P, unsigned Opcode>
1152 LHS_P L;
1153 Test_P T;
1154
1155 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
1156
1157 template <typename OpTy>
1159 MachineInstr *TmpMI;
1160 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
1161 return false;
1162
1163 Register LHS = TmpMI->getOperand(1).getReg();
1164 if (!L.match(MRI, LHS))
1165 return false;
1166
1167 FPClassTest TmpClass =
1168 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
1169 if (T.match(MRI, TmpClass))
1170 return true;
1171
1172 return false;
1173 }
1174};
1175
1176template <typename Pred, typename LHS, typename RHS>
1178m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
1180}
1181
1182template <typename Pred, typename LHS, typename RHS>
1184m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
1186}
1187
1188/// G_ICMP matcher that also matches commuted compares.
1189/// E.g.
1190///
1191/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
1192///
1193/// Could match both of:
1194///
1195/// icmp ugt (add x, y) (sub a, b)
1196/// icmp ult (sub a, b) (add x, y)
1197template <typename Pred, typename LHS, typename RHS>
1199m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
1201}
1202
1203/// G_FCMP matcher that also matches commuted compares.
1204/// E.g.
1205///
1206/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
1207///
1208/// Could match both of:
1209///
1210/// fcmp ogt (fadd x, y) (fmul a, b)
1211/// fcmp olt (fmul a, b) (fadd x, y)
1212template <typename Pred, typename LHS, typename RHS>
1214m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
1216}
1217
1218/// Matches the register and immediate used in a fpclass test
1219/// G_IS_FPCLASS %val, 96
1220template <typename LHS, typename Test>
1225
1226// Helper for checking if a Reg is of specific type.
1229 CheckType(const LLT Ty) : Ty(Ty) {}
1230
1232 return MRI.getType(Reg) == Ty;
1233 }
1234};
1235
1236inline CheckType m_SpecificType(LLT Ty) { return Ty; }
1237
1238template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
1240 Src0Ty Src0;
1241 Src1Ty Src1;
1242 Src2Ty Src2;
1243
1244 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
1245 : Src0(Src0), Src1(Src1), Src2(Src2) {}
1246 template <typename OpTy>
1248 MachineInstr *TmpMI;
1249 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
1250 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
1251 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
1252 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
1253 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
1254 }
1255 }
1256 return false;
1257 }
1258};
1259template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
1260inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
1261 TargetOpcode::G_INSERT_VECTOR_ELT>
1262m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
1263 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
1264 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
1265}
1266
1267template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
1269m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
1271 Src0, Src1, Src2);
1272}
1273
1274/// Matches a register negated by a G_SUB.
1275/// G_SUB 0, %negated_reg
1276template <typename SrcTy>
1278m_Neg(const SrcTy &&Src) {
1279 return m_GSub(m_ZeroInt(), Src);
1280}
1281
1282/// Matches a register not-ed by a G_XOR.
1283/// G_XOR %not_reg, -1
1284template <typename SrcTy>
1286m_Not(const SrcTy &&Src) {
1287 return m_GXor(Src, m_AllOnesInt());
1288}
1289
1290} // namespace MIPatternMatch
1291} // namespace llvm
1292
1293#endif
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)
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
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: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
@ 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: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
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
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_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)