Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:23

0001 //===- llvm/CodeGen/GlobalISel/GenericMachineInstrs.h -----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// Declares convenience wrapper classes for interpreting MachineInstr instances
0010 /// as specific generic operations.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
0015 #define LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
0016 
0017 #include "llvm/ADT/APInt.h"
0018 #include "llvm/CodeGen/MachineInstr.h"
0019 #include "llvm/CodeGen/MachineMemOperand.h"
0020 #include "llvm/CodeGen/TargetOpcodes.h"
0021 #include "llvm/IR/Constants.h"
0022 #include "llvm/IR/Instructions.h"
0023 #include "llvm/Support/Casting.h"
0024 
0025 namespace llvm {
0026 
0027 /// A base class for all GenericMachineInstrs.
0028 class GenericMachineInstr : public MachineInstr {
0029   constexpr static unsigned PoisonFlags = NoUWrap | NoSWrap | NoUSWrap |
0030                                           IsExact | Disjoint | NonNeg |
0031                                           FmNoNans | FmNoInfs | SameSign;
0032 
0033 public:
0034   GenericMachineInstr() = delete;
0035 
0036   /// Access the Idx'th operand as a register and return it.
0037   /// This assumes that the Idx'th operand is a Register type.
0038   Register getReg(unsigned Idx) const { return getOperand(Idx).getReg(); }
0039 
0040   static bool classof(const MachineInstr *MI) {
0041     return isPreISelGenericOpcode(MI->getOpcode());
0042   }
0043 
0044   bool hasPoisonGeneratingFlags() const { return getFlags() & PoisonFlags; }
0045 
0046   void dropPoisonGeneratingFlags() {
0047     clearFlags(PoisonFlags);
0048     assert(!hasPoisonGeneratingFlags());
0049   }
0050 };
0051 
0052 /// Provides common memory operand functionality.
0053 class GMemOperation : public GenericMachineInstr {
0054 public:
0055   /// Get the MachineMemOperand on this instruction.
0056   MachineMemOperand &getMMO() const { return **memoperands_begin(); }
0057 
0058   /// Returns true if the attached MachineMemOperand  has the atomic flag set.
0059   bool isAtomic() const { return getMMO().isAtomic(); }
0060   /// Returns true if the attached MachineMemOpeand as the volatile flag set.
0061   bool isVolatile() const { return getMMO().isVolatile(); }
0062   /// Returns true if the memory operation is neither atomic or volatile.
0063   bool isSimple() const { return !isAtomic() && !isVolatile(); }
0064   /// Returns true if this memory operation doesn't have any ordering
0065   /// constraints other than normal aliasing. Volatile and (ordered) atomic
0066   /// memory operations can't be reordered.
0067   bool isUnordered() const { return getMMO().isUnordered(); }
0068 
0069   /// Returns the size in bytes of the memory access.
0070   LocationSize getMemSize() const { return getMMO().getSize(); }
0071   /// Returns the size in bits of the memory access.
0072   LocationSize getMemSizeInBits() const { return getMMO().getSizeInBits(); }
0073 
0074   static bool classof(const MachineInstr *MI) {
0075     return GenericMachineInstr::classof(MI) && MI->hasOneMemOperand();
0076   }
0077 };
0078 
0079 /// Represents any type of generic load or store.
0080 /// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD.
0081 class GLoadStore : public GMemOperation {
0082 public:
0083   /// Get the source register of the pointer value.
0084   Register getPointerReg() const { return getOperand(1).getReg(); }
0085 
0086   static bool classof(const MachineInstr *MI) {
0087     switch (MI->getOpcode()) {
0088     case TargetOpcode::G_LOAD:
0089     case TargetOpcode::G_STORE:
0090     case TargetOpcode::G_ZEXTLOAD:
0091     case TargetOpcode::G_SEXTLOAD:
0092       return true;
0093     default:
0094       return false;
0095     }
0096   }
0097 };
0098 
0099 /// Represents indexed loads. These are different enough from regular loads
0100 /// that they get their own class. Including them in GAnyLoad would probably
0101 /// make a footgun for someone.
0102 class GIndexedLoad : public GMemOperation {
0103 public:
0104   /// Get the definition register of the loaded value.
0105   Register getDstReg() const { return getOperand(0).getReg(); }
0106   /// Get the def register of the writeback value.
0107   Register getWritebackReg() const { return getOperand(1).getReg(); }
0108   /// Get the base register of the pointer value.
0109   Register getBaseReg() const { return getOperand(2).getReg(); }
0110   /// Get the offset register of the pointer value.
0111   Register getOffsetReg() const { return getOperand(3).getReg(); }
0112 
0113   bool isPre() const { return getOperand(4).getImm() == 1; }
0114   bool isPost() const { return !isPre(); }
0115 
0116   static bool classof(const MachineInstr *MI) {
0117     return MI->getOpcode() == TargetOpcode::G_INDEXED_LOAD;
0118   }
0119 };
0120 
0121 /// Represents a G_INDEX_ZEXTLOAD/G_INDEXED_SEXTLOAD.
0122 class GIndexedExtLoad : public GIndexedLoad {
0123 public:
0124   static bool classof(const MachineInstr *MI) {
0125     return MI->getOpcode() == TargetOpcode::G_INDEXED_SEXTLOAD ||
0126            MI->getOpcode() == TargetOpcode::G_INDEXED_ZEXTLOAD;
0127   }
0128 };
0129 
0130 /// Represents either G_INDEXED_LOAD, G_INDEXED_ZEXTLOAD or G_INDEXED_SEXTLOAD.
0131 class GIndexedAnyExtLoad : public GIndexedLoad {
0132 public:
0133   static bool classof(const MachineInstr *MI) {
0134     switch (MI->getOpcode()) {
0135     case TargetOpcode::G_INDEXED_LOAD:
0136     case TargetOpcode::G_INDEXED_ZEXTLOAD:
0137     case TargetOpcode::G_INDEXED_SEXTLOAD:
0138       return true;
0139     default:
0140       return false;
0141     }
0142   }
0143 };
0144 
0145 /// Represents a G_ZEXTLOAD.
0146 class GIndexedZExtLoad : GIndexedExtLoad {
0147 public:
0148   static bool classof(const MachineInstr *MI) {
0149     return MI->getOpcode() == TargetOpcode::G_INDEXED_ZEXTLOAD;
0150   }
0151 };
0152 
0153 /// Represents a G_SEXTLOAD.
0154 class GIndexedSExtLoad : GIndexedExtLoad {
0155 public:
0156   static bool classof(const MachineInstr *MI) {
0157     return MI->getOpcode() == TargetOpcode::G_INDEXED_SEXTLOAD;
0158   }
0159 };
0160 
0161 /// Represents indexed stores.
0162 class GIndexedStore : public GMemOperation {
0163 public:
0164   /// Get the def register of the writeback value.
0165   Register getWritebackReg() const { return getOperand(0).getReg(); }
0166   /// Get the stored value register.
0167   Register getValueReg() const { return getOperand(1).getReg(); }
0168   /// Get the base register of the pointer value.
0169   Register getBaseReg() const { return getOperand(2).getReg(); }
0170   /// Get the offset register of the pointer value.
0171   Register getOffsetReg() const { return getOperand(3).getReg(); }
0172 
0173   bool isPre() const { return getOperand(4).getImm() == 1; }
0174   bool isPost() const { return !isPre(); }
0175 
0176   static bool classof(const MachineInstr *MI) {
0177     return MI->getOpcode() == TargetOpcode::G_INDEXED_STORE;
0178   }
0179 };
0180 
0181 /// Represents any generic load, including sign/zero extending variants.
0182 class GAnyLoad : public GLoadStore {
0183 public:
0184   /// Get the definition register of the loaded value.
0185   Register getDstReg() const { return getOperand(0).getReg(); }
0186 
0187   /// Returns the Ranges that describes the dereference.
0188   const MDNode *getRanges() const {
0189     return getMMO().getRanges();
0190   }
0191 
0192   static bool classof(const MachineInstr *MI) {
0193     switch (MI->getOpcode()) {
0194     case TargetOpcode::G_LOAD:
0195     case TargetOpcode::G_ZEXTLOAD:
0196     case TargetOpcode::G_SEXTLOAD:
0197       return true;
0198     default:
0199       return false;
0200     }
0201   }
0202 };
0203 
0204 /// Represents a G_LOAD.
0205 class GLoad : public GAnyLoad {
0206 public:
0207   static bool classof(const MachineInstr *MI) {
0208     return MI->getOpcode() == TargetOpcode::G_LOAD;
0209   }
0210 };
0211 
0212 /// Represents either a G_SEXTLOAD or G_ZEXTLOAD.
0213 class GExtLoad : public GAnyLoad {
0214 public:
0215   static bool classof(const MachineInstr *MI) {
0216     return MI->getOpcode() == TargetOpcode::G_SEXTLOAD ||
0217            MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
0218   }
0219 };
0220 
0221 /// Represents a G_SEXTLOAD.
0222 class GSExtLoad : public GExtLoad {
0223 public:
0224   static bool classof(const MachineInstr *MI) {
0225     return MI->getOpcode() == TargetOpcode::G_SEXTLOAD;
0226   }
0227 };
0228 
0229 /// Represents a G_ZEXTLOAD.
0230 class GZExtLoad : public GExtLoad {
0231 public:
0232   static bool classof(const MachineInstr *MI) {
0233     return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD;
0234   }
0235 };
0236 
0237 /// Represents a G_STORE.
0238 class GStore : public GLoadStore {
0239 public:
0240   /// Get the stored value register.
0241   Register getValueReg() const { return getOperand(0).getReg(); }
0242 
0243   static bool classof(const MachineInstr *MI) {
0244     return MI->getOpcode() == TargetOpcode::G_STORE;
0245   }
0246 };
0247 
0248 /// Represents a G_UNMERGE_VALUES.
0249 class GUnmerge : public GenericMachineInstr {
0250 public:
0251   /// Returns the number of def registers.
0252   unsigned getNumDefs() const { return getNumOperands() - 1; }
0253   /// Get the unmerge source register.
0254   Register getSourceReg() const { return getOperand(getNumDefs()).getReg(); }
0255 
0256   static bool classof(const MachineInstr *MI) {
0257     return MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES;
0258   }
0259 };
0260 
0261 /// Represents G_BUILD_VECTOR, G_CONCAT_VECTORS or G_MERGE_VALUES.
0262 /// All these have the common property of generating a single value from
0263 /// multiple sources.
0264 class GMergeLikeInstr : public GenericMachineInstr {
0265 public:
0266   /// Returns the number of source registers.
0267   unsigned getNumSources() const { return getNumOperands() - 1; }
0268   /// Returns the I'th source register.
0269   Register getSourceReg(unsigned I) const { return getReg(I + 1); }
0270 
0271   static bool classof(const MachineInstr *MI) {
0272     switch (MI->getOpcode()) {
0273     case TargetOpcode::G_MERGE_VALUES:
0274     case TargetOpcode::G_CONCAT_VECTORS:
0275     case TargetOpcode::G_BUILD_VECTOR:
0276       return true;
0277     default:
0278       return false;
0279     }
0280   }
0281 };
0282 
0283 /// Represents a G_MERGE_VALUES.
0284 class GMerge : public GMergeLikeInstr {
0285 public:
0286   static bool classof(const MachineInstr *MI) {
0287     return MI->getOpcode() == TargetOpcode::G_MERGE_VALUES;
0288   }
0289 };
0290 
0291 /// Represents a G_CONCAT_VECTORS.
0292 class GConcatVectors : public GMergeLikeInstr {
0293 public:
0294   static bool classof(const MachineInstr *MI) {
0295     return MI->getOpcode() == TargetOpcode::G_CONCAT_VECTORS;
0296   }
0297 };
0298 
0299 /// Represents a G_BUILD_VECTOR.
0300 class GBuildVector : public GMergeLikeInstr {
0301 public:
0302   static bool classof(const MachineInstr *MI) {
0303     return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR;
0304   }
0305 };
0306 
0307 /// Represents a G_BUILD_VECTOR_TRUNC.
0308 class GBuildVectorTrunc : public GMergeLikeInstr {
0309 public:
0310   static bool classof(const MachineInstr *MI) {
0311     return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC;
0312   }
0313 };
0314 
0315 /// Represents a G_SHUFFLE_VECTOR.
0316 class GShuffleVector : public GenericMachineInstr {
0317 public:
0318   Register getSrc1Reg() const { return getOperand(1).getReg(); }
0319   Register getSrc2Reg() const { return getOperand(2).getReg(); }
0320   ArrayRef<int> getMask() const { return getOperand(3).getShuffleMask(); }
0321 
0322   static bool classof(const MachineInstr *MI) {
0323     return MI->getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR;
0324   }
0325 };
0326 
0327 /// Represents a G_PTR_ADD.
0328 class GPtrAdd : public GenericMachineInstr {
0329 public:
0330   Register getBaseReg() const { return getReg(1); }
0331   Register getOffsetReg() const { return getReg(2); }
0332 
0333   static bool classof(const MachineInstr *MI) {
0334     return MI->getOpcode() == TargetOpcode::G_PTR_ADD;
0335   }
0336 };
0337 
0338 /// Represents a G_IMPLICIT_DEF.
0339 class GImplicitDef : public GenericMachineInstr {
0340 public:
0341   static bool classof(const MachineInstr *MI) {
0342     return MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF;
0343   }
0344 };
0345 
0346 /// Represents a G_SELECT.
0347 class GSelect : public GenericMachineInstr {
0348 public:
0349   Register getCondReg() const { return getReg(1); }
0350   Register getTrueReg() const { return getReg(2); }
0351   Register getFalseReg() const { return getReg(3); }
0352 
0353   static bool classof(const MachineInstr *MI) {
0354     return MI->getOpcode() == TargetOpcode::G_SELECT;
0355   }
0356 };
0357 
0358 /// Represent a G_ICMP or G_FCMP.
0359 class GAnyCmp : public GenericMachineInstr {
0360 public:
0361   CmpInst::Predicate getCond() const {
0362     return static_cast<CmpInst::Predicate>(getOperand(1).getPredicate());
0363   }
0364   Register getLHSReg() const { return getReg(2); }
0365   Register getRHSReg() const { return getReg(3); }
0366 
0367   static bool classof(const MachineInstr *MI) {
0368     return MI->getOpcode() == TargetOpcode::G_ICMP ||
0369            MI->getOpcode() == TargetOpcode::G_FCMP;
0370   }
0371 };
0372 
0373 /// Represent a G_ICMP.
0374 class GICmp : public GAnyCmp {
0375 public:
0376   static bool classof(const MachineInstr *MI) {
0377     return MI->getOpcode() == TargetOpcode::G_ICMP;
0378   }
0379 };
0380 
0381 /// Represent a G_FCMP.
0382 class GFCmp : public GAnyCmp {
0383 public:
0384   static bool classof(const MachineInstr *MI) {
0385     return MI->getOpcode() == TargetOpcode::G_FCMP;
0386   }
0387 };
0388 
0389 /// Represents overflowing binary operations.
0390 /// Only carry-out:
0391 /// G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO
0392 /// Carry-in and carry-out:
0393 /// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
0394 class GBinOpCarryOut : public GenericMachineInstr {
0395 public:
0396   Register getDstReg() const { return getReg(0); }
0397   Register getCarryOutReg() const { return getReg(1); }
0398   MachineOperand &getLHS() { return getOperand(2); }
0399   MachineOperand &getRHS() { return getOperand(3); }
0400   Register getLHSReg() const { return getOperand(2).getReg(); }
0401   Register getRHSReg() const { return getOperand(3).getReg(); }
0402 
0403   static bool classof(const MachineInstr *MI) {
0404     switch (MI->getOpcode()) {
0405     case TargetOpcode::G_UADDO:
0406     case TargetOpcode::G_SADDO:
0407     case TargetOpcode::G_USUBO:
0408     case TargetOpcode::G_SSUBO:
0409     case TargetOpcode::G_UADDE:
0410     case TargetOpcode::G_SADDE:
0411     case TargetOpcode::G_USUBE:
0412     case TargetOpcode::G_SSUBE:
0413     case TargetOpcode::G_UMULO:
0414     case TargetOpcode::G_SMULO:
0415       return true;
0416     default:
0417       return false;
0418     }
0419   }
0420 };
0421 
0422 /// Represents overflowing add/sub operations.
0423 /// Only carry-out:
0424 /// G_UADDO, G_SADDO, G_USUBO, G_SSUBO
0425 /// Carry-in and carry-out:
0426 /// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
0427 class GAddSubCarryOut : public GBinOpCarryOut {
0428 public:
0429   bool isAdd() const {
0430     switch (getOpcode()) {
0431     case TargetOpcode::G_UADDO:
0432     case TargetOpcode::G_SADDO:
0433     case TargetOpcode::G_UADDE:
0434     case TargetOpcode::G_SADDE:
0435       return true;
0436     default:
0437       return false;
0438     }
0439   }
0440   bool isSub() const { return !isAdd(); }
0441 
0442   bool isSigned() const {
0443     switch (getOpcode()) {
0444     case TargetOpcode::G_SADDO:
0445     case TargetOpcode::G_SSUBO:
0446     case TargetOpcode::G_SADDE:
0447     case TargetOpcode::G_SSUBE:
0448       return true;
0449     default:
0450       return false;
0451     }
0452   }
0453   bool isUnsigned() const { return !isSigned(); }
0454 
0455   static bool classof(const MachineInstr *MI) {
0456     switch (MI->getOpcode()) {
0457     case TargetOpcode::G_UADDO:
0458     case TargetOpcode::G_SADDO:
0459     case TargetOpcode::G_USUBO:
0460     case TargetOpcode::G_SSUBO:
0461     case TargetOpcode::G_UADDE:
0462     case TargetOpcode::G_SADDE:
0463     case TargetOpcode::G_USUBE:
0464     case TargetOpcode::G_SSUBE:
0465       return true;
0466     default:
0467       return false;
0468     }
0469   }
0470 };
0471 
0472 /// Represents overflowing add operations.
0473 /// G_UADDO, G_SADDO
0474 class GAddCarryOut : public GBinOpCarryOut {
0475 public:
0476   bool isSigned() const { return getOpcode() == TargetOpcode::G_SADDO; }
0477 
0478   static bool classof(const MachineInstr *MI) {
0479     switch (MI->getOpcode()) {
0480     case TargetOpcode::G_UADDO:
0481     case TargetOpcode::G_SADDO:
0482       return true;
0483     default:
0484       return false;
0485     }
0486   }
0487 };
0488 
0489 /// Represents overflowing sub operations.
0490 /// G_USUBO, G_SSUBO
0491 class GSubCarryOut : public GBinOpCarryOut {
0492 public:
0493   bool isSigned() const { return getOpcode() == TargetOpcode::G_SSUBO; }
0494 
0495   static bool classof(const MachineInstr *MI) {
0496     switch (MI->getOpcode()) {
0497     case TargetOpcode::G_USUBO:
0498     case TargetOpcode::G_SSUBO:
0499       return true;
0500     default:
0501       return false;
0502     }
0503   }
0504 };
0505 
0506 /// Represents overflowing add/sub operations that also consume a carry-in.
0507 /// G_UADDE, G_SADDE, G_USUBE, G_SSUBE
0508 class GAddSubCarryInOut : public GAddSubCarryOut {
0509 public:
0510   Register getCarryInReg() const { return getReg(4); }
0511 
0512   static bool classof(const MachineInstr *MI) {
0513     switch (MI->getOpcode()) {
0514     case TargetOpcode::G_UADDE:
0515     case TargetOpcode::G_SADDE:
0516     case TargetOpcode::G_USUBE:
0517     case TargetOpcode::G_SSUBE:
0518       return true;
0519     default:
0520       return false;
0521     }
0522   }
0523 };
0524 
0525 /// Represents a call to an intrinsic.
0526 class GIntrinsic final : public GenericMachineInstr {
0527 public:
0528   Intrinsic::ID getIntrinsicID() const {
0529     return getOperand(getNumExplicitDefs()).getIntrinsicID();
0530   }
0531 
0532   bool is(Intrinsic::ID ID) const { return getIntrinsicID() == ID; }
0533 
0534   bool hasSideEffects() const {
0535     switch (getOpcode()) {
0536     case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
0537     case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
0538       return true;
0539     default:
0540       return false;
0541     }
0542   }
0543 
0544   bool isConvergent() const {
0545     switch (getOpcode()) {
0546     case TargetOpcode::G_INTRINSIC_CONVERGENT:
0547     case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
0548       return true;
0549     default:
0550       return false;
0551     }
0552   }
0553 
0554   static bool classof(const MachineInstr *MI) {
0555     switch (MI->getOpcode()) {
0556     case TargetOpcode::G_INTRINSIC:
0557     case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
0558     case TargetOpcode::G_INTRINSIC_CONVERGENT:
0559     case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
0560       return true;
0561     default:
0562       return false;
0563     }
0564   }
0565 };
0566 
0567 // Represents a (non-sequential) vector reduction operation.
0568 class GVecReduce : public GenericMachineInstr {
0569 public:
0570   static bool classof(const MachineInstr *MI) {
0571     switch (MI->getOpcode()) {
0572     case TargetOpcode::G_VECREDUCE_FADD:
0573     case TargetOpcode::G_VECREDUCE_FMUL:
0574     case TargetOpcode::G_VECREDUCE_FMAX:
0575     case TargetOpcode::G_VECREDUCE_FMIN:
0576     case TargetOpcode::G_VECREDUCE_FMAXIMUM:
0577     case TargetOpcode::G_VECREDUCE_FMINIMUM:
0578     case TargetOpcode::G_VECREDUCE_ADD:
0579     case TargetOpcode::G_VECREDUCE_MUL:
0580     case TargetOpcode::G_VECREDUCE_AND:
0581     case TargetOpcode::G_VECREDUCE_OR:
0582     case TargetOpcode::G_VECREDUCE_XOR:
0583     case TargetOpcode::G_VECREDUCE_SMAX:
0584     case TargetOpcode::G_VECREDUCE_SMIN:
0585     case TargetOpcode::G_VECREDUCE_UMAX:
0586     case TargetOpcode::G_VECREDUCE_UMIN:
0587       return true;
0588     default:
0589       return false;
0590     }
0591   }
0592 
0593   /// Get the opcode for the equivalent scalar operation for this reduction.
0594   /// E.g. for G_VECREDUCE_FADD, this returns G_FADD.
0595   unsigned getScalarOpcForReduction() {
0596     unsigned ScalarOpc;
0597     switch (getOpcode()) {
0598     case TargetOpcode::G_VECREDUCE_FADD:
0599       ScalarOpc = TargetOpcode::G_FADD;
0600       break;
0601     case TargetOpcode::G_VECREDUCE_FMUL:
0602       ScalarOpc = TargetOpcode::G_FMUL;
0603       break;
0604     case TargetOpcode::G_VECREDUCE_FMAX:
0605       ScalarOpc = TargetOpcode::G_FMAXNUM;
0606       break;
0607     case TargetOpcode::G_VECREDUCE_FMIN:
0608       ScalarOpc = TargetOpcode::G_FMINNUM;
0609       break;
0610     case TargetOpcode::G_VECREDUCE_FMAXIMUM:
0611       ScalarOpc = TargetOpcode::G_FMAXIMUM;
0612       break;
0613     case TargetOpcode::G_VECREDUCE_FMINIMUM:
0614       ScalarOpc = TargetOpcode::G_FMINIMUM;
0615       break;
0616     case TargetOpcode::G_VECREDUCE_ADD:
0617       ScalarOpc = TargetOpcode::G_ADD;
0618       break;
0619     case TargetOpcode::G_VECREDUCE_MUL:
0620       ScalarOpc = TargetOpcode::G_MUL;
0621       break;
0622     case TargetOpcode::G_VECREDUCE_AND:
0623       ScalarOpc = TargetOpcode::G_AND;
0624       break;
0625     case TargetOpcode::G_VECREDUCE_OR:
0626       ScalarOpc = TargetOpcode::G_OR;
0627       break;
0628     case TargetOpcode::G_VECREDUCE_XOR:
0629       ScalarOpc = TargetOpcode::G_XOR;
0630       break;
0631     case TargetOpcode::G_VECREDUCE_SMAX:
0632       ScalarOpc = TargetOpcode::G_SMAX;
0633       break;
0634     case TargetOpcode::G_VECREDUCE_SMIN:
0635       ScalarOpc = TargetOpcode::G_SMIN;
0636       break;
0637     case TargetOpcode::G_VECREDUCE_UMAX:
0638       ScalarOpc = TargetOpcode::G_UMAX;
0639       break;
0640     case TargetOpcode::G_VECREDUCE_UMIN:
0641       ScalarOpc = TargetOpcode::G_UMIN;
0642       break;
0643     default:
0644       llvm_unreachable("Unhandled reduction");
0645     }
0646     return ScalarOpc;
0647   }
0648 };
0649 
0650 /// Represents a G_PHI.
0651 class GPhi : public GenericMachineInstr {
0652 public:
0653   /// Returns the number of incoming values.
0654   unsigned getNumIncomingValues() const { return (getNumOperands() - 1) / 2; }
0655   /// Returns the I'th incoming vreg.
0656   Register getIncomingValue(unsigned I) const {
0657     return getOperand(I * 2 + 1).getReg();
0658   }
0659   /// Returns the I'th incoming basic block.
0660   MachineBasicBlock *getIncomingBlock(unsigned I) const {
0661     return getOperand(I * 2 + 2).getMBB();
0662   }
0663 
0664   static bool classof(const MachineInstr *MI) {
0665     return MI->getOpcode() == TargetOpcode::G_PHI;
0666   }
0667 };
0668 
0669 /// Represents a binary operation, i.e, x = y op z.
0670 class GBinOp : public GenericMachineInstr {
0671 public:
0672   Register getLHSReg() const { return getReg(1); }
0673   Register getRHSReg() const { return getReg(2); }
0674 
0675   static bool classof(const MachineInstr *MI) {
0676     switch (MI->getOpcode()) {
0677     // Integer.
0678     case TargetOpcode::G_ADD:
0679     case TargetOpcode::G_SUB:
0680     case TargetOpcode::G_MUL:
0681     case TargetOpcode::G_SDIV:
0682     case TargetOpcode::G_UDIV:
0683     case TargetOpcode::G_SREM:
0684     case TargetOpcode::G_UREM:
0685     case TargetOpcode::G_SMIN:
0686     case TargetOpcode::G_SMAX:
0687     case TargetOpcode::G_UMIN:
0688     case TargetOpcode::G_UMAX:
0689     // Floating point.
0690     case TargetOpcode::G_FMINNUM:
0691     case TargetOpcode::G_FMAXNUM:
0692     case TargetOpcode::G_FMINNUM_IEEE:
0693     case TargetOpcode::G_FMAXNUM_IEEE:
0694     case TargetOpcode::G_FMINIMUM:
0695     case TargetOpcode::G_FMAXIMUM:
0696     case TargetOpcode::G_FADD:
0697     case TargetOpcode::G_FSUB:
0698     case TargetOpcode::G_FMUL:
0699     case TargetOpcode::G_FDIV:
0700     case TargetOpcode::G_FPOW:
0701     // Logical.
0702     case TargetOpcode::G_AND:
0703     case TargetOpcode::G_OR:
0704     case TargetOpcode::G_XOR:
0705       return true;
0706     default:
0707       return false;
0708     }
0709   };
0710 };
0711 
0712 /// Represents an integer binary operation.
0713 class GIntBinOp : public GBinOp {
0714 public:
0715   static bool classof(const MachineInstr *MI) {
0716     switch (MI->getOpcode()) {
0717     case TargetOpcode::G_ADD:
0718     case TargetOpcode::G_SUB:
0719     case TargetOpcode::G_MUL:
0720     case TargetOpcode::G_SDIV:
0721     case TargetOpcode::G_UDIV:
0722     case TargetOpcode::G_SREM:
0723     case TargetOpcode::G_UREM:
0724     case TargetOpcode::G_SMIN:
0725     case TargetOpcode::G_SMAX:
0726     case TargetOpcode::G_UMIN:
0727     case TargetOpcode::G_UMAX:
0728       return true;
0729     default:
0730       return false;
0731     }
0732   };
0733 };
0734 
0735 /// Represents a floating point binary operation.
0736 class GFBinOp : public GBinOp {
0737 public:
0738   static bool classof(const MachineInstr *MI) {
0739     switch (MI->getOpcode()) {
0740     case TargetOpcode::G_FMINNUM:
0741     case TargetOpcode::G_FMAXNUM:
0742     case TargetOpcode::G_FMINNUM_IEEE:
0743     case TargetOpcode::G_FMAXNUM_IEEE:
0744     case TargetOpcode::G_FMINIMUM:
0745     case TargetOpcode::G_FMAXIMUM:
0746     case TargetOpcode::G_FADD:
0747     case TargetOpcode::G_FSUB:
0748     case TargetOpcode::G_FMUL:
0749     case TargetOpcode::G_FDIV:
0750     case TargetOpcode::G_FPOW:
0751       return true;
0752     default:
0753       return false;
0754     }
0755   };
0756 };
0757 
0758 /// Represents a logical binary operation.
0759 class GLogicalBinOp : public GBinOp {
0760 public:
0761   static bool classof(const MachineInstr *MI) {
0762     switch (MI->getOpcode()) {
0763     case TargetOpcode::G_AND:
0764     case TargetOpcode::G_OR:
0765     case TargetOpcode::G_XOR:
0766       return true;
0767     default:
0768       return false;
0769     }
0770   };
0771 };
0772 
0773 /// Represents an integer addition.
0774 class GAdd : public GIntBinOp {
0775 public:
0776   static bool classof(const MachineInstr *MI) {
0777     return MI->getOpcode() == TargetOpcode::G_ADD;
0778   };
0779 };
0780 
0781 /// Represents a logical and.
0782 class GAnd : public GLogicalBinOp {
0783 public:
0784   static bool classof(const MachineInstr *MI) {
0785     return MI->getOpcode() == TargetOpcode::G_AND;
0786   };
0787 };
0788 
0789 /// Represents a logical or.
0790 class GOr : public GLogicalBinOp {
0791 public:
0792   static bool classof(const MachineInstr *MI) {
0793     return MI->getOpcode() == TargetOpcode::G_OR;
0794   };
0795 };
0796 
0797 /// Represents an extract vector element.
0798 class GExtractVectorElement : public GenericMachineInstr {
0799 public:
0800   Register getVectorReg() const { return getOperand(1).getReg(); }
0801   Register getIndexReg() const { return getOperand(2).getReg(); }
0802 
0803   static bool classof(const MachineInstr *MI) {
0804     return MI->getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT;
0805   }
0806 };
0807 
0808 /// Represents an insert vector element.
0809 class GInsertVectorElement : public GenericMachineInstr {
0810 public:
0811   Register getVectorReg() const { return getOperand(1).getReg(); }
0812   Register getElementReg() const { return getOperand(2).getReg(); }
0813   Register getIndexReg() const { return getOperand(3).getReg(); }
0814 
0815   static bool classof(const MachineInstr *MI) {
0816     return MI->getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
0817   }
0818 };
0819 
0820 /// Represents an extract subvector.
0821 class GExtractSubvector : public GenericMachineInstr {
0822 public:
0823   Register getSrcVec() const { return getOperand(1).getReg(); }
0824   uint64_t getIndexImm() const { return getOperand(2).getImm(); }
0825 
0826   static bool classof(const MachineInstr *MI) {
0827     return MI->getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR;
0828   }
0829 };
0830 
0831 /// Represents a insert subvector.
0832 class GInsertSubvector : public GenericMachineInstr {
0833 public:
0834   Register getBigVec() const { return getOperand(1).getReg(); }
0835   Register getSubVec() const { return getOperand(2).getReg(); }
0836   uint64_t getIndexImm() const { return getOperand(3).getImm(); }
0837 
0838   static bool classof(const MachineInstr *MI) {
0839     return MI->getOpcode() == TargetOpcode::G_INSERT_SUBVECTOR;
0840   }
0841 };
0842 
0843 /// Represents a freeze.
0844 class GFreeze : public GenericMachineInstr {
0845 public:
0846   Register getSourceReg() const { return getOperand(1).getReg(); }
0847 
0848   static bool classof(const MachineInstr *MI) {
0849     return MI->getOpcode() == TargetOpcode::G_FREEZE;
0850   }
0851 };
0852 
0853 /// Represents a cast operation.
0854 /// It models the llvm::CastInst concept.
0855 /// The exception is bitcast.
0856 class GCastOp : public GenericMachineInstr {
0857 public:
0858   Register getSrcReg() const { return getOperand(1).getReg(); }
0859 
0860   static bool classof(const MachineInstr *MI) {
0861     switch (MI->getOpcode()) {
0862     case TargetOpcode::G_ADDRSPACE_CAST:
0863     case TargetOpcode::G_FPEXT:
0864     case TargetOpcode::G_FPTOSI:
0865     case TargetOpcode::G_FPTOUI:
0866     case TargetOpcode::G_FPTOSI_SAT:
0867     case TargetOpcode::G_FPTOUI_SAT:
0868     case TargetOpcode::G_FPTRUNC:
0869     case TargetOpcode::G_INTTOPTR:
0870     case TargetOpcode::G_PTRTOINT:
0871     case TargetOpcode::G_SEXT:
0872     case TargetOpcode::G_SITOFP:
0873     case TargetOpcode::G_TRUNC:
0874     case TargetOpcode::G_UITOFP:
0875     case TargetOpcode::G_ZEXT:
0876     case TargetOpcode::G_ANYEXT:
0877       return true;
0878     default:
0879       return false;
0880     }
0881   };
0882 };
0883 
0884 /// Represents a sext.
0885 class GSext : public GCastOp {
0886 public:
0887   static bool classof(const MachineInstr *MI) {
0888     return MI->getOpcode() == TargetOpcode::G_SEXT;
0889   };
0890 };
0891 
0892 /// Represents a zext.
0893 class GZext : public GCastOp {
0894 public:
0895   static bool classof(const MachineInstr *MI) {
0896     return MI->getOpcode() == TargetOpcode::G_ZEXT;
0897   };
0898 };
0899 
0900 /// Represents an any ext.
0901 class GAnyExt : public GCastOp {
0902 public:
0903   static bool classof(const MachineInstr *MI) {
0904     return MI->getOpcode() == TargetOpcode::G_ANYEXT;
0905   };
0906 };
0907 
0908 /// Represents a trunc.
0909 class GTrunc : public GCastOp {
0910 public:
0911   static bool classof(const MachineInstr *MI) {
0912     return MI->getOpcode() == TargetOpcode::G_TRUNC;
0913   };
0914 };
0915 
0916 /// Represents a vscale.
0917 class GVScale : public GenericMachineInstr {
0918 public:
0919   APInt getSrc() const { return getOperand(1).getCImm()->getValue(); }
0920 
0921   static bool classof(const MachineInstr *MI) {
0922     return MI->getOpcode() == TargetOpcode::G_VSCALE;
0923   };
0924 };
0925 
0926 /// Represents a step vector.
0927 class GStepVector : public GenericMachineInstr {
0928 public:
0929   uint64_t getStep() const {
0930     return getOperand(1).getCImm()->getValue().getZExtValue();
0931   }
0932 
0933   static bool classof(const MachineInstr *MI) {
0934     return MI->getOpcode() == TargetOpcode::G_STEP_VECTOR;
0935   };
0936 };
0937 
0938 /// Represents an integer subtraction.
0939 class GSub : public GIntBinOp {
0940 public:
0941   static bool classof(const MachineInstr *MI) {
0942     return MI->getOpcode() == TargetOpcode::G_SUB;
0943   };
0944 };
0945 
0946 /// Represents an integer multiplication.
0947 class GMul : public GIntBinOp {
0948 public:
0949   static bool classof(const MachineInstr *MI) {
0950     return MI->getOpcode() == TargetOpcode::G_MUL;
0951   };
0952 };
0953 
0954 /// Represents a shift left.
0955 class GShl : public GenericMachineInstr {
0956 public:
0957   Register getSrcReg() const { return getOperand(1).getReg(); }
0958   Register getShiftReg() const { return getOperand(2).getReg(); }
0959 
0960   static bool classof(const MachineInstr *MI) {
0961     return MI->getOpcode() == TargetOpcode::G_SHL;
0962   };
0963 };
0964 
0965 /// Represents a threeway compare.
0966 class GSUCmp : public GenericMachineInstr {
0967 public:
0968   Register getLHSReg() const { return getOperand(1).getReg(); }
0969   Register getRHSReg() const { return getOperand(2).getReg(); }
0970 
0971   bool isSigned() const { return getOpcode() == TargetOpcode::G_SCMP; }
0972 
0973   static bool classof(const MachineInstr *MI) {
0974     switch (MI->getOpcode()) {
0975     case TargetOpcode::G_SCMP:
0976     case TargetOpcode::G_UCMP:
0977       return true;
0978     default:
0979       return false;
0980     }
0981   };
0982 };
0983 
0984 /// Represents an integer-like extending operation.
0985 class GExtOp : public GCastOp {
0986 public:
0987   static bool classof(const MachineInstr *MI) {
0988     switch (MI->getOpcode()) {
0989     case TargetOpcode::G_SEXT:
0990     case TargetOpcode::G_ZEXT:
0991     case TargetOpcode::G_ANYEXT:
0992       return true;
0993     default:
0994       return false;
0995     }
0996   };
0997 };
0998 
0999 /// Represents an integer-like extending or truncating operation.
1000 class GExtOrTruncOp : public GCastOp {
1001 public:
1002   static bool classof(const MachineInstr *MI) {
1003     switch (MI->getOpcode()) {
1004     case TargetOpcode::G_SEXT:
1005     case TargetOpcode::G_ZEXT:
1006     case TargetOpcode::G_ANYEXT:
1007     case TargetOpcode::G_TRUNC:
1008       return true;
1009     default:
1010       return false;
1011     }
1012   };
1013 };
1014 
1015 /// Represents a splat vector.
1016 class GSplatVector : public GenericMachineInstr {
1017 public:
1018   Register getScalarReg() const { return getOperand(1).getReg(); }
1019 
1020   static bool classof(const MachineInstr *MI) {
1021     return MI->getOpcode() == TargetOpcode::G_SPLAT_VECTOR;
1022   };
1023 };
1024 
1025 } // namespace llvm
1026 
1027 #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H