| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 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 |  | 
| Benjamin Kramer | a7c40ef | 2014-08-13 16:26:38 +0000 | [diff] [blame] | 14 | #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64INSTRINFO_H | 
|  | 15 | #define LLVM_LIB_TARGET_AARCH64_AARCH64INSTRINFO_H | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 16 |  | 
|  | 17 | #include "AArch64.h" | 
|  | 18 | #include "AArch64RegisterInfo.h" | 
|  | 19 | #include "llvm/Target/TargetInstrInfo.h" | 
| Gerolf Hoflehner | 97c383b | 2014-08-07 21:40:58 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/MachineCombinerPattern.h" | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 21 |  | 
|  | 22 | #define GET_INSTRINFO_HEADER | 
|  | 23 | #include "AArch64GenInstrInfo.inc" | 
|  | 24 |  | 
|  | 25 | namespace llvm { | 
|  | 26 |  | 
|  | 27 | class AArch64Subtarget; | 
|  | 28 | class AArch64TargetMachine; | 
|  | 29 |  | 
|  | 30 | class AArch64InstrInfo : public AArch64GenInstrInfo { | 
|  | 31 | // Reserve bits in the MachineMemOperand target hint flags, starting at 1. | 
|  | 32 | // They will be shifted into MOTargetHintStart when accessed. | 
|  | 33 | enum TargetMemOperandFlags { | 
|  | 34 | MOSuppressPair = 1 | 
|  | 35 | }; | 
|  | 36 |  | 
|  | 37 | const AArch64RegisterInfo RI; | 
|  | 38 | const AArch64Subtarget &Subtarget; | 
|  | 39 |  | 
|  | 40 | public: | 
|  | 41 | explicit AArch64InstrInfo(const AArch64Subtarget &STI); | 
|  | 42 |  | 
|  | 43 | /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As | 
|  | 44 | /// such, whenever a client has an instance of instruction info, it should | 
|  | 45 | /// always be able to get register info as well (through this method). | 
|  | 46 | const AArch64RegisterInfo &getRegisterInfo() const { return RI; } | 
|  | 47 |  | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 48 | unsigned GetInstSizeInBytes(const MachineInstr *MI) const; | 
|  | 49 |  | 
| Jiangning Liu | cd29637 | 2014-07-29 02:09:26 +0000 | [diff] [blame] | 50 | bool isAsCheapAsAMove(const MachineInstr *MI) const override; | 
|  | 51 |  | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 52 | bool isCoalescableExtInstr(const MachineInstr &MI, unsigned &SrcReg, | 
|  | 53 | unsigned &DstReg, unsigned &SubIdx) const override; | 
|  | 54 |  | 
|  | 55 | unsigned isLoadFromStackSlot(const MachineInstr *MI, | 
|  | 56 | int &FrameIndex) const override; | 
|  | 57 | unsigned isStoreToStackSlot(const MachineInstr *MI, | 
|  | 58 | int &FrameIndex) const override; | 
|  | 59 |  | 
|  | 60 | /// Returns true if there is a shiftable register and that the shift value | 
|  | 61 | /// is non-zero. | 
|  | 62 | bool hasShiftedReg(const MachineInstr *MI) const; | 
|  | 63 |  | 
|  | 64 | /// Returns true if there is an extendable register and that the extending | 
|  | 65 | /// value is non-zero. | 
|  | 66 | bool hasExtendedReg(const MachineInstr *MI) const; | 
|  | 67 |  | 
|  | 68 | /// \brief Does this instruction set its full destination register to zero? | 
|  | 69 | bool isGPRZero(const MachineInstr *MI) const; | 
|  | 70 |  | 
|  | 71 | /// \brief Does this instruction rename a GPR without modifying bits? | 
|  | 72 | bool isGPRCopy(const MachineInstr *MI) const; | 
|  | 73 |  | 
|  | 74 | /// \brief Does this instruction rename an FPR without modifying bits? | 
|  | 75 | bool isFPRCopy(const MachineInstr *MI) const; | 
|  | 76 |  | 
|  | 77 | /// Return true if this is load/store scales or extends its register offset. | 
|  | 78 | /// This refers to scaling a dynamic index as opposed to scaled immediates. | 
|  | 79 | /// MI should be a memory op that allows scaled addressing. | 
|  | 80 | bool isScaledAddr(const MachineInstr *MI) const; | 
|  | 81 |  | 
|  | 82 | /// Return true if pairing the given load or store is hinted to be | 
|  | 83 | /// unprofitable. | 
|  | 84 | bool isLdStPairSuppressed(const MachineInstr *MI) const; | 
|  | 85 |  | 
|  | 86 | /// Hint that pairing the given load or store is unprofitable. | 
|  | 87 | void suppressLdStPair(MachineInstr *MI) const; | 
|  | 88 |  | 
|  | 89 | bool getLdStBaseRegImmOfs(MachineInstr *LdSt, unsigned &BaseReg, | 
|  | 90 | unsigned &Offset, | 
|  | 91 | const TargetRegisterInfo *TRI) const override; | 
|  | 92 |  | 
|  | 93 | bool enableClusterLoads() const override { return true; } | 
|  | 94 |  | 
|  | 95 | bool shouldClusterLoads(MachineInstr *FirstLdSt, MachineInstr *SecondLdSt, | 
|  | 96 | unsigned NumLoads) const override; | 
|  | 97 |  | 
|  | 98 | bool shouldScheduleAdjacent(MachineInstr *First, | 
|  | 99 | MachineInstr *Second) const override; | 
|  | 100 |  | 
|  | 101 | MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, | 
|  | 102 | uint64_t Offset, const MDNode *MDPtr, | 
|  | 103 | DebugLoc DL) const; | 
|  | 104 | void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, | 
|  | 105 | DebugLoc DL, unsigned DestReg, unsigned SrcReg, | 
|  | 106 | bool KillSrc, unsigned Opcode, | 
|  | 107 | llvm::ArrayRef<unsigned> Indices) const; | 
|  | 108 | void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, | 
|  | 109 | DebugLoc DL, unsigned DestReg, unsigned SrcReg, | 
|  | 110 | bool KillSrc) const override; | 
|  | 111 |  | 
|  | 112 | void storeRegToStackSlot(MachineBasicBlock &MBB, | 
|  | 113 | MachineBasicBlock::iterator MBBI, unsigned SrcReg, | 
|  | 114 | bool isKill, int FrameIndex, | 
|  | 115 | const TargetRegisterClass *RC, | 
|  | 116 | const TargetRegisterInfo *TRI) const override; | 
|  | 117 |  | 
|  | 118 | void loadRegFromStackSlot(MachineBasicBlock &MBB, | 
|  | 119 | MachineBasicBlock::iterator MBBI, unsigned DestReg, | 
|  | 120 | int FrameIndex, const TargetRegisterClass *RC, | 
|  | 121 | const TargetRegisterInfo *TRI) const override; | 
|  | 122 |  | 
| Aaron Ballman | ed9fabd | 2014-07-31 12:58:50 +0000 | [diff] [blame] | 123 | using TargetInstrInfo::foldMemoryOperandImpl; | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 124 | MachineInstr * | 
|  | 125 | foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, | 
|  | 126 | const SmallVectorImpl<unsigned> &Ops, | 
|  | 127 | int FrameIndex) const override; | 
|  | 128 |  | 
|  | 129 | bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, | 
|  | 130 | MachineBasicBlock *&FBB, | 
|  | 131 | SmallVectorImpl<MachineOperand> &Cond, | 
|  | 132 | bool AllowModify = false) const override; | 
|  | 133 | unsigned RemoveBranch(MachineBasicBlock &MBB) const override; | 
|  | 134 | unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, | 
|  | 135 | MachineBasicBlock *FBB, | 
|  | 136 | const SmallVectorImpl<MachineOperand> &Cond, | 
|  | 137 | DebugLoc DL) const override; | 
|  | 138 | bool | 
|  | 139 | ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; | 
|  | 140 | bool canInsertSelect(const MachineBasicBlock &, | 
|  | 141 | const SmallVectorImpl<MachineOperand> &Cond, unsigned, | 
|  | 142 | unsigned, int &, int &, int &) const override; | 
|  | 143 | void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, | 
|  | 144 | DebugLoc DL, unsigned DstReg, | 
|  | 145 | const SmallVectorImpl<MachineOperand> &Cond, | 
|  | 146 | unsigned TrueReg, unsigned FalseReg) const override; | 
|  | 147 | void getNoopForMachoTarget(MCInst &NopInst) const override; | 
|  | 148 |  | 
|  | 149 | /// analyzeCompare - For a comparison instruction, return the source registers | 
|  | 150 | /// in SrcReg and SrcReg2, and the value it compares against in CmpValue. | 
|  | 151 | /// Return true if the comparison instruction can be analyzed. | 
|  | 152 | bool analyzeCompare(const MachineInstr *MI, unsigned &SrcReg, | 
|  | 153 | unsigned &SrcReg2, int &CmpMask, | 
|  | 154 | int &CmpValue) const override; | 
|  | 155 | /// optimizeCompareInstr - Convert the instruction supplying the argument to | 
|  | 156 | /// the comparison into one that sets the zero bit in the flags register. | 
|  | 157 | bool optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, | 
|  | 158 | unsigned SrcReg2, int CmpMask, int CmpValue, | 
|  | 159 | const MachineRegisterInfo *MRI) const override; | 
| Gerolf Hoflehner | 97c383b | 2014-08-07 21:40:58 +0000 | [diff] [blame] | 160 | /// hasPattern - return true when there is potentially a faster code sequence | 
|  | 161 | /// for an instruction chain ending in <Root>. All potential patterns are | 
|  | 162 | /// listed | 
|  | 163 | /// in the <Pattern> array. | 
|  | 164 | virtual bool hasPattern( | 
|  | 165 | MachineInstr &Root, | 
|  | 166 | SmallVectorImpl<MachineCombinerPattern::MC_PATTERN> &Pattern) const; | 
|  | 167 |  | 
|  | 168 | /// genAlternativeCodeSequence - when hasPattern() finds a pattern | 
|  | 169 | /// this function generates the instructions that could replace the | 
|  | 170 | /// original code sequence | 
|  | 171 | virtual void genAlternativeCodeSequence( | 
|  | 172 | MachineInstr &Root, MachineCombinerPattern::MC_PATTERN P, | 
|  | 173 | SmallVectorImpl<MachineInstr *> &InsInstrs, | 
|  | 174 | SmallVectorImpl<MachineInstr *> &DelInstrs, | 
|  | 175 | DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const; | 
|  | 176 | /// useMachineCombiner - AArch64 supports MachineCombiner | 
|  | 177 | virtual bool useMachineCombiner(void) const; | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 178 |  | 
| Akira Hatanaka | e5b6e0d | 2014-07-25 19:31:34 +0000 | [diff] [blame] | 179 | bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override; | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 180 | private: | 
|  | 181 | void instantiateCondBranch(MachineBasicBlock &MBB, DebugLoc DL, | 
|  | 182 | MachineBasicBlock *TBB, | 
|  | 183 | const SmallVectorImpl<MachineOperand> &Cond) const; | 
|  | 184 | }; | 
|  | 185 |  | 
|  | 186 | /// emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg | 
|  | 187 | /// plus Offset.  This is intended to be used from within the prolog/epilog | 
|  | 188 | /// insertion (PEI) pass, where a virtual scratch register may be allocated | 
|  | 189 | /// if necessary, to be replaced by the scavenger at the end of PEI. | 
|  | 190 | void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | 191 | DebugLoc DL, unsigned DestReg, unsigned SrcReg, int Offset, | 
| Eric Christopher | bc76b97 | 2014-06-10 17:33:39 +0000 | [diff] [blame] | 192 | const TargetInstrInfo *TII, | 
| Tim Northover | 3b0846e | 2014-05-24 12:50:23 +0000 | [diff] [blame] | 193 | MachineInstr::MIFlag = MachineInstr::NoFlags, | 
|  | 194 | bool SetNZCV = false); | 
|  | 195 |  | 
|  | 196 | /// rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the | 
|  | 197 | /// FP. Return false if the offset could not be handled directly in MI, and | 
|  | 198 | /// return the left-over portion by reference. | 
|  | 199 | bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, | 
|  | 200 | unsigned FrameReg, int &Offset, | 
|  | 201 | const AArch64InstrInfo *TII); | 
|  | 202 |  | 
|  | 203 | /// \brief Use to report the frame offset status in isAArch64FrameOffsetLegal. | 
|  | 204 | enum AArch64FrameOffsetStatus { | 
|  | 205 | AArch64FrameOffsetCannotUpdate = 0x0, ///< Offset cannot apply. | 
|  | 206 | AArch64FrameOffsetIsLegal = 0x1,      ///< Offset is legal. | 
|  | 207 | AArch64FrameOffsetCanUpdate = 0x2     ///< Offset can apply, at least partly. | 
|  | 208 | }; | 
|  | 209 |  | 
|  | 210 | /// \brief Check if the @p Offset is a valid frame offset for @p MI. | 
|  | 211 | /// The returned value reports the validity of the frame offset for @p MI. | 
|  | 212 | /// It uses the values defined by AArch64FrameOffsetStatus for that. | 
|  | 213 | /// If result == AArch64FrameOffsetCannotUpdate, @p MI cannot be updated to | 
|  | 214 | /// use an offset.eq | 
|  | 215 | /// If result & AArch64FrameOffsetIsLegal, @p Offset can completely be | 
|  | 216 | /// rewriten in @p MI. | 
|  | 217 | /// If result & AArch64FrameOffsetCanUpdate, @p Offset contains the | 
|  | 218 | /// amount that is off the limit of the legal offset. | 
|  | 219 | /// If set, @p OutUseUnscaledOp will contain the whether @p MI should be | 
|  | 220 | /// turned into an unscaled operator, which opcode is in @p OutUnscaledOp. | 
|  | 221 | /// If set, @p EmittableOffset contains the amount that can be set in @p MI | 
|  | 222 | /// (possibly with @p OutUnscaledOp if OutUseUnscaledOp is true) and that | 
|  | 223 | /// is a legal offset. | 
|  | 224 | int isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset, | 
|  | 225 | bool *OutUseUnscaledOp = nullptr, | 
|  | 226 | unsigned *OutUnscaledOp = nullptr, | 
|  | 227 | int *EmittableOffset = nullptr); | 
|  | 228 |  | 
|  | 229 | static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; } | 
|  | 230 |  | 
|  | 231 | static inline bool isCondBranchOpcode(int Opc) { | 
|  | 232 | switch (Opc) { | 
|  | 233 | case AArch64::Bcc: | 
|  | 234 | case AArch64::CBZW: | 
|  | 235 | case AArch64::CBZX: | 
|  | 236 | case AArch64::CBNZW: | 
|  | 237 | case AArch64::CBNZX: | 
|  | 238 | case AArch64::TBZW: | 
|  | 239 | case AArch64::TBZX: | 
|  | 240 | case AArch64::TBNZW: | 
|  | 241 | case AArch64::TBNZX: | 
|  | 242 | return true; | 
|  | 243 | default: | 
|  | 244 | return false; | 
|  | 245 | } | 
|  | 246 | } | 
|  | 247 |  | 
|  | 248 | static inline bool isIndirectBranchOpcode(int Opc) { return Opc == AArch64::BR; } | 
|  | 249 |  | 
|  | 250 | } // end namespace llvm | 
|  | 251 |  | 
|  | 252 | #endif |