1 | //===-- R600InstrInfo.h - R600 Instruction Info Interface -------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | /// \file |
10 | /// Interface definition for R600InstrInfo |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_LIB_TARGET_AMDGPU_R600INSTRINFO_H |
15 | #define LLVM_LIB_TARGET_AMDGPU_R600INSTRINFO_H |
16 | |
17 | #include "R600RegisterInfo.h" |
18 | #include "llvm/CodeGen/TargetInstrInfo.h" |
19 | |
20 | #define |
21 | #define GET_INSTRINFO_OPERAND_ENUM |
22 | #include "R600GenInstrInfo.inc" |
23 | |
24 | namespace llvm { |
25 | |
26 | namespace R600InstrFlags { |
27 | enum : uint64_t { |
28 | REGISTER_STORE = UINT64_C(1) << 62, |
29 | REGISTER_LOAD = UINT64_C(1) << 63 |
30 | }; |
31 | } |
32 | |
33 | class DFAPacketizer; |
34 | class MachineFunction; |
35 | class MachineInstr; |
36 | class MachineInstrBuilder; |
37 | class R600Subtarget; |
38 | |
39 | class R600InstrInfo final : public R600GenInstrInfo { |
40 | private: |
41 | const R600RegisterInfo RI; |
42 | const R600Subtarget &ST; |
43 | |
44 | std::vector<std::pair<int, unsigned>> |
45 | (MachineInstr &MI, const DenseMap<unsigned, unsigned> &PV, |
46 | unsigned &ConstCount) const; |
47 | |
48 | MachineInstrBuilder buildIndirectRead(MachineBasicBlock *MBB, |
49 | MachineBasicBlock::iterator I, |
50 | unsigned ValueReg, unsigned Address, |
51 | unsigned OffsetReg, |
52 | unsigned AddrChan) const; |
53 | |
54 | MachineInstrBuilder buildIndirectWrite(MachineBasicBlock *MBB, |
55 | MachineBasicBlock::iterator I, |
56 | unsigned ValueReg, unsigned Address, |
57 | unsigned OffsetReg, |
58 | unsigned AddrChan) const; |
59 | public: |
60 | enum BankSwizzle { |
61 | ALU_VEC_012_SCL_210 = 0, |
62 | ALU_VEC_021_SCL_122, |
63 | ALU_VEC_120_SCL_212, |
64 | ALU_VEC_102_SCL_221, |
65 | ALU_VEC_201, |
66 | ALU_VEC_210 |
67 | }; |
68 | |
69 | explicit R600InstrInfo(const R600Subtarget &); |
70 | |
71 | const R600RegisterInfo &getRegisterInfo() const { |
72 | return RI; |
73 | } |
74 | |
75 | void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, |
76 | const DebugLoc &DL, Register DestReg, Register SrcReg, |
77 | bool KillSrc, bool RenamableDest = false, |
78 | bool RenamableSrc = false) const override; |
79 | bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, |
80 | MachineBasicBlock::iterator MBBI) const override; |
81 | |
82 | bool isReductionOp(unsigned opcode) const; |
83 | bool isCubeOp(unsigned opcode) const; |
84 | |
85 | /// \returns true if this \p Opcode represents an ALU instruction. |
86 | bool isALUInstr(unsigned Opcode) const; |
87 | bool hasInstrModifiers(unsigned Opcode) const; |
88 | bool isLDSInstr(unsigned Opcode) const; |
89 | bool isLDSRetInstr(unsigned Opcode) const; |
90 | |
91 | /// \returns true if this \p Opcode represents an ALU instruction or an |
92 | /// instruction that will be lowered in ExpandSpecialInstrs Pass. |
93 | bool canBeConsideredALU(const MachineInstr &MI) const; |
94 | |
95 | bool isTransOnly(unsigned Opcode) const; |
96 | bool isTransOnly(const MachineInstr &MI) const; |
97 | bool isVectorOnly(unsigned Opcode) const; |
98 | bool isVectorOnly(const MachineInstr &MI) const; |
99 | bool isExport(unsigned Opcode) const; |
100 | |
101 | bool usesVertexCache(unsigned Opcode) const; |
102 | bool usesVertexCache(const MachineInstr &MI) const; |
103 | bool usesTextureCache(unsigned Opcode) const; |
104 | bool usesTextureCache(const MachineInstr &MI) const; |
105 | |
106 | bool mustBeLastInClause(unsigned Opcode) const; |
107 | bool usesAddressRegister(MachineInstr &MI) const; |
108 | bool definesAddressRegister(MachineInstr &MI) const; |
109 | bool readsLDSSrcReg(const MachineInstr &MI) const; |
110 | |
111 | /// \returns The operand Index for the Sel operand given an index to one |
112 | /// of the instruction's src operands. |
113 | int getSelIdx(unsigned Opcode, unsigned SrcIdx) const; |
114 | |
115 | /// \returns a pair for each src of an ALU instructions. |
116 | /// The first member of a pair is the register id. |
117 | /// If register is ALU_CONST, second member is SEL. |
118 | /// If register is ALU_LITERAL, second member is IMM. |
119 | /// Otherwise, second member value is undefined. |
120 | SmallVector<std::pair<MachineOperand *, int64_t>, 3> |
121 | getSrcs(MachineInstr &MI) const; |
122 | |
123 | unsigned isLegalUpTo( |
124 | const std::vector<std::vector<std::pair<int, unsigned> > > &IGSrcs, |
125 | const std::vector<R600InstrInfo::BankSwizzle> &Swz, |
126 | const std::vector<std::pair<int, unsigned> > &TransSrcs, |
127 | R600InstrInfo::BankSwizzle TransSwz) const; |
128 | |
129 | bool FindSwizzleForVectorSlot( |
130 | const std::vector<std::vector<std::pair<int, unsigned> > > &IGSrcs, |
131 | std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate, |
132 | const std::vector<std::pair<int, unsigned> > &TransSrcs, |
133 | R600InstrInfo::BankSwizzle TransSwz) const; |
134 | |
135 | /// Given the order VEC_012 < VEC_021 < VEC_120 < VEC_102 < VEC_201 < VEC_210 |
136 | /// returns true and the first (in lexical order) BankSwizzle affectation |
137 | /// starting from the one already provided in the Instruction Group MIs that |
138 | /// fits Read Port limitations in BS if available. Otherwise returns false |
139 | /// and undefined content in BS. |
140 | /// isLastAluTrans should be set if the last Alu of MIs will be executed on |
141 | /// Trans ALU. In this case, ValidTSwizzle returns the BankSwizzle value to |
142 | /// apply to the last instruction. |
143 | /// PV holds GPR to PV registers in the Instruction Group MIs. |
144 | bool fitsReadPortLimitations(const std::vector<MachineInstr *> &MIs, |
145 | const DenseMap<unsigned, unsigned> &PV, |
146 | std::vector<BankSwizzle> &BS, |
147 | bool isLastAluTrans) const; |
148 | |
149 | /// An instruction group can only access 2 channel pair (either [XY] or [ZW]) |
150 | /// from KCache bank on R700+. This function check if MI set in input meet |
151 | /// this limitations |
152 | bool fitsConstReadLimitations(const std::vector<MachineInstr *> &) const; |
153 | /// Same but using const index set instead of MI set. |
154 | bool fitsConstReadLimitations(const std::vector<unsigned>&) const; |
155 | |
156 | /// Vector instructions are instructions that must fill all |
157 | /// instruction slots within an instruction group. |
158 | bool isVector(const MachineInstr &MI) const; |
159 | |
160 | bool isMov(unsigned Opcode) const; |
161 | |
162 | DFAPacketizer * |
163 | CreateTargetScheduleState(const TargetSubtargetInfo &) const override; |
164 | |
165 | bool reverseBranchCondition( |
166 | SmallVectorImpl<MachineOperand> &Cond) const override; |
167 | |
168 | bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, |
169 | MachineBasicBlock *&FBB, |
170 | SmallVectorImpl<MachineOperand> &Cond, |
171 | bool AllowModify) const override; |
172 | |
173 | unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, |
174 | MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, |
175 | const DebugLoc &DL, |
176 | int *BytesAdded = nullptr) const override; |
177 | |
178 | unsigned removeBranch(MachineBasicBlock &MBB, |
179 | int *BytesRemoved = nullptr) const override; |
180 | |
181 | bool isPredicated(const MachineInstr &MI) const override; |
182 | |
183 | bool isPredicable(const MachineInstr &MI) const override; |
184 | |
185 | bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, |
186 | BranchProbability Probability) const override; |
187 | |
188 | bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, |
189 | unsigned , |
190 | BranchProbability Probability) const override ; |
191 | |
192 | bool isProfitableToIfCvt(MachineBasicBlock &TMBB, |
193 | unsigned NumTCycles, unsigned , |
194 | MachineBasicBlock &FMBB, |
195 | unsigned NumFCycles, unsigned , |
196 | BranchProbability Probability) const override; |
197 | |
198 | bool ClobbersPredicate(MachineInstr &MI, std::vector<MachineOperand> &Pred, |
199 | bool SkipDead) const override; |
200 | |
201 | bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, |
202 | MachineBasicBlock &FMBB) const override; |
203 | |
204 | bool PredicateInstruction(MachineInstr &MI, |
205 | ArrayRef<MachineOperand> Pred) const override; |
206 | |
207 | unsigned int getPredicationCost(const MachineInstr &) const override; |
208 | |
209 | unsigned int getInstrLatency(const InstrItineraryData *ItinData, |
210 | const MachineInstr &MI, |
211 | unsigned *PredCost = nullptr) const override; |
212 | |
213 | bool expandPostRAPseudo(MachineInstr &MI) const override; |
214 | |
215 | /// Reserve the registers that may be accessed using indirect addressing. |
216 | void reserveIndirectRegisters(BitVector &Reserved, |
217 | const MachineFunction &MF, |
218 | const R600RegisterInfo &TRI) const; |
219 | |
220 | /// Calculate the "Indirect Address" for the given \p RegIndex and |
221 | /// \p Channel |
222 | /// |
223 | /// We model indirect addressing using a virtual address space that can be |
224 | /// accessed with loads and stores. The "Indirect Address" is the memory |
225 | /// address in this virtual address space that maps to the given \p RegIndex |
226 | /// and \p Channel. |
227 | unsigned calculateIndirectAddress(unsigned RegIndex, unsigned Channel) const; |
228 | |
229 | |
230 | /// \returns The register class to be used for loading and storing values |
231 | /// from an "Indirect Address" . |
232 | const TargetRegisterClass *getIndirectAddrRegClass() const; |
233 | |
234 | /// \returns the smallest register index that will be accessed by an indirect |
235 | /// read or write or -1 if indirect addressing is not used by this program. |
236 | int getIndirectIndexBegin(const MachineFunction &MF) const; |
237 | |
238 | /// \returns the largest register index that will be accessed by an indirect |
239 | /// read or write or -1 if indirect addressing is not used by this program. |
240 | int getIndirectIndexEnd(const MachineFunction &MF) const; |
241 | |
242 | /// Build instruction(s) for an indirect register write. |
243 | /// |
244 | /// \returns The instruction that performs the indirect register write |
245 | MachineInstrBuilder buildIndirectWrite(MachineBasicBlock *MBB, |
246 | MachineBasicBlock::iterator I, |
247 | unsigned ValueReg, unsigned Address, |
248 | unsigned OffsetReg) const; |
249 | |
250 | /// Build instruction(s) for an indirect register read. |
251 | /// |
252 | /// \returns The instruction that performs the indirect register read |
253 | MachineInstrBuilder buildIndirectRead(MachineBasicBlock *MBB, |
254 | MachineBasicBlock::iterator I, |
255 | unsigned ValueReg, unsigned Address, |
256 | unsigned OffsetReg) const; |
257 | |
258 | unsigned getMaxAlusPerClause() const; |
259 | |
260 | /// buildDefaultInstruction - This function returns a MachineInstr with all |
261 | /// the instruction modifiers initialized to their default values. You can |
262 | /// use this function to avoid manually specifying each instruction modifier |
263 | /// operand when building a new instruction. |
264 | /// |
265 | /// \returns a MachineInstr with all the instruction modifiers initialized |
266 | /// to their default values. |
267 | MachineInstrBuilder buildDefaultInstruction(MachineBasicBlock &MBB, |
268 | MachineBasicBlock::iterator I, |
269 | unsigned Opcode, |
270 | unsigned DstReg, |
271 | unsigned Src0Reg, |
272 | unsigned Src1Reg = 0) const; |
273 | |
274 | MachineInstr *buildSlotOfVectorInstruction(MachineBasicBlock &MBB, |
275 | MachineInstr *MI, |
276 | unsigned Slot, |
277 | unsigned DstReg) const; |
278 | |
279 | MachineInstr *buildMovImm(MachineBasicBlock &BB, |
280 | MachineBasicBlock::iterator I, |
281 | unsigned DstReg, |
282 | uint64_t Imm) const; |
283 | |
284 | MachineInstr *buildMovInstr(MachineBasicBlock *MBB, |
285 | MachineBasicBlock::iterator I, |
286 | unsigned DstReg, unsigned SrcReg) const; |
287 | |
288 | /// Get the index of Op in the MachineInstr. |
289 | /// |
290 | /// \returns -1 if the Instruction does not contain the specified \p Op. |
291 | int getOperandIdx(const MachineInstr &MI, R600::OpName Op) const; |
292 | |
293 | /// Get the index of \p Op for the given Opcode. |
294 | /// |
295 | /// \returns -1 if the Instruction does not contain the specified \p Op. |
296 | int getOperandIdx(unsigned Opcode, R600::OpName Op) const; |
297 | |
298 | /// Helper function for setting instruction flag values. |
299 | void setImmOperand(MachineInstr &MI, R600::OpName Op, int64_t Imm) const; |
300 | |
301 | /// Add one of the MO_FLAG* flags to the operand at \p SrcIdx. |
302 | void addFlag(MachineInstr &MI, unsigned SrcIdx, unsigned Flag) const; |
303 | |
304 | /// Determine if the specified \p Flag is set on operand at \p SrcIdx. |
305 | bool isFlagSet(const MachineInstr &MI, unsigned SrcIdx, unsigned Flag) const; |
306 | |
307 | /// \param SrcIdx The register source to set the flag on (e.g src0, src1, src2) |
308 | /// \param Flag The flag being set. |
309 | /// |
310 | /// \returns the operand containing the flags for this instruction. |
311 | MachineOperand &getFlagOp(MachineInstr &MI, unsigned SrcIdx = 0, |
312 | unsigned Flag = 0) const; |
313 | |
314 | /// Clear the specified flag on the instruction. |
315 | void clearFlag(MachineInstr &MI, unsigned SrcIdx, unsigned Flag) const; |
316 | |
317 | // Helper functions that check the opcode for status information |
318 | bool isRegisterStore(const MachineInstr &MI) const { |
319 | return get(Opcode: MI.getOpcode()).TSFlags & R600InstrFlags::REGISTER_STORE; |
320 | } |
321 | |
322 | bool isRegisterLoad(const MachineInstr &MI) const { |
323 | return get(Opcode: MI.getOpcode()).TSFlags & R600InstrFlags::REGISTER_LOAD; |
324 | } |
325 | }; |
326 | |
327 | namespace R600 { |
328 | |
329 | int getLDSNoRetOp(uint16_t Opcode); |
330 | |
331 | } //End namespace AMDGPU |
332 | |
333 | } // End llvm namespace |
334 | |
335 | #endif |
336 | |