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) {
83 return getIConstantVRegVal(Reg, MRI);
84}
85
86template <>
87inline std::optional<int64_t> matchConstant(Register Reg,
88 const MachineRegisterInfo &MRI) {
89 return getIConstantVRegSExtVal(Reg, 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 = *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) {
118 return getIConstantSplatVal(Reg, 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 = *MaybeCst;
133 return true;
134 }
135
136 if (auto MaybeCstSplat = matchConstantSplat<ConstT>(Reg, MRI)) {
137 CR = *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) {}
158 return ValReg ? true : false;
159 }
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) {}
172 return FPValReg ? true : false;
173 }
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) {}
185 return (FPValReg = getFConstantSplat(Reg, MRI)) ||
187 };
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 if (MatchedVal.getBitWidth() > RequestedVal.getBitWidth())
221 RequestedVal = RequestedVal.sext(MatchedVal.getBitWidth());
222 else
223 MatchedVal = MatchedVal.sext(RequestedVal.getBitWidth());
224
225 return APInt::isSameValue(MatchedVal, RequestedVal);
226 }
227 return false;
228 }
229};
230
231/// Matches a constant equal to \p RequestedValue.
232inline SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue) {
233 return SpecificConstantMatch(RequestedValue);
234}
235
236inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
237 return SpecificConstantMatch(APInt(64, RequestedValue, /* isSigned */ true));
238}
239
243 bool match(int64_t Imm) const { return Imm == RequestedVal; }
244};
245
246/// Matches an immediate operand equal to \p RequestedValue.
247inline SpecificImmMatch m_SpecificImm(int64_t RequestedValue) {
248 return SpecificImmMatch(RequestedValue);
249}
250
252 int64_t &ImmOut;
254 bool match(int64_t Imm) const {
255 ImmOut = Imm;
256 return true;
257 }
258};
259
260/// Binds an immediate operand's value.
261inline BindImmMatch m_Imm(int64_t &Imm) { return BindImmMatch(Imm); }
262
263/// Matches an integer constant with all bits set, regardless of width.
266 APInt MatchedVal;
267 return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal.isAllOnes();
268 }
269};
270
271inline AllOnesConstantMatch m_AllOnes() { return {}; }
272
273/// Matcher for a specific constant splat.
283
284/// Matches a constant splat of \p RequestedValue.
286m_SpecificICstSplat(const APInt &RequestedValue) {
287 return SpecificConstantSplatMatch(RequestedValue);
288}
289
290inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
292 APInt(64, RequestedValue, /* isSigned */ true));
293}
294
295/// Matcher for a specific constant or constant splat.
301 APInt MatchedVal;
302 if (mi_match(Reg, MRI, m_ICst(MatchedVal))) {
303 if (MatchedVal.getBitWidth() > RequestedVal.getBitWidth())
304 RequestedVal = RequestedVal.sext(MatchedVal.getBitWidth());
305 else
306 MatchedVal = MatchedVal.sext(RequestedVal.getBitWidth());
307
308 if (APInt::isSameValue(MatchedVal, RequestedVal))
309 return true;
310 }
312 /* AllowUndef */ false);
313 }
314};
315
316/// Matches a \p RequestedValue constant or a constant splat of \p
317/// RequestedValue.
319m_SpecificICstOrSplat(const APInt &RequestedValue) {
320 return SpecificConstantOrSplatMatch(RequestedValue);
321}
322
324m_SpecificICstOrSplat(int64_t RequestedValue) {
326 APInt(64, RequestedValue, /* isSigned */ true));
327}
328
329/// Convenience matchers for specific integer values.
336
337/// Matcher for a specific register.
345
346/// Matches a register only if it is equal to \p RequestedReg.
348 return SpecificRegisterMatch(RequestedReg);
349}
350
351// TODO: Rework this for different kinds of MachineOperand.
352// Currently assumes the Src for a match is a register.
353// We might want to support taking in some MachineOperands and call getReg on
354// that.
355
357 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
359 return MO->isReg();
360 }
361};
362
364
365/// Matching combinators.
366template <typename... Preds> struct And {
367 template <typename MatchSrc>
368 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
369 return true;
370 }
371};
372
373template <typename Pred, typename... Preds>
374struct And<Pred, Preds...> : And<Preds...> {
375 Pred P;
376 And(Pred &&p, Preds &&... preds)
377 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
378 }
379 template <typename MatchSrc>
380 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
381 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
382 }
383};
384
385template <typename... Preds> struct Or {
386 template <typename MatchSrc>
387 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
388 return false;
389 }
390};
391
392template <typename Pred, typename... Preds>
393struct Or<Pred, Preds...> : Or<Preds...> {
394 Pred P;
395 Or(Pred &&p, Preds &&... preds)
396 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
397 template <typename MatchSrc>
398 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
399 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
400 }
401};
402
403template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
404 return And<Preds...>(std::forward<Preds>(preds)...);
405}
406
407template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
408 return Or<Preds...>(std::forward<Preds>(preds)...);
409}
410
411template <typename BindTy> struct bind_helper {
412 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
413 VR = V;
414 return true;
415 }
416};
417
418template <> struct bind_helper<MachineInstr *> {
419 static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
420 Register Reg) {
421 MI = MRI.getVRegDef(Reg);
422 if (MI)
423 return true;
424 return false;
425 }
426 static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
427 MachineInstr *Inst) {
428 MI = Inst;
429 return MI;
430 }
431};
432
433template <> struct bind_helper<const MachineInstr *> {
434 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
435 Register Reg) {
436 MI = MRI.getVRegDef(Reg);
437 return MI;
438 }
439 static bool bind(const MachineRegisterInfo &MRI, const MachineInstr *&MI,
440 const MachineInstr *Inst) {
441 MI = Inst;
442 return MI;
443 }
444};
445
446template <> struct bind_helper<LLT> {
447 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
448 Ty = MRI.getType(Reg);
449 if (Ty.isValid())
450 return true;
451 return false;
452 }
453};
454
455template <> struct bind_helper<const ConstantFP *> {
456 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
457 Register Reg) {
458 F = getConstantFPVRegVal(Reg, MRI);
459 if (F)
460 return true;
461 return false;
462 }
463};
464
465template <typename Class> struct bind_ty {
466 Class &VR;
467
468 bind_ty(Class &V) : VR(V) {}
469
470 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
471 return bind_helper<Class>::bind(MRI, VR, V);
472 }
473};
474
475inline bind_ty<Register> m_Reg(Register &R) { return R; }
478 return MI;
479}
480inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
484
485/// Wraps a MIFlags output for use as an optional trailing operand of an
486/// instruction matcher (e.g. m_GPtrAdd(L, R, m_MIFlags(Flags))). On a
487/// successful match the matched instruction's flags are written to \p Flags.
491
492inline MIFlagsRef m_MIFlags(uint32_t &Flags) { return {Flags}; }
493
494/// Optional trailing operand for a load matcher (e.g. m_GLoad(m_Reg(Ptr),
495/// m_MMO(MMO))) that binds the matched instruction's MachineMemOperand.
496struct MMORef {
498};
499
500inline MMORef m_MMO(const MachineMemOperand *&MMO) { return {MMO}; }
501
502template <typename BindTy> struct deferred_helper {
503 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
504 return VR == V;
505 }
506};
507
508template <> struct deferred_helper<LLT> {
509 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
510 return VT == MRI.getType(R);
511 }
512};
513
514template <typename Class> struct deferred_ty {
515 Class &VR;
516
517 deferred_ty(Class &V) : VR(V) {}
518
519 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
520 return deferred_helper<Class>::match(MRI, VR, V);
521 }
522};
523
524/// Similar to m_SpecificReg/Type, but the specific value to match originated
525/// from an earlier sub-pattern in the same mi_match expression. For example,
526/// we cannot match `(add X, X)` with `m_GAdd(m_Reg(X), m_SpecificReg(X))`
527/// because `X` is not initialized at the time it's passed to `m_SpecificReg`.
528/// Instead, we can use `m_GAdd(m_Reg(x), m_DeferredReg(X))`.
530inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
531
534 MachineInstr *TmpMI;
535 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
536 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
537 return false;
538 }
539};
540
542
543/// Binds the defining instruction of \p Reg if it is a \p Class. Prefer the
544/// named helpers below so the opcode is spelled out at the call site.
545template <typename Class> struct GInstrBind {
546 Class *&Inst;
547
548 GInstrBind(Class *&Inst) : Inst(Inst) {}
550 MachineInstr *TmpMI;
551 if (mi_match(Reg, MRI, m_MInstr(TmpMI))) {
552 if (auto *Cst = dyn_cast<Class>(TmpMI)) {
553 Inst = Cst;
554 return true;
555 }
556 }
557 return false;
558 }
559};
560
561/// Match a literal G_CONSTANT instruction (no look-through of splats or
562/// copies).
563inline GInstrBind<GConstant> m_GConstant(GConstant *&Inst) { return Inst; }
565 return Inst;
566}
567
568/// Match a literal G_CONSTANT or G_FCONSTANT, binding its raw bits to \p Bits
569/// (the integer value, or the float reinterpreted as an integer).
574 if (MI->getOpcode() == TargetOpcode::G_CONSTANT) {
575 Bits = MI->getOperand(1).getCImm()->getValue();
576 return true;
577 }
578 if (MI->getOpcode() == TargetOpcode::G_FCONSTANT) {
579 Bits = MI->getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
580 return true;
581 }
582 return false;
583 }
584};
585
587 return {Bits};
588}
589
590/// Match a load of type \p Class, binding its pointer operand (like IR's
591/// m_Load), and optionally the instruction and/or its MachineMemOperand.
592template <typename Class, typename PtrP> struct LoadOp_match {
593 PtrP Ptr;
594 Class **InstOut = nullptr;
595 const MachineMemOperand **MMOOut = nullptr;
596
597 LoadOp_match(const PtrP &Ptr) : Ptr(Ptr) {}
598 LoadOp_match(const PtrP &Ptr, MMORef MMO) : Ptr(Ptr), MMOOut(&MMO.MMO) {}
599 LoadOp_match(Class *&Inst, const PtrP &Ptr) : Ptr(Ptr), InstOut(&Inst) {}
600 LoadOp_match(Class *&Inst, const PtrP &Ptr, MMORef MMO)
601 : Ptr(Ptr), InstOut(&Inst), MMOOut(&MMO.MMO) {}
602
604 MachineInstr *TmpMI;
605 if (!mi_match(Reg, MRI, m_MInstr(TmpMI)))
606 return false;
607 auto *Load = dyn_cast<Class>(TmpMI);
608 if (!Load || !Ptr.match(MRI, Load->getPointerReg()))
609 return false;
610 if (InstOut)
611 *InstOut = Load;
612 if (MMOOut)
613 *MMOOut = &Load->getMMO();
614 return true;
615 }
616};
617
618template <typename PtrP>
621}
622template <typename PtrP>
624 const PtrP &Ptr) {
625 return LoadOp_match<GAnyLoad, PtrP>(Inst, Ptr);
626}
627template <typename PtrP>
628inline LoadOp_match<GAnyLoad, PtrP> m_GAnyLoad(GAnyLoad *&Inst, const PtrP &Ptr,
629 MMORef MMO) {
630 return LoadOp_match<GAnyLoad, PtrP>(Inst, Ptr, MMO);
631}
632template <typename PtrP>
633inline LoadOp_match<GLoad, PtrP> m_GLoad(const PtrP &Ptr) {
634 return LoadOp_match<GLoad, PtrP>(Ptr);
635}
636template <typename PtrP>
637inline LoadOp_match<GLoad, PtrP> m_GLoad(const PtrP &Ptr, MMORef MMO) {
638 return LoadOp_match<GLoad, PtrP>(Ptr, MMO);
639}
640
641/// Instruction binders for ops with no operand-form matcher (constant-immediate
642/// or variadic-source ops).
643inline GInstrBind<GUnmerge> m_GUnmerge(GUnmerge *&Inst) { return Inst; }
644inline GInstrBind<GVScale> m_GVScale(GVScale *&Inst) { return Inst; }
646 return Inst;
647}
649 return Inst;
650}
651
652/// Binds the defining instruction of \p Reg if it is a GIntrinsic (any of the
653/// four G_INTRINSIC* opcodes).
654inline GInstrBind<GIntrinsic> m_GIntrinsic(GIntrinsic *&Inst) { return Inst; }
656 return Inst;
657}
658
659/// Matches a GIntrinsic with a specific intrinsic ID and optionally, matchers
660/// for its leading arguments.
661template <Intrinsic::ID IntrID, typename... OpMatchers>
663 std::tuple<OpMatchers...> Operands;
664
665 GIntrinsic_match(const OpMatchers &...Ops) : Operands(Ops...) {}
666
667 template <typename OpTy>
668 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
669 MachineInstr *TmpMI;
670 if (!mi_match(Op, MRI, m_MInstr(TmpMI)))
671 return false;
672 auto *GI = dyn_cast<GIntrinsic>(TmpMI);
673 if (!GI || !GI->is(IntrID))
674 return false;
675 return matchOperands(MRI, *GI, std::index_sequence_for<OpMatchers...>{});
676 }
677
678private:
679 template <size_t... Is>
680 bool matchOperands(const MachineRegisterInfo &MRI, GIntrinsic &GI,
681 std::index_sequence<Is...>) {
682 // Intrinsic arguments follow the ID operand.
683 unsigned FirstArg = GI.getNumExplicitDefs() + 1;
684 return (std::get<Is>(Operands).match(
685 MRI, GI.getOperand(FirstArg + Is).getReg()) &&
686 ...);
687 }
688};
689
690template <Intrinsic::ID IntrID, typename... OpMatchers>
691inline GIntrinsic_match<IntrID, OpMatchers...>
692m_GIntrinsic(const OpMatchers &...Ops) {
693 return GIntrinsic_match<IntrID, OpMatchers...>(Ops...);
694}
695
696/// Matches a G_SHUFFLE_VECTOR, binding its two source operands and its mask.
697template <typename Src1Ty, typename Src2Ty> struct ShuffleVectorMatch {
698 Src1Ty Src1;
699 Src2Ty Src2;
701
702 ShuffleVectorMatch(const Src1Ty &Src1, const Src2Ty &Src2,
704 : Src1(Src1), Src2(Src2), Mask(Mask) {}
706 MachineInstr *TmpMI;
707 if (!mi_match(Reg, MRI, m_MInstr(TmpMI)))
708 return false;
709 auto *Shuf = dyn_cast<GShuffleVector>(TmpMI);
710 if (!Shuf || !Src1.match(MRI, Shuf->getSrc1Reg()) ||
711 !Src2.match(MRI, Shuf->getSrc2Reg()))
712 return false;
713 Mask = Shuf->getMask();
714 return true;
715 }
716};
717
718template <typename Src1Ty, typename Src2Ty>
720m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef<int> &Mask) {
721 return ShuffleVectorMatch<Src1Ty, Src2Ty>(Src1, Src2, Mask);
722}
723
724/// Matches a G_FRAME_INDEX, binding its frame index.
726 int &FI;
728 MachineInstr *TmpMI;
729 if (mi_match(Reg, MRI, m_MInstr(TmpMI)) &&
730 TmpMI->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
731 FI = TmpMI->getOperand(1).getIndex();
732 return true;
733 }
734 return false;
735 }
736};
737
738inline GFrameIndexMatch m_GFrameIndex(int &FI) { return {FI}; }
739
740// Helper for matching G_FCONSTANT
742
743// General helper for all the binary generic MI such as G_ADD/G_SUB etc
744template <typename LHS_P, typename RHS_P, unsigned Opcode,
745 bool Commutable = false, unsigned Flags = MachineInstr::NoFlags>
747 LHS_P L;
748 RHS_P R;
749 // Optional output: when set, receives the matched instruction's flags.
750 uint32_t *FlagsOut = nullptr;
751
752 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
753 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS, MIFlagsRef FlagsOut)
754 : L(LHS), R(RHS), FlagsOut(&FlagsOut.Flags) {}
755 template <typename OpTy>
756 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
757 const MachineInstr *TmpMI;
758 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
759 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
760 if ((!L.match(MRI, TmpMI->getOperand(1).getReg()) ||
761 !R.match(MRI, TmpMI->getOperand(2).getReg())) &&
762 // NOTE: When trying the alternative operand ordering
763 // with a commutative operation, it is imperative to always run
764 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
765 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
766 // expected.
767 (!Commutable || !L.match(MRI, TmpMI->getOperand(2).getReg()) ||
768 !R.match(MRI, TmpMI->getOperand(1).getReg())))
769 return false;
770 if ((TmpMI->getFlags() & Flags) != Flags)
771 return false;
772 if (FlagsOut)
773 *FlagsOut = TmpMI->getFlags();
774 return true;
775 }
776 }
777 return false;
778 }
779};
780
781// Helper for (commutative) binary generic MI that checks Opcode.
782template <typename LHS_P, typename RHS_P, bool Commutable = false>
784 unsigned Opc;
785 LHS_P L;
786 RHS_P R;
787
788 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
789 : Opc(Opcode), L(LHS), R(RHS) {}
790 template <typename OpTy>
791 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
792 MachineInstr *TmpMI;
793 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
794 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
795 TmpMI->getNumOperands() == 3) {
796 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
797 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
798 // NOTE: When trying the alternative operand ordering
799 // with a commutative operation, it is imperative to always run
800 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
801 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as
802 // expected.
803 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
804 R.match(MRI, TmpMI->getOperand(1).getReg())));
805 }
806 }
807 return false;
808 }
809};
810
811template <typename LHS, typename RHS>
812inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
813 const RHS &R) {
814 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
815}
816
817template <typename LHS, typename RHS>
819m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
820 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
821}
822
823template <typename LHS, typename RHS>
825m_GAdd(const LHS &L, const RHS &R) {
827}
828
829template <typename LHS, typename RHS>
834
835template <typename LHS, typename RHS>
841
842template <typename LHS, typename RHS>
847
848template <typename LHS, typename RHS>
850m_GPtrAdd(const LHS &L, const RHS &R, MIFlagsRef Flags) {
852}
853
854template <typename LHS, typename RHS>
859
860template <typename LHS, typename RHS>
862m_GSub(const LHS &L, const RHS &R, MIFlagsRef Flags) {
864}
865
866template <typename LHS, typename RHS>
868m_GMul(const LHS &L, const RHS &R) {
870}
871
872template <typename LHS, typename RHS>
874m_GFAdd(const LHS &L, const RHS &R) {
876}
877
878template <typename LHS, typename RHS>
880m_GFMul(const LHS &L, const RHS &R) {
882}
883
884template <typename LHS, typename RHS>
886m_GFSub(const LHS &L, const RHS &R) {
888}
889
890template <typename LHS, typename RHS>
892m_GAnd(const LHS &L, const RHS &R) {
894}
895
896template <typename LHS, typename RHS>
898m_GXor(const LHS &L, const RHS &R) {
900}
901
902template <typename LHS, typename RHS>
907
908template <typename LHS, typename RHS>
909inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
911m_GDisjointOr(const LHS &L, const RHS &R) {
912 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true,
914}
915
916template <typename LHS, typename RHS>
917inline auto m_GAddLike(const LHS &L, const RHS &R) {
918 return m_any_of(m_GAdd(L, R), m_GDisjointOr(L, R));
919}
920
921template <typename LHS, typename RHS>
923m_GShl(const LHS &L, const RHS &R) {
925}
926
927template <typename LHS, typename RHS>
929m_GLShr(const LHS &L, const RHS &R) {
931}
932
933template <typename LHS, typename RHS>
935m_GAShr(const LHS &L, const RHS &R) {
937}
938
939template <typename LHS, typename RHS>
941m_GSMax(const LHS &L, const RHS &R) {
943}
944
945template <typename LHS, typename RHS>
947m_GSMin(const LHS &L, const RHS &R) {
949}
950
951template <typename LHS, typename RHS>
953m_GUMax(const LHS &L, const RHS &R) {
955}
956
957template <typename LHS, typename RHS>
959m_GUMin(const LHS &L, const RHS &R) {
961}
962
963// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc
964template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
965 SrcTy L;
966
967 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
968 template <typename OpTy>
969 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
970 MachineInstr *TmpMI;
971 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
972 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
973 return L.match(MRI, TmpMI->getOperand(1).getReg());
974 }
975 }
976 return false;
977 }
978};
979
980template <typename SrcTy>
982m_GAnyExt(const SrcTy &Src) {
984}
985
986template <typename SrcTy>
990
991template <typename SrcTy>
995
996template <typename SrcTy>
1000
1001template <typename SrcTy>
1005
1006template <typename SrcTy>
1008m_GBitcast(const SrcTy &Src) {
1010}
1011
1012template <typename SrcTy>
1014m_GPtrToInt(const SrcTy &Src) {
1016}
1017
1018template <typename SrcTy>
1020m_GIntToPtr(const SrcTy &Src) {
1022}
1023
1024template <typename SrcTy>
1026m_GFPTrunc(const SrcTy &Src) {
1028}
1029
1030/// Matches an op that binds a source operand and an immediate operand with
1031/// sub-matchers (e.g. G_SEXT_INREG, G_ASSERT_ZEXT).
1032template <typename SrcTy, typename ImmTy, unsigned Opcode>
1034 SrcTy L;
1035 ImmTy Imm;
1036
1037 SrcImmOp_match(const SrcTy &LHS, const ImmTy &Imm) : L(LHS), Imm(Imm) {}
1038 template <typename OpTy>
1039 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
1040 MachineInstr *TmpMI;
1041 return mi_match(Op, MRI, m_MInstr(TmpMI)) && TmpMI->getOpcode() == Opcode &&
1042 L.match(MRI, TmpMI->getOperand(1).getReg()) &&
1043 Imm.match(TmpMI->getOperand(2).getImm());
1044 }
1045};
1046
1047/// Matches any immediate operand.
1049 bool match(int64_t) const { return true; }
1050};
1051
1052/// Matches a G_SEXT_INREG, binding its source and immediate width.
1053template <typename SrcTy>
1055m_GSExtInReg(const SrcTy &Src) {
1056 return {Src, AnyImmMatch()};
1057}
1058
1059template <typename SrcTy, typename ImmTy>
1061m_GSExtInReg(const SrcTy &Src, const ImmTy &Imm) {
1062 return {Src, Imm};
1063}
1064
1065/// Matches a G_ASSERT_ZEXT, binding its source and immediate bit width.
1066template <typename SrcTy>
1068m_GAssertZext(const SrcTy &Src) {
1069 return {Src, AnyImmMatch()};
1070}
1071
1072template <typename SrcTy, typename ImmTy>
1074m_GAssertZext(const SrcTy &Src, const ImmTy &Imm) {
1075 return {Src, Imm};
1076}
1077
1078template <typename SrcTy>
1082
1083template <typename SrcTy>
1087
1088template <typename SrcTy>
1090 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
1091}
1092
1093template <typename SrcTy>
1097
1098template <typename SrcTy>
1100m_GFFloor(const SrcTy &Src) {
1102}
1103
1104// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
1105// TODO: Allow checking a specific predicate.
1106template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
1107 bool Commutable = false>
1109 Pred_P P;
1110 LHS_P L;
1111 RHS_P R;
1112
1113 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
1114 : P(Pred), L(LHS), R(RHS) {}
1115
1116 template <typename OpTy>
1117 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
1118 MachineInstr *TmpMI;
1119 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
1120 return false;
1121
1122 auto TmpPred =
1123 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
1124 if (!P.match(MRI, TmpPred))
1125 return false;
1126 Register LHS = TmpMI->getOperand(2).getReg();
1127 Register RHS = TmpMI->getOperand(3).getReg();
1128 if (L.match(MRI, LHS) && R.match(MRI, RHS))
1129 return true;
1130 // NOTE: When trying the alternative operand ordering
1131 // with a commutative operation, it is imperative to always run
1132 // the LHS sub-pattern (i.e. `L`) before the RHS sub-pattern
1133 // (i.e. `R`). Otherwise, m_DeferredReg/Type will not work as expected.
1134 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
1135 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
1136 return true;
1137 return false;
1138 }
1139};
1140
1141template <typename LHS_P, typename Test_P, unsigned Opcode>
1143 LHS_P L;
1144 Test_P T;
1145
1146 ClassifyOp_match(const LHS_P &LHS, const Test_P &Tst) : L(LHS), T(Tst) {}
1147
1148 template <typename OpTy>
1149 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
1150 MachineInstr *TmpMI;
1151 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
1152 return false;
1153
1154 Register LHS = TmpMI->getOperand(1).getReg();
1155 if (!L.match(MRI, LHS))
1156 return false;
1157
1158 FPClassTest TmpClass =
1159 static_cast<FPClassTest>(TmpMI->getOperand(2).getImm());
1160 if (T.match(MRI, TmpClass))
1161 return true;
1162
1163 return false;
1164 }
1165};
1166
1167template <typename Pred, typename LHS, typename RHS>
1169m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
1171}
1172
1173template <typename Pred, typename LHS, typename RHS>
1175m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
1177}
1178
1179/// G_ICMP matcher that also matches commuted compares.
1180/// E.g.
1181///
1182/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
1183///
1184/// Could match both of:
1185///
1186/// icmp ugt (add x, y) (sub a, b)
1187/// icmp ult (sub a, b) (add x, y)
1188template <typename Pred, typename LHS, typename RHS>
1190m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
1192}
1193
1194/// G_FCMP matcher that also matches commuted compares.
1195/// E.g.
1196///
1197/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
1198///
1199/// Could match both of:
1200///
1201/// fcmp ogt (fadd x, y) (fmul a, b)
1202/// fcmp olt (fmul a, b) (fadd x, y)
1203template <typename Pred, typename LHS, typename RHS>
1205m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
1207}
1208
1209/// Matches the register and immediate used in a fpclass test
1210/// G_IS_FPCLASS %val, 96
1211template <typename LHS, typename Test>
1216
1217// Helper for checking if a Reg is of specific type.
1220 CheckType(const LLT Ty) : Ty(Ty) {}
1221
1223 return MRI.getType(Reg) == Ty;
1224 }
1225};
1226
1227inline CheckType m_SpecificType(LLT Ty) { return Ty; }
1228
1229template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
1231 Src0Ty Src0;
1232 Src1Ty Src1;
1233 Src2Ty Src2;
1234
1235 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
1236 : Src0(Src0), Src1(Src1), Src2(Src2) {}
1237 template <typename OpTy>
1238 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
1239 MachineInstr *TmpMI;
1240 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
1241 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
1242 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
1243 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
1244 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
1245 }
1246 }
1247 return false;
1248 }
1249};
1250template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
1251inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
1252 TargetOpcode::G_INSERT_VECTOR_ELT>
1253m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
1254 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
1255 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
1256}
1257
1258template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
1260m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
1262 Src0, Src1, Src2);
1263}
1264
1265/// Matches a register negated by a G_SUB.
1266/// G_SUB 0, %negated_reg
1267template <typename SrcTy>
1269m_Neg(const SrcTy &&Src) {
1270 return m_GSub(m_ZeroInt(), Src);
1271}
1272
1273/// Matches a register not-ed by a G_XOR.
1274/// G_XOR %not_reg, -1
1275template <typename SrcTy>
1277m_Not(const SrcTy &&Src) {
1278 return m_GXor(Src, m_AllOnesInt());
1279}
1280
1281} // namespace MIPatternMatch
1282} // namespace llvm
1283
1284#endif
aarch64 promote const
unsigned 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)
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:231
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
Definition APInt.h:368
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1509
static bool isSameValue(const APInt &I1, const APInt &I2, bool SignedCompare=false)
Determine if two APInts have the same value, after zero-extending or sign-extending (if SignedCompare...
Definition APInt.h:551
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1029
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:197
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_UNMERGE_VALUES.
Represents a vscale.
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,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
operand_type_match m_Reg()
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)
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, binding its pointer operand (like IR's m_Load), and optionally the instru...
LoadOp_match(Class *&Inst, const PtrP &Ptr, MMORef MMO)
bool match(const MachineRegisterInfo &MRI, Register Reg)
const MachineMemOperand ** MMOOut
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)