Home | History | Annotate | Download | only in AArch64
      1 //===- AArch64InstrInfo.h - AArch64 Instruction Information -----*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the AArch64 implementation of the TargetInstrInfo class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64INSTRINFO_H
     15 #define LLVM_LIB_TARGET_AARCH64_AARCH64INSTRINFO_H
     16 
     17 #include "AArch64.h"
     18 #include "AArch64RegisterInfo.h"
     19 #include "llvm/CodeGen/MachineCombinerPattern.h"
     20 #include "llvm/CodeGen/TargetInstrInfo.h"
     21 
     22 #define GET_INSTRINFO_HEADER
     23 #include "AArch64GenInstrInfo.inc"
     24 
     25 namespace llvm {
     26 
     27 class AArch64Subtarget;
     28 class AArch64TargetMachine;
     29 
     30 static const MachineMemOperand::Flags MOSuppressPair =
     31     MachineMemOperand::MOTargetFlag1;
     32 static const MachineMemOperand::Flags MOStridedAccess =
     33     MachineMemOperand::MOTargetFlag2;
     34 
     35 #define FALKOR_STRIDED_ACCESS_MD "falkor.strided.access"
     36 
     37 class AArch64InstrInfo final : public AArch64GenInstrInfo {
     38   const AArch64RegisterInfo RI;
     39   const AArch64Subtarget &Subtarget;
     40 
     41 public:
     42   explicit AArch64InstrInfo(const AArch64Subtarget &STI);
     43 
     44   /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As
     45   /// such, whenever a client has an instance of instruction info, it should
     46   /// always be able to get register info as well (through this method).
     47   const AArch64RegisterInfo &getRegisterInfo() const { return RI; }
     48 
     49   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
     50 
     51   bool isAsCheapAsAMove(const MachineInstr &MI) const override;
     52 
     53   bool isCoalescableExtInstr(const MachineInstr &MI, unsigned &SrcReg,
     54                              unsigned &DstReg, unsigned &SubIdx) const override;
     55 
     56   bool
     57   areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
     58                                   AliasAnalysis *AA = nullptr) const override;
     59 
     60   unsigned isLoadFromStackSlot(const MachineInstr &MI,
     61                                int &FrameIndex) const override;
     62   unsigned isStoreToStackSlot(const MachineInstr &MI,
     63                               int &FrameIndex) const override;
     64 
     65   /// Returns true if there is a shiftable register and that the shift value
     66   /// is non-zero.
     67   static bool hasShiftedReg(const MachineInstr &MI);
     68 
     69   /// Returns true if there is an extendable register and that the extending
     70   /// value is non-zero.
     71   static bool hasExtendedReg(const MachineInstr &MI);
     72 
     73   /// Does this instruction set its full destination register to zero?
     74   static bool isGPRZero(const MachineInstr &MI);
     75 
     76   /// Does this instruction rename a GPR without modifying bits?
     77   static bool isGPRCopy(const MachineInstr &MI);
     78 
     79   /// Does this instruction rename an FPR without modifying bits?
     80   static bool isFPRCopy(const MachineInstr &MI);
     81 
     82   /// Return true if this is load/store scales or extends its register offset.
     83   /// This refers to scaling a dynamic index as opposed to scaled immediates.
     84   /// MI should be a memory op that allows scaled addressing.
     85   static bool isScaledAddr(const MachineInstr &MI);
     86 
     87   /// Return true if pairing the given load or store is hinted to be
     88   /// unprofitable.
     89   static bool isLdStPairSuppressed(const MachineInstr &MI);
     90 
     91   /// Return true if the given load or store is a strided memory access.
     92   static bool isStridedAccess(const MachineInstr &MI);
     93 
     94   /// Return true if this is an unscaled load/store.
     95   static bool isUnscaledLdSt(unsigned Opc);
     96   static bool isUnscaledLdSt(MachineInstr &MI) {
     97     return isUnscaledLdSt(MI.getOpcode());
     98   }
     99 
    100   /// Return true if pairing the given load or store may be paired with another.
    101   static bool isPairableLdStInst(const MachineInstr &MI);
    102 
    103   /// Return the opcode that set flags when possible.  The caller is
    104   /// responsible for ensuring the opc has a flag setting equivalent.
    105   static unsigned convertToFlagSettingOpc(unsigned Opc, bool &Is64Bit);
    106 
    107   /// Return true if this is a load/store that can be potentially paired/merged.
    108   bool isCandidateToMergeOrPair(MachineInstr &MI) const;
    109 
    110   /// Hint that pairing the given load or store is unprofitable.
    111   static void suppressLdStPair(MachineInstr &MI);
    112 
    113   bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg,
    114                              int64_t &Offset,
    115                              const TargetRegisterInfo *TRI) const override;
    116 
    117   bool getMemOpBaseRegImmOfsWidth(MachineInstr &LdSt, unsigned &BaseReg,
    118                                   int64_t &Offset, unsigned &Width,
    119                                   const TargetRegisterInfo *TRI) const;
    120 
    121   /// Return the immediate offset of the base register in a load/store \p LdSt.
    122   MachineOperand &getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const;
    123 
    124   /// Returns true if opcode \p Opc is a memory operation. If it is, set
    125   /// \p Scale, \p Width, \p MinOffset, and \p MaxOffset accordingly.
    126   ///
    127   /// For unscaled instructions, \p Scale is set to 1.
    128   bool getMemOpInfo(unsigned Opcode, unsigned &Scale, unsigned &Width,
    129                     int64_t &MinOffset, int64_t &MaxOffset) const;
    130 
    131   bool shouldClusterMemOps(MachineInstr &FirstLdSt, unsigned BaseReg1,
    132                            MachineInstr &SecondLdSt, unsigned BaseReg2,
    133                            unsigned NumLoads) const override;
    134 
    135   void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
    136                         const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
    137                         bool KillSrc, unsigned Opcode,
    138                         llvm::ArrayRef<unsigned> Indices) const;
    139   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
    140                    const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
    141                    bool KillSrc) const override;
    142 
    143   void storeRegToStackSlot(MachineBasicBlock &MBB,
    144                            MachineBasicBlock::iterator MBBI, unsigned SrcReg,
    145                            bool isKill, int FrameIndex,
    146                            const TargetRegisterClass *RC,
    147                            const TargetRegisterInfo *TRI) const override;
    148 
    149   void loadRegFromStackSlot(MachineBasicBlock &MBB,
    150                             MachineBasicBlock::iterator MBBI, unsigned DestReg,
    151                             int FrameIndex, const TargetRegisterClass *RC,
    152                             const TargetRegisterInfo *TRI) const override;
    153 
    154   // This tells target independent code that it is okay to pass instructions
    155   // with subreg operands to foldMemoryOperandImpl.
    156   bool isSubregFoldable() const override { return true; }
    157 
    158   using TargetInstrInfo::foldMemoryOperandImpl;
    159   MachineInstr *
    160   foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
    161                         ArrayRef<unsigned> Ops,
    162                         MachineBasicBlock::iterator InsertPt, int FrameIndex,
    163                         LiveIntervals *LIS = nullptr) const override;
    164 
    165   /// \returns true if a branch from an instruction with opcode \p BranchOpc
    166   ///  bytes is capable of jumping to a position \p BrOffset bytes away.
    167   bool isBranchOffsetInRange(unsigned BranchOpc,
    168                              int64_t BrOffset) const override;
    169 
    170   MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
    171 
    172   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
    173                      MachineBasicBlock *&FBB,
    174                      SmallVectorImpl<MachineOperand> &Cond,
    175                      bool AllowModify = false) const override;
    176   unsigned removeBranch(MachineBasicBlock &MBB,
    177                         int *BytesRemoved = nullptr) const override;
    178   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
    179                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
    180                         const DebugLoc &DL,
    181                         int *BytesAdded = nullptr) const override;
    182   bool
    183   reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
    184   bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
    185                        unsigned, unsigned, int &, int &, int &) const override;
    186   void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
    187                     const DebugLoc &DL, unsigned DstReg,
    188                     ArrayRef<MachineOperand> Cond, unsigned TrueReg,
    189                     unsigned FalseReg) const override;
    190   void getNoop(MCInst &NopInst) const override;
    191 
    192   /// analyzeCompare - For a comparison instruction, return the source registers
    193   /// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
    194   /// Return true if the comparison instruction can be analyzed.
    195   bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
    196                       unsigned &SrcReg2, int &CmpMask,
    197                       int &CmpValue) const override;
    198   /// optimizeCompareInstr - Convert the instruction supplying the argument to
    199   /// the comparison into one that sets the zero bit in the flags register.
    200   bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
    201                             unsigned SrcReg2, int CmpMask, int CmpValue,
    202                             const MachineRegisterInfo *MRI) const override;
    203   bool optimizeCondBranch(MachineInstr &MI) const override;
    204 
    205   /// Return true when a code sequence can improve throughput. It
    206   /// should be called only for instructions in loops.
    207   /// \param Pattern - combiner pattern
    208   bool isThroughputPattern(MachineCombinerPattern Pattern) const override;
    209   /// Return true when there is potentially a faster code sequence
    210   /// for an instruction chain ending in ``Root``. All potential patterns are
    211   /// listed in the ``Patterns`` array.
    212   bool getMachineCombinerPatterns(
    213       MachineInstr &Root,
    214       SmallVectorImpl<MachineCombinerPattern> &Patterns) const override;
    215   /// Return true when Inst is associative and commutative so that it can be
    216   /// reassociated.
    217   bool isAssociativeAndCommutative(const MachineInstr &Inst) const override;
    218   /// When getMachineCombinerPatterns() finds patterns, this function generates
    219   /// the instructions that could replace the original code sequence
    220   void genAlternativeCodeSequence(
    221       MachineInstr &Root, MachineCombinerPattern Pattern,
    222       SmallVectorImpl<MachineInstr *> &InsInstrs,
    223       SmallVectorImpl<MachineInstr *> &DelInstrs,
    224       DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override;
    225   /// AArch64 supports MachineCombiner.
    226   bool useMachineCombiner() const override;
    227 
    228   bool expandPostRAPseudo(MachineInstr &MI) const override;
    229 
    230   std::pair<unsigned, unsigned>
    231   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
    232   ArrayRef<std::pair<unsigned, const char *>>
    233   getSerializableDirectMachineOperandTargetFlags() const override;
    234   ArrayRef<std::pair<unsigned, const char *>>
    235   getSerializableBitmaskMachineOperandTargetFlags() const override;
    236   ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>
    237   getSerializableMachineMemOperandTargetFlags() const override;
    238 
    239   bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
    240                                    bool OutlineFromLinkOnceODRs) const override;
    241   outliner::OutlinedFunction getOutliningCandidateInfo(
    242       std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;
    243   outliner::InstrType
    244   getOutliningType(MachineBasicBlock::iterator &MIT, unsigned Flags) const override;
    245   unsigned getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const override;
    246   void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
    247                           const outliner::OutlinedFunction &OF) const override;
    248   MachineBasicBlock::iterator
    249   insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
    250                      MachineBasicBlock::iterator &It, MachineFunction &MF,
    251                      const outliner::Candidate &C) const override;
    252   bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;
    253   /// Returns true if the instruction sets to an immediate value that can be
    254   /// executed more efficiently.
    255   bool isExynosResetFast(const MachineInstr &MI) const;
    256   /// Returns true if the instruction has a shift left that can be executed
    257   /// more efficiently.
    258   bool isExynosShiftLeftFast(const MachineInstr &MI) const;
    259   /// Returns true if the instruction has a shift by immediate that can be
    260   /// executed in one cycle less.
    261   bool isFalkorShiftExtFast(const MachineInstr &MI) const;
    262 
    263 private:
    264   /// Sets the offsets on outlined instructions in \p MBB which use SP
    265   /// so that they will be valid post-outlining.
    266   ///
    267   /// \param MBB A \p MachineBasicBlock in an outlined function.
    268   void fixupPostOutline(MachineBasicBlock &MBB) const;
    269 
    270   void instantiateCondBranch(MachineBasicBlock &MBB, const DebugLoc &DL,
    271                              MachineBasicBlock *TBB,
    272                              ArrayRef<MachineOperand> Cond) const;
    273   bool substituteCmpToZero(MachineInstr &CmpInstr, unsigned SrcReg,
    274                            const MachineRegisterInfo *MRI) const;
    275 
    276   /// Returns an unused general-purpose register which can be used for
    277   /// constructing an outlined call if one exists. Returns 0 otherwise.
    278   unsigned findRegisterToSaveLRTo(const outliner::Candidate &C) const;
    279 };
    280 
    281 /// emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg
    282 /// plus Offset.  This is intended to be used from within the prolog/epilog
    283 /// insertion (PEI) pass, where a virtual scratch register may be allocated
    284 /// if necessary, to be replaced by the scavenger at the end of PEI.
    285 void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
    286                      const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
    287                      int Offset, const TargetInstrInfo *TII,
    288                      MachineInstr::MIFlag = MachineInstr::NoFlags,
    289                      bool SetNZCV = false);
    290 
    291 /// rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the
    292 /// FP. Return false if the offset could not be handled directly in MI, and
    293 /// return the left-over portion by reference.
    294 bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
    295                               unsigned FrameReg, int &Offset,
    296                               const AArch64InstrInfo *TII);
    297 
    298 /// Use to report the frame offset status in isAArch64FrameOffsetLegal.
    299 enum AArch64FrameOffsetStatus {
    300   AArch64FrameOffsetCannotUpdate = 0x0, ///< Offset cannot apply.
    301   AArch64FrameOffsetIsLegal = 0x1,      ///< Offset is legal.
    302   AArch64FrameOffsetCanUpdate = 0x2     ///< Offset can apply, at least partly.
    303 };
    304 
    305 /// Check if the @p Offset is a valid frame offset for @p MI.
    306 /// The returned value reports the validity of the frame offset for @p MI.
    307 /// It uses the values defined by AArch64FrameOffsetStatus for that.
    308 /// If result == AArch64FrameOffsetCannotUpdate, @p MI cannot be updated to
    309 /// use an offset.eq
    310 /// If result & AArch64FrameOffsetIsLegal, @p Offset can completely be
    311 /// rewritten in @p MI.
    312 /// If result & AArch64FrameOffsetCanUpdate, @p Offset contains the
    313 /// amount that is off the limit of the legal offset.
    314 /// If set, @p OutUseUnscaledOp will contain the whether @p MI should be
    315 /// turned into an unscaled operator, which opcode is in @p OutUnscaledOp.
    316 /// If set, @p EmittableOffset contains the amount that can be set in @p MI
    317 /// (possibly with @p OutUnscaledOp if OutUseUnscaledOp is true) and that
    318 /// is a legal offset.
    319 int isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset,
    320                               bool *OutUseUnscaledOp = nullptr,
    321                               unsigned *OutUnscaledOp = nullptr,
    322                               int *EmittableOffset = nullptr);
    323 
    324 static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; }
    325 
    326 static inline bool isCondBranchOpcode(int Opc) {
    327   switch (Opc) {
    328   case AArch64::Bcc:
    329   case AArch64::CBZW:
    330   case AArch64::CBZX:
    331   case AArch64::CBNZW:
    332   case AArch64::CBNZX:
    333   case AArch64::TBZW:
    334   case AArch64::TBZX:
    335   case AArch64::TBNZW:
    336   case AArch64::TBNZX:
    337     return true;
    338   default:
    339     return false;
    340   }
    341 }
    342 
    343 static inline bool isIndirectBranchOpcode(int Opc) {
    344   return Opc == AArch64::BR;
    345 }
    346 
    347 // struct TSFlags {
    348 #define TSFLAG_ELEMENT_SIZE_TYPE(X)      (X)       // 3-bits
    349 #define TSFLAG_DESTRUCTIVE_INST_TYPE(X) ((X) << 3) // 1-bit
    350 // }
    351 
    352 namespace AArch64 {
    353 
    354 enum ElementSizeType {
    355   ElementSizeMask = TSFLAG_ELEMENT_SIZE_TYPE(0x7),
    356   ElementSizeNone = TSFLAG_ELEMENT_SIZE_TYPE(0x0),
    357   ElementSizeB    = TSFLAG_ELEMENT_SIZE_TYPE(0x1),
    358   ElementSizeH    = TSFLAG_ELEMENT_SIZE_TYPE(0x2),
    359   ElementSizeS    = TSFLAG_ELEMENT_SIZE_TYPE(0x3),
    360   ElementSizeD    = TSFLAG_ELEMENT_SIZE_TYPE(0x4),
    361 };
    362 
    363 enum DestructiveInstType {
    364   DestructiveInstTypeMask = TSFLAG_DESTRUCTIVE_INST_TYPE(0x1),
    365   NotDestructive          = TSFLAG_DESTRUCTIVE_INST_TYPE(0x0),
    366   Destructive             = TSFLAG_DESTRUCTIVE_INST_TYPE(0x1),
    367 };
    368 
    369 #undef TSFLAG_ELEMENT_SIZE_TYPE
    370 #undef TSFLAG_DESTRUCTIVE_INST_TYPE
    371 }
    372 
    373 } // end namespace llvm
    374 
    375 #endif
    376