LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64InstrInfo.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 4 4 100.0 %
Date: 2018-10-20 13:21:21 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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     3547094 :   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       39790 :     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        1321 :   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      377195 :   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

Generated by: LCOV version 1.13