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
|