File indexing completed on 2026-05-10 08:43:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
0014 #define LLVM_CODEGEN_GLOBALISEL_MIPATTERNMATCH_H
0015
0016 #include "llvm/ADT/APInt.h"
0017 #include "llvm/CodeGen/GlobalISel/Utils.h"
0018 #include "llvm/CodeGen/MachineRegisterInfo.h"
0019 #include "llvm/IR/InstrTypes.h"
0020
0021 namespace llvm {
0022 namespace MIPatternMatch {
0023
0024 template <typename Reg, typename Pattern>
0025 [[nodiscard]] bool mi_match(Reg R, const MachineRegisterInfo &MRI,
0026 Pattern &&P) {
0027 return P.match(MRI, R);
0028 }
0029
0030 template <typename Pattern>
0031 [[nodiscard]] bool mi_match(MachineInstr &MI, const MachineRegisterInfo &MRI,
0032 Pattern &&P) {
0033 return P.match(MRI, &MI);
0034 }
0035
0036
0037 template <typename SubPatternT> struct OneUse_match {
0038 SubPatternT SubPat;
0039 OneUse_match(const SubPatternT &SP) : SubPat(SP) {}
0040
0041 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0042 return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg);
0043 }
0044 };
0045
0046 template <typename SubPat>
0047 inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) {
0048 return SP;
0049 }
0050
0051 template <typename SubPatternT> struct OneNonDBGUse_match {
0052 SubPatternT SubPat;
0053 OneNonDBGUse_match(const SubPatternT &SP) : SubPat(SP) {}
0054
0055 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0056 return MRI.hasOneNonDBGUse(Reg) && SubPat.match(MRI, Reg);
0057 }
0058 };
0059
0060 template <typename SubPat>
0061 inline OneNonDBGUse_match<SubPat> m_OneNonDBGUse(const SubPat &SP) {
0062 return SP;
0063 }
0064
0065 template <typename ConstT>
0066 inline std::optional<ConstT> matchConstant(Register,
0067 const MachineRegisterInfo &);
0068
0069 template <>
0070 inline std::optional<APInt> matchConstant(Register Reg,
0071 const MachineRegisterInfo &MRI) {
0072 return getIConstantVRegVal(Reg, MRI);
0073 }
0074
0075 template <>
0076 inline std::optional<int64_t> matchConstant(Register Reg,
0077 const MachineRegisterInfo &MRI) {
0078 return getIConstantVRegSExtVal(Reg, MRI);
0079 }
0080
0081 template <typename ConstT> struct ConstantMatch {
0082 ConstT &CR;
0083 ConstantMatch(ConstT &C) : CR(C) {}
0084 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0085 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
0086 CR = *MaybeCst;
0087 return true;
0088 }
0089 return false;
0090 }
0091 };
0092
0093 inline ConstantMatch<APInt> m_ICst(APInt &Cst) {
0094 return ConstantMatch<APInt>(Cst);
0095 }
0096 inline ConstantMatch<int64_t> m_ICst(int64_t &Cst) {
0097 return ConstantMatch<int64_t>(Cst);
0098 }
0099
0100 template <typename ConstT>
0101 inline std::optional<ConstT> matchConstantSplat(Register,
0102 const MachineRegisterInfo &);
0103
0104 template <>
0105 inline std::optional<APInt> matchConstantSplat(Register Reg,
0106 const MachineRegisterInfo &MRI) {
0107 return getIConstantSplatVal(Reg, MRI);
0108 }
0109
0110 template <>
0111 inline std::optional<int64_t>
0112 matchConstantSplat(Register Reg, const MachineRegisterInfo &MRI) {
0113 return getIConstantSplatSExtVal(Reg, MRI);
0114 }
0115
0116 template <typename ConstT> struct ICstOrSplatMatch {
0117 ConstT &CR;
0118 ICstOrSplatMatch(ConstT &C) : CR(C) {}
0119 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0120 if (auto MaybeCst = matchConstant<ConstT>(Reg, MRI)) {
0121 CR = *MaybeCst;
0122 return true;
0123 }
0124
0125 if (auto MaybeCstSplat = matchConstantSplat<ConstT>(Reg, MRI)) {
0126 CR = *MaybeCstSplat;
0127 return true;
0128 }
0129
0130 return false;
0131 };
0132 };
0133
0134 inline ICstOrSplatMatch<APInt> m_ICstOrSplat(APInt &Cst) {
0135 return ICstOrSplatMatch<APInt>(Cst);
0136 }
0137
0138 inline ICstOrSplatMatch<int64_t> m_ICstOrSplat(int64_t &Cst) {
0139 return ICstOrSplatMatch<int64_t>(Cst);
0140 }
0141
0142 struct GCstAndRegMatch {
0143 std::optional<ValueAndVReg> &ValReg;
0144 GCstAndRegMatch(std::optional<ValueAndVReg> &ValReg) : ValReg(ValReg) {}
0145 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0146 ValReg = getIConstantVRegValWithLookThrough(Reg, MRI);
0147 return ValReg ? true : false;
0148 }
0149 };
0150
0151 inline GCstAndRegMatch m_GCst(std::optional<ValueAndVReg> &ValReg) {
0152 return GCstAndRegMatch(ValReg);
0153 }
0154
0155 struct GFCstAndRegMatch {
0156 std::optional<FPValueAndVReg> &FPValReg;
0157 GFCstAndRegMatch(std::optional<FPValueAndVReg> &FPValReg)
0158 : FPValReg(FPValReg) {}
0159 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0160 FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI);
0161 return FPValReg ? true : false;
0162 }
0163 };
0164
0165 inline GFCstAndRegMatch m_GFCst(std::optional<FPValueAndVReg> &FPValReg) {
0166 return GFCstAndRegMatch(FPValReg);
0167 }
0168
0169 struct GFCstOrSplatGFCstMatch {
0170 std::optional<FPValueAndVReg> &FPValReg;
0171 GFCstOrSplatGFCstMatch(std::optional<FPValueAndVReg> &FPValReg)
0172 : FPValReg(FPValReg) {}
0173 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0174 return (FPValReg = getFConstantSplat(Reg, MRI)) ||
0175 (FPValReg = getFConstantVRegValWithLookThrough(Reg, MRI));
0176 };
0177 };
0178
0179 inline GFCstOrSplatGFCstMatch
0180 m_GFCstOrSplat(std::optional<FPValueAndVReg> &FPValReg) {
0181 return GFCstOrSplatGFCstMatch(FPValReg);
0182 }
0183
0184
0185 struct SpecificConstantMatch {
0186 int64_t RequestedVal;
0187 SpecificConstantMatch(int64_t RequestedVal) : RequestedVal(RequestedVal) {}
0188 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0189 int64_t MatchedVal;
0190 return mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal;
0191 }
0192 };
0193
0194
0195 inline SpecificConstantMatch m_SpecificICst(int64_t RequestedValue) {
0196 return SpecificConstantMatch(RequestedValue);
0197 }
0198
0199
0200 struct SpecificConstantSplatMatch {
0201 int64_t RequestedVal;
0202 SpecificConstantSplatMatch(int64_t RequestedVal)
0203 : RequestedVal(RequestedVal) {}
0204 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0205 return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
0206 false);
0207 }
0208 };
0209
0210
0211 inline SpecificConstantSplatMatch m_SpecificICstSplat(int64_t RequestedValue) {
0212 return SpecificConstantSplatMatch(RequestedValue);
0213 }
0214
0215
0216 struct SpecificConstantOrSplatMatch {
0217 int64_t RequestedVal;
0218 SpecificConstantOrSplatMatch(int64_t RequestedVal)
0219 : RequestedVal(RequestedVal) {}
0220 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0221 int64_t MatchedVal;
0222 if (mi_match(Reg, MRI, m_ICst(MatchedVal)) && MatchedVal == RequestedVal)
0223 return true;
0224 return isBuildVectorConstantSplat(Reg, MRI, RequestedVal,
0225 false);
0226 }
0227 };
0228
0229
0230
0231 inline SpecificConstantOrSplatMatch
0232 m_SpecificICstOrSplat(int64_t RequestedValue) {
0233 return SpecificConstantOrSplatMatch(RequestedValue);
0234 }
0235
0236
0237
0238 inline SpecificConstantMatch m_ZeroInt() { return SpecificConstantMatch(0); }
0239 inline SpecificConstantMatch m_AllOnesInt() {
0240 return SpecificConstantMatch(-1);
0241 }
0242
0243
0244
0245 struct SpecificRegisterMatch {
0246 Register RequestedReg;
0247 SpecificRegisterMatch(Register RequestedReg) : RequestedReg(RequestedReg) {}
0248 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0249 return Reg == RequestedReg;
0250 }
0251 };
0252
0253
0254 inline SpecificRegisterMatch m_SpecificReg(Register RequestedReg) {
0255 return SpecificRegisterMatch(RequestedReg);
0256 }
0257
0258
0259
0260
0261
0262
0263 struct operand_type_match {
0264 bool match(const MachineRegisterInfo &MRI, Register Reg) { return true; }
0265 bool match(const MachineRegisterInfo &MRI, MachineOperand *MO) {
0266 return MO->isReg();
0267 }
0268 };
0269
0270 inline operand_type_match m_Reg() { return operand_type_match(); }
0271
0272
0273 template <typename... Preds> struct And {
0274 template <typename MatchSrc>
0275 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
0276 return true;
0277 }
0278 };
0279
0280 template <typename Pred, typename... Preds>
0281 struct And<Pred, Preds...> : And<Preds...> {
0282 Pred P;
0283 And(Pred &&p, Preds &&... preds)
0284 : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {
0285 }
0286 template <typename MatchSrc>
0287 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
0288 return P.match(MRI, src) && And<Preds...>::match(MRI, src);
0289 }
0290 };
0291
0292 template <typename... Preds> struct Or {
0293 template <typename MatchSrc>
0294 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
0295 return false;
0296 }
0297 };
0298
0299 template <typename Pred, typename... Preds>
0300 struct Or<Pred, Preds...> : Or<Preds...> {
0301 Pred P;
0302 Or(Pred &&p, Preds &&... preds)
0303 : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {}
0304 template <typename MatchSrc>
0305 bool match(const MachineRegisterInfo &MRI, MatchSrc &&src) {
0306 return P.match(MRI, src) || Or<Preds...>::match(MRI, src);
0307 }
0308 };
0309
0310 template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) {
0311 return And<Preds...>(std::forward<Preds>(preds)...);
0312 }
0313
0314 template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) {
0315 return Or<Preds...>(std::forward<Preds>(preds)...);
0316 }
0317
0318 template <typename BindTy> struct bind_helper {
0319 static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
0320 VR = V;
0321 return true;
0322 }
0323 };
0324
0325 template <> struct bind_helper<MachineInstr *> {
0326 static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
0327 Register Reg) {
0328 MI = MRI.getVRegDef(Reg);
0329 if (MI)
0330 return true;
0331 return false;
0332 }
0333 static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI,
0334 MachineInstr *Inst) {
0335 MI = Inst;
0336 return MI;
0337 }
0338 };
0339
0340 template <> struct bind_helper<LLT> {
0341 static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, Register Reg) {
0342 Ty = MRI.getType(Reg);
0343 if (Ty.isValid())
0344 return true;
0345 return false;
0346 }
0347 };
0348
0349 template <> struct bind_helper<const ConstantFP *> {
0350 static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
0351 Register Reg) {
0352 F = getConstantFPVRegVal(Reg, MRI);
0353 if (F)
0354 return true;
0355 return false;
0356 }
0357 };
0358
0359 template <typename Class> struct bind_ty {
0360 Class &VR;
0361
0362 bind_ty(Class &V) : VR(V) {}
0363
0364 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
0365 return bind_helper<Class>::bind(MRI, VR, V);
0366 }
0367 };
0368
0369 inline bind_ty<Register> m_Reg(Register &R) { return R; }
0370 inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
0371 inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
0372 inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
0373 inline operand_type_match m_Pred() { return operand_type_match(); }
0374
0375 template <typename BindTy> struct deferred_helper {
0376 static bool match(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) {
0377 return VR == V;
0378 }
0379 };
0380
0381 template <> struct deferred_helper<LLT> {
0382 static bool match(const MachineRegisterInfo &MRI, LLT VT, Register R) {
0383 return VT == MRI.getType(R);
0384 }
0385 };
0386
0387 template <typename Class> struct deferred_ty {
0388 Class &VR;
0389
0390 deferred_ty(Class &V) : VR(V) {}
0391
0392 template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) {
0393 return deferred_helper<Class>::match(MRI, VR, V);
0394 }
0395 };
0396
0397
0398
0399
0400
0401
0402 inline deferred_ty<Register> m_DeferredReg(Register &R) { return R; }
0403 inline deferred_ty<LLT> m_DeferredType(LLT &Ty) { return Ty; }
0404
0405 struct ImplicitDefMatch {
0406 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0407 MachineInstr *TmpMI;
0408 if (mi_match(Reg, MRI, m_MInstr(TmpMI)))
0409 return TmpMI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
0410 return false;
0411 }
0412 };
0413
0414 inline ImplicitDefMatch m_GImplicitDef() { return ImplicitDefMatch(); }
0415
0416
0417 inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
0418
0419
0420 template <typename LHS_P, typename RHS_P, unsigned Opcode,
0421 bool Commutable = false>
0422 struct BinaryOp_match {
0423 LHS_P L;
0424 RHS_P R;
0425
0426 BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {}
0427 template <typename OpTy>
0428 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
0429 MachineInstr *TmpMI;
0430 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
0431 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) {
0432 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
0433 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
0434
0435
0436
0437
0438
0439 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
0440 R.match(MRI, TmpMI->getOperand(1).getReg())));
0441 }
0442 }
0443 return false;
0444 }
0445 };
0446
0447
0448 template <typename LHS_P, typename RHS_P, bool Commutable = false>
0449 struct BinaryOpc_match {
0450 unsigned Opc;
0451 LHS_P L;
0452 RHS_P R;
0453
0454 BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
0455 : Opc(Opcode), L(LHS), R(RHS) {}
0456 template <typename OpTy>
0457 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
0458 MachineInstr *TmpMI;
0459 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
0460 if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
0461 TmpMI->getNumOperands() == 3) {
0462 return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
0463 R.match(MRI, TmpMI->getOperand(2).getReg())) ||
0464
0465
0466
0467
0468
0469 (Commutable && (L.match(MRI, TmpMI->getOperand(2).getReg()) &&
0470 R.match(MRI, TmpMI->getOperand(1).getReg())));
0471 }
0472 }
0473 return false;
0474 }
0475 };
0476
0477 template <typename LHS, typename RHS>
0478 inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
0479 const RHS &R) {
0480 return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
0481 }
0482
0483 template <typename LHS, typename RHS>
0484 inline BinaryOpc_match<LHS, RHS, true>
0485 m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
0486 return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
0487 }
0488
0489 template <typename LHS, typename RHS>
0490 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>
0491 m_GAdd(const LHS &L, const RHS &R) {
0492 return BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>(L, R);
0493 }
0494
0495 template <typename LHS, typename RHS>
0496 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_BUILD_VECTOR, false>
0497 m_GBuildVector(const LHS &L, const RHS &R) {
0498 return BinaryOp_match<LHS, RHS, TargetOpcode::G_BUILD_VECTOR, false>(L, R);
0499 }
0500
0501 template <typename LHS, typename RHS>
0502 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_BUILD_VECTOR_TRUNC, false>
0503 m_GBuildVectorTrunc(const LHS &L, const RHS &R) {
0504 return BinaryOp_match<LHS, RHS, TargetOpcode::G_BUILD_VECTOR_TRUNC, false>(L,
0505 R);
0506 }
0507
0508 template <typename LHS, typename RHS>
0509 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_PTR_ADD, false>
0510 m_GPtrAdd(const LHS &L, const RHS &R) {
0511 return BinaryOp_match<LHS, RHS, TargetOpcode::G_PTR_ADD, false>(L, R);
0512 }
0513
0514 template <typename LHS, typename RHS>
0515 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB> m_GSub(const LHS &L,
0516 const RHS &R) {
0517 return BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB>(L, R);
0518 }
0519
0520 template <typename LHS, typename RHS>
0521 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>
0522 m_GMul(const LHS &L, const RHS &R) {
0523 return BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>(L, R);
0524 }
0525
0526 template <typename LHS, typename RHS>
0527 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>
0528 m_GFAdd(const LHS &L, const RHS &R) {
0529 return BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>(L, R);
0530 }
0531
0532 template <typename LHS, typename RHS>
0533 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>
0534 m_GFMul(const LHS &L, const RHS &R) {
0535 return BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>(L, R);
0536 }
0537
0538 template <typename LHS, typename RHS>
0539 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>
0540 m_GFSub(const LHS &L, const RHS &R) {
0541 return BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>(L, R);
0542 }
0543
0544 template <typename LHS, typename RHS>
0545 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>
0546 m_GAnd(const LHS &L, const RHS &R) {
0547 return BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>(L, R);
0548 }
0549
0550 template <typename LHS, typename RHS>
0551 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_XOR, true>
0552 m_GXor(const LHS &L, const RHS &R) {
0553 return BinaryOp_match<LHS, RHS, TargetOpcode::G_XOR, true>(L, R);
0554 }
0555
0556 template <typename LHS, typename RHS>
0557 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true> m_GOr(const LHS &L,
0558 const RHS &R) {
0559 return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true>(L, R);
0560 }
0561
0562 template <typename LHS, typename RHS>
0563 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>
0564 m_GShl(const LHS &L, const RHS &R) {
0565 return BinaryOp_match<LHS, RHS, TargetOpcode::G_SHL, false>(L, R);
0566 }
0567
0568 template <typename LHS, typename RHS>
0569 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_LSHR, false>
0570 m_GLShr(const LHS &L, const RHS &R) {
0571 return BinaryOp_match<LHS, RHS, TargetOpcode::G_LSHR, false>(L, R);
0572 }
0573
0574 template <typename LHS, typename RHS>
0575 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ASHR, false>
0576 m_GAShr(const LHS &L, const RHS &R) {
0577 return BinaryOp_match<LHS, RHS, TargetOpcode::G_ASHR, false>(L, R);
0578 }
0579
0580 template <typename LHS, typename RHS>
0581 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SMAX, true>
0582 m_GSMax(const LHS &L, const RHS &R) {
0583 return BinaryOp_match<LHS, RHS, TargetOpcode::G_SMAX, true>(L, R);
0584 }
0585
0586 template <typename LHS, typename RHS>
0587 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SMIN, true>
0588 m_GSMin(const LHS &L, const RHS &R) {
0589 return BinaryOp_match<LHS, RHS, TargetOpcode::G_SMIN, true>(L, R);
0590 }
0591
0592 template <typename LHS, typename RHS>
0593 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_UMAX, true>
0594 m_GUMax(const LHS &L, const RHS &R) {
0595 return BinaryOp_match<LHS, RHS, TargetOpcode::G_UMAX, true>(L, R);
0596 }
0597
0598 template <typename LHS, typename RHS>
0599 inline BinaryOp_match<LHS, RHS, TargetOpcode::G_UMIN, true>
0600 m_GUMin(const LHS &L, const RHS &R) {
0601 return BinaryOp_match<LHS, RHS, TargetOpcode::G_UMIN, true>(L, R);
0602 }
0603
0604
0605 template <typename SrcTy, unsigned Opcode> struct UnaryOp_match {
0606 SrcTy L;
0607
0608 UnaryOp_match(const SrcTy &LHS) : L(LHS) {}
0609 template <typename OpTy>
0610 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
0611 MachineInstr *TmpMI;
0612 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
0613 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) {
0614 return L.match(MRI, TmpMI->getOperand(1).getReg());
0615 }
0616 }
0617 return false;
0618 }
0619 };
0620
0621 template <typename SrcTy>
0622 inline UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>
0623 m_GAnyExt(const SrcTy &Src) {
0624 return UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>(Src);
0625 }
0626
0627 template <typename SrcTy>
0628 inline UnaryOp_match<SrcTy, TargetOpcode::G_SEXT> m_GSExt(const SrcTy &Src) {
0629 return UnaryOp_match<SrcTy, TargetOpcode::G_SEXT>(Src);
0630 }
0631
0632 template <typename SrcTy>
0633 inline UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT> m_GZExt(const SrcTy &Src) {
0634 return UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT>(Src);
0635 }
0636
0637 template <typename SrcTy>
0638 inline UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT> m_GFPExt(const SrcTy &Src) {
0639 return UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT>(Src);
0640 }
0641
0642 template <typename SrcTy>
0643 inline UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC> m_GTrunc(const SrcTy &Src) {
0644 return UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC>(Src);
0645 }
0646
0647 template <typename SrcTy>
0648 inline UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>
0649 m_GBitcast(const SrcTy &Src) {
0650 return UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>(Src);
0651 }
0652
0653 template <typename SrcTy>
0654 inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>
0655 m_GPtrToInt(const SrcTy &Src) {
0656 return UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>(Src);
0657 }
0658
0659 template <typename SrcTy>
0660 inline UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>
0661 m_GIntToPtr(const SrcTy &Src) {
0662 return UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>(Src);
0663 }
0664
0665 template <typename SrcTy>
0666 inline UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>
0667 m_GFPTrunc(const SrcTy &Src) {
0668 return UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>(Src);
0669 }
0670
0671 template <typename SrcTy>
0672 inline UnaryOp_match<SrcTy, TargetOpcode::G_FABS> m_GFabs(const SrcTy &Src) {
0673 return UnaryOp_match<SrcTy, TargetOpcode::G_FABS>(Src);
0674 }
0675
0676 template <typename SrcTy>
0677 inline UnaryOp_match<SrcTy, TargetOpcode::G_FNEG> m_GFNeg(const SrcTy &Src) {
0678 return UnaryOp_match<SrcTy, TargetOpcode::G_FNEG>(Src);
0679 }
0680
0681 template <typename SrcTy>
0682 inline UnaryOp_match<SrcTy, TargetOpcode::COPY> m_Copy(SrcTy &&Src) {
0683 return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
0684 }
0685
0686 template <typename SrcTy>
0687 inline UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT> m_GFSqrt(const SrcTy &Src) {
0688 return UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT>(Src);
0689 }
0690
0691
0692
0693 template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
0694 bool Commutable = false>
0695 struct CompareOp_match {
0696 Pred_P P;
0697 LHS_P L;
0698 RHS_P R;
0699
0700 CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
0701 : P(Pred), L(LHS), R(RHS) {}
0702
0703 template <typename OpTy>
0704 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
0705 MachineInstr *TmpMI;
0706 if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
0707 return false;
0708
0709 auto TmpPred =
0710 static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
0711 if (!P.match(MRI, TmpPred))
0712 return false;
0713 Register LHS = TmpMI->getOperand(2).getReg();
0714 Register RHS = TmpMI->getOperand(3).getReg();
0715 if (L.match(MRI, LHS) && R.match(MRI, RHS))
0716 return true;
0717
0718
0719
0720
0721 if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
0722 P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
0723 return true;
0724 return false;
0725 }
0726 };
0727
0728 template <typename Pred, typename LHS, typename RHS>
0729 inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
0730 m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
0731 return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>(P, L, R);
0732 }
0733
0734 template <typename Pred, typename LHS, typename RHS>
0735 inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>
0736 m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
0737 return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>(P, L, R);
0738 }
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749 template <typename Pred, typename LHS, typename RHS>
0750 inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP, true>
0751 m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
0752 return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP, true>(P, L, R);
0753 }
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764 template <typename Pred, typename LHS, typename RHS>
0765 inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>
0766 m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
0767 return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>(P, L, R);
0768 }
0769
0770
0771 struct CheckType {
0772 LLT Ty;
0773 CheckType(const LLT Ty) : Ty(Ty) {}
0774
0775 bool match(const MachineRegisterInfo &MRI, Register Reg) {
0776 return MRI.getType(Reg) == Ty;
0777 }
0778 };
0779
0780 inline CheckType m_SpecificType(LLT Ty) { return Ty; }
0781
0782 template <typename Src0Ty, typename Src1Ty, typename Src2Ty, unsigned Opcode>
0783 struct TernaryOp_match {
0784 Src0Ty Src0;
0785 Src1Ty Src1;
0786 Src2Ty Src2;
0787
0788 TernaryOp_match(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2)
0789 : Src0(Src0), Src1(Src1), Src2(Src2) {}
0790 template <typename OpTy>
0791 bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
0792 MachineInstr *TmpMI;
0793 if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
0794 if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 4) {
0795 return (Src0.match(MRI, TmpMI->getOperand(1).getReg()) &&
0796 Src1.match(MRI, TmpMI->getOperand(2).getReg()) &&
0797 Src2.match(MRI, TmpMI->getOperand(3).getReg()));
0798 }
0799 }
0800 return false;
0801 }
0802 };
0803 template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
0804 inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
0805 TargetOpcode::G_INSERT_VECTOR_ELT>
0806 m_GInsertVecElt(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
0807 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty,
0808 TargetOpcode::G_INSERT_VECTOR_ELT>(Src0, Src1, Src2);
0809 }
0810
0811 template <typename Src0Ty, typename Src1Ty, typename Src2Ty>
0812 inline TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>
0813 m_GISelect(const Src0Ty &Src0, const Src1Ty &Src1, const Src2Ty &Src2) {
0814 return TernaryOp_match<Src0Ty, Src1Ty, Src2Ty, TargetOpcode::G_SELECT>(
0815 Src0, Src1, Src2);
0816 }
0817
0818
0819
0820 template <typename SrcTy>
0821 inline BinaryOp_match<SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB>
0822 m_Neg(const SrcTy &&Src) {
0823 return m_GSub(m_ZeroInt(), Src);
0824 }
0825
0826
0827
0828 template <typename SrcTy>
0829 inline BinaryOp_match<SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true>
0830 m_Not(const SrcTy &&Src) {
0831 return m_GXor(Src, m_AllOnesInt());
0832 }
0833
0834 }
0835 }
0836
0837 #endif