Line data Source code
1 : //===- SIInstrInfo.h - SI Instruction Info Interface ------------*- 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 : /// \file
11 : /// Interface definition for SIInstrInfo.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
16 : #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
17 :
18 : #include "AMDGPUInstrInfo.h"
19 : #include "SIDefines.h"
20 : #include "SIRegisterInfo.h"
21 : #include "Utils/AMDGPUBaseInfo.h"
22 : #include "llvm/ADT/ArrayRef.h"
23 : #include "llvm/ADT/SetVector.h"
24 : #include "llvm/CodeGen/MachineBasicBlock.h"
25 : #include "llvm/CodeGen/MachineFunction.h"
26 : #include "llvm/CodeGen/MachineInstr.h"
27 : #include "llvm/CodeGen/MachineInstrBuilder.h"
28 : #include "llvm/CodeGen/MachineOperand.h"
29 : #include "llvm/MC/MCInstrDesc.h"
30 : #include "llvm/Support/Compiler.h"
31 : #include <cassert>
32 : #include <cstdint>
33 :
34 : #define GET_INSTRINFO_HEADER
35 : #include "AMDGPUGenInstrInfo.inc"
36 :
37 : namespace llvm {
38 :
39 : class APInt;
40 : class MachineDominatorTree;
41 : class MachineRegisterInfo;
42 : class RegScavenger;
43 : class GCNSubtarget;
44 : class TargetRegisterClass;
45 :
46 4962 : class SIInstrInfo final : public AMDGPUGenInstrInfo {
47 : private:
48 : const SIRegisterInfo RI;
49 : const GCNSubtarget &ST;
50 :
51 : // The inverse predicate should have the negative value.
52 : enum BranchPredicate {
53 : INVALID_BR = 0,
54 : SCC_TRUE = 1,
55 : SCC_FALSE = -1,
56 : VCCNZ = 2,
57 : VCCZ = -2,
58 : EXECNZ = -3,
59 : EXECZ = 3
60 : };
61 :
62 : using SetVectorType = SmallSetVector<MachineInstr *, 32>;
63 :
64 : static unsigned getBranchOpcode(BranchPredicate Cond);
65 : static BranchPredicate getBranchPredicate(unsigned Opcode);
66 :
67 : public:
68 : unsigned buildExtractSubReg(MachineBasicBlock::iterator MI,
69 : MachineRegisterInfo &MRI,
70 : MachineOperand &SuperReg,
71 : const TargetRegisterClass *SuperRC,
72 : unsigned SubIdx,
73 : const TargetRegisterClass *SubRC) const;
74 : MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI,
75 : MachineRegisterInfo &MRI,
76 : MachineOperand &SuperReg,
77 : const TargetRegisterClass *SuperRC,
78 : unsigned SubIdx,
79 : const TargetRegisterClass *SubRC) const;
80 : private:
81 : void swapOperands(MachineInstr &Inst) const;
82 :
83 : bool moveScalarAddSub(SetVectorType &Worklist, MachineInstr &Inst,
84 : MachineDominatorTree *MDT = nullptr) const;
85 :
86 : void lowerScalarAbs(SetVectorType &Worklist,
87 : MachineInstr &Inst) const;
88 :
89 : void lowerScalarXnor(SetVectorType &Worklist,
90 : MachineInstr &Inst) const;
91 :
92 : void splitScalar64BitUnaryOp(SetVectorType &Worklist,
93 : MachineInstr &Inst, unsigned Opcode) const;
94 :
95 : void splitScalar64BitAddSub(SetVectorType &Worklist, MachineInstr &Inst,
96 : MachineDominatorTree *MDT = nullptr) const;
97 :
98 : void splitScalar64BitBinaryOp(SetVectorType &Worklist, MachineInstr &Inst,
99 : unsigned Opcode,
100 : MachineDominatorTree *MDT = nullptr) const;
101 :
102 : void splitScalar64BitBCNT(SetVectorType &Worklist,
103 : MachineInstr &Inst) const;
104 : void splitScalar64BitBFE(SetVectorType &Worklist,
105 : MachineInstr &Inst) const;
106 : void movePackToVALU(SetVectorType &Worklist,
107 : MachineRegisterInfo &MRI,
108 : MachineInstr &Inst) const;
109 :
110 : void addUsersToMoveToVALUWorklist(unsigned Reg, MachineRegisterInfo &MRI,
111 : SetVectorType &Worklist) const;
112 :
113 : void
114 : addSCCDefUsersToVALUWorklist(MachineInstr &SCCDefInst,
115 : SetVectorType &Worklist) const;
116 :
117 : const TargetRegisterClass *
118 : getDestEquivalentVGPRClass(const MachineInstr &Inst) const;
119 :
120 : bool checkInstOffsetsDoNotOverlap(MachineInstr &MIa, MachineInstr &MIb) const;
121 :
122 : unsigned findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;
123 :
124 : protected:
125 : bool swapSourceModifiers(MachineInstr &MI,
126 : MachineOperand &Src0, unsigned Src0OpName,
127 : MachineOperand &Src1, unsigned Src1OpName) const;
128 :
129 : MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
130 : unsigned OpIdx0,
131 : unsigned OpIdx1) const override;
132 :
133 : public:
134 : enum TargetOperandFlags {
135 : MO_MASK = 0x7,
136 :
137 : MO_NONE = 0,
138 : // MO_GOTPCREL -> symbol@GOTPCREL -> R_AMDGPU_GOTPCREL.
139 : MO_GOTPCREL = 1,
140 : // MO_GOTPCREL32_LO -> symbol@gotpcrel32@lo -> R_AMDGPU_GOTPCREL32_LO.
141 : MO_GOTPCREL32 = 2,
142 : MO_GOTPCREL32_LO = 2,
143 : // MO_GOTPCREL32_HI -> symbol@gotpcrel32@hi -> R_AMDGPU_GOTPCREL32_HI.
144 : MO_GOTPCREL32_HI = 3,
145 : // MO_REL32_LO -> symbol@rel32@lo -> R_AMDGPU_REL32_LO.
146 : MO_REL32 = 4,
147 : MO_REL32_LO = 4,
148 : // MO_REL32_HI -> symbol@rel32@hi -> R_AMDGPU_REL32_HI.
149 : MO_REL32_HI = 5
150 : };
151 :
152 : explicit SIInstrInfo(const GCNSubtarget &ST);
153 :
154 : const SIRegisterInfo &getRegisterInfo() const {
155 32073298 : return RI;
156 : }
157 :
158 : bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
159 : AliasAnalysis *AA) const override;
160 :
161 : bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
162 : int64_t &Offset1,
163 : int64_t &Offset2) const override;
164 :
165 : bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg,
166 : int64_t &Offset,
167 : const TargetRegisterInfo *TRI) const final;
168 :
169 : bool shouldClusterMemOps(MachineInstr &FirstLdSt, unsigned BaseReg1,
170 : MachineInstr &SecondLdSt, unsigned BaseReg2,
171 : unsigned NumLoads) const override;
172 :
173 : bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0,
174 : int64_t Offset1, unsigned NumLoads) const override;
175 :
176 : void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
177 : const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
178 : bool KillSrc) const override;
179 :
180 : unsigned calculateLDSSpillAddress(MachineBasicBlock &MBB, MachineInstr &MI,
181 : RegScavenger *RS, unsigned TmpReg,
182 : unsigned Offset, unsigned Size) const;
183 :
184 : void materializeImmediate(MachineBasicBlock &MBB,
185 : MachineBasicBlock::iterator MI,
186 : const DebugLoc &DL,
187 : unsigned DestReg,
188 : int64_t Value) const;
189 :
190 : const TargetRegisterClass *getPreferredSelectRegClass(
191 : unsigned Size) const;
192 :
193 : unsigned insertNE(MachineBasicBlock *MBB,
194 : MachineBasicBlock::iterator I, const DebugLoc &DL,
195 : unsigned SrcReg, int Value) const;
196 :
197 : unsigned insertEQ(MachineBasicBlock *MBB,
198 : MachineBasicBlock::iterator I, const DebugLoc &DL,
199 : unsigned SrcReg, int Value) const;
200 :
201 : void storeRegToStackSlot(MachineBasicBlock &MBB,
202 : MachineBasicBlock::iterator MI, unsigned SrcReg,
203 : bool isKill, int FrameIndex,
204 : const TargetRegisterClass *RC,
205 : const TargetRegisterInfo *TRI) const override;
206 :
207 : void loadRegFromStackSlot(MachineBasicBlock &MBB,
208 : MachineBasicBlock::iterator MI, unsigned DestReg,
209 : int FrameIndex, const TargetRegisterClass *RC,
210 : const TargetRegisterInfo *TRI) const override;
211 :
212 : bool expandPostRAPseudo(MachineInstr &MI) const override;
213 :
214 : // Returns an opcode that can be used to move a value to a \p DstRC
215 : // register. If there is no hardware instruction that can store to \p
216 : // DstRC, then AMDGPU::COPY is returned.
217 : unsigned getMovOpcode(const TargetRegisterClass *DstRC) const;
218 :
219 : LLVM_READONLY
220 : int commuteOpcode(unsigned Opc) const;
221 :
222 : LLVM_READONLY
223 : inline int commuteOpcode(const MachineInstr &MI) const {
224 9900 : return commuteOpcode(MI.getOpcode());
225 : }
226 :
227 : bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
228 : unsigned &SrcOpIdx2) const override;
229 :
230 : bool findCommutedOpIndices(MCInstrDesc Desc, unsigned & SrcOpIdx0,
231 : unsigned & SrcOpIdx1) const;
232 :
233 : bool isBranchOffsetInRange(unsigned BranchOpc,
234 : int64_t BrOffset) const override;
235 :
236 : MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
237 :
238 : unsigned insertIndirectBranch(MachineBasicBlock &MBB,
239 : MachineBasicBlock &NewDestBB,
240 : const DebugLoc &DL,
241 : int64_t BrOffset,
242 : RegScavenger *RS = nullptr) const override;
243 :
244 : bool analyzeBranchImpl(MachineBasicBlock &MBB,
245 : MachineBasicBlock::iterator I,
246 : MachineBasicBlock *&TBB,
247 : MachineBasicBlock *&FBB,
248 : SmallVectorImpl<MachineOperand> &Cond,
249 : bool AllowModify) const;
250 :
251 : bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
252 : MachineBasicBlock *&FBB,
253 : SmallVectorImpl<MachineOperand> &Cond,
254 : bool AllowModify = false) const override;
255 :
256 : unsigned removeBranch(MachineBasicBlock &MBB,
257 : int *BytesRemoved = nullptr) const override;
258 :
259 : unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
260 : MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
261 : const DebugLoc &DL,
262 : int *BytesAdded = nullptr) const override;
263 :
264 : bool reverseBranchCondition(
265 : SmallVectorImpl<MachineOperand> &Cond) const override;
266 :
267 : bool canInsertSelect(const MachineBasicBlock &MBB,
268 : ArrayRef<MachineOperand> Cond,
269 : unsigned TrueReg, unsigned FalseReg,
270 : int &CondCycles,
271 : int &TrueCycles, int &FalseCycles) const override;
272 :
273 : void insertSelect(MachineBasicBlock &MBB,
274 : MachineBasicBlock::iterator I, const DebugLoc &DL,
275 : unsigned DstReg, ArrayRef<MachineOperand> Cond,
276 : unsigned TrueReg, unsigned FalseReg) const override;
277 :
278 : void insertVectorSelect(MachineBasicBlock &MBB,
279 : MachineBasicBlock::iterator I, const DebugLoc &DL,
280 : unsigned DstReg, ArrayRef<MachineOperand> Cond,
281 : unsigned TrueReg, unsigned FalseReg) const;
282 :
283 : unsigned getAddressSpaceForPseudoSourceKind(
284 : unsigned Kind) const override;
285 :
286 : bool
287 : areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
288 : AliasAnalysis *AA = nullptr) const override;
289 :
290 : bool isFoldableCopy(const MachineInstr &MI) const;
291 :
292 : bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, unsigned Reg,
293 : MachineRegisterInfo *MRI) const final;
294 :
295 38977 : unsigned getMachineCSELookAheadLimit() const override { return 500; }
296 :
297 : MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
298 : MachineInstr &MI,
299 : LiveVariables *LV) const override;
300 :
301 : bool isSchedulingBoundary(const MachineInstr &MI,
302 : const MachineBasicBlock *MBB,
303 : const MachineFunction &MF) const override;
304 :
305 : static bool isSALU(const MachineInstr &MI) {
306 7756373 : return MI.getDesc().TSFlags & SIInstrFlags::SALU;
307 : }
308 :
309 : bool isSALU(uint16_t Opcode) const {
310 : return get(Opcode).TSFlags & SIInstrFlags::SALU;
311 : }
312 :
313 : static bool isVALU(const MachineInstr &MI) {
314 13521158 : return MI.getDesc().TSFlags & SIInstrFlags::VALU;
315 : }
316 :
317 : bool isVALU(uint16_t Opcode) const {
318 : return get(Opcode).TSFlags & SIInstrFlags::VALU;
319 : }
320 :
321 : static bool isVMEM(const MachineInstr &MI) {
322 2994805 : return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI);
323 : }
324 :
325 : bool isVMEM(uint16_t Opcode) const {
326 : return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode);
327 : }
328 :
329 : static bool isSOP1(const MachineInstr &MI) {
330 : return MI.getDesc().TSFlags & SIInstrFlags::SOP1;
331 : }
332 :
333 : bool isSOP1(uint16_t Opcode) const {
334 : return get(Opcode).TSFlags & SIInstrFlags::SOP1;
335 : }
336 :
337 : static bool isSOP2(const MachineInstr &MI) {
338 : return MI.getDesc().TSFlags & SIInstrFlags::SOP2;
339 : }
340 :
341 : bool isSOP2(uint16_t Opcode) const {
342 : return get(Opcode).TSFlags & SIInstrFlags::SOP2;
343 : }
344 :
345 : static bool isSOPC(const MachineInstr &MI) {
346 9349 : return MI.getDesc().TSFlags & SIInstrFlags::SOPC;
347 : }
348 :
349 : bool isSOPC(uint16_t Opcode) const {
350 : return get(Opcode).TSFlags & SIInstrFlags::SOPC;
351 : }
352 :
353 : static bool isSOPK(const MachineInstr &MI) {
354 11521906 : return MI.getDesc().TSFlags & SIInstrFlags::SOPK;
355 : }
356 :
357 : bool isSOPK(uint16_t Opcode) const {
358 : return get(Opcode).TSFlags & SIInstrFlags::SOPK;
359 : }
360 :
361 : static bool isSOPP(const MachineInstr &MI) {
362 : return MI.getDesc().TSFlags & SIInstrFlags::SOPP;
363 : }
364 :
365 : bool isSOPP(uint16_t Opcode) const {
366 : return get(Opcode).TSFlags & SIInstrFlags::SOPP;
367 : }
368 :
369 : static bool isVOP1(const MachineInstr &MI) {
370 11521226 : return MI.getDesc().TSFlags & SIInstrFlags::VOP1;
371 : }
372 :
373 : bool isVOP1(uint16_t Opcode) const {
374 : return get(Opcode).TSFlags & SIInstrFlags::VOP1;
375 : }
376 :
377 : static bool isVOP2(const MachineInstr &MI) {
378 10535079 : return MI.getDesc().TSFlags & SIInstrFlags::VOP2;
379 : }
380 :
381 : bool isVOP2(uint16_t Opcode) const {
382 : return get(Opcode).TSFlags & SIInstrFlags::VOP2;
383 : }
384 :
385 : static bool isVOP3(const MachineInstr &MI) {
386 13515162 : return MI.getDesc().TSFlags & SIInstrFlags::VOP3;
387 : }
388 :
389 : bool isVOP3(uint16_t Opcode) const {
390 83146 : return get(Opcode).TSFlags & SIInstrFlags::VOP3;
391 : }
392 :
393 : static bool isSDWA(const MachineInstr &MI) {
394 19314199 : return MI.getDesc().TSFlags & SIInstrFlags::SDWA;
395 : }
396 :
397 : bool isSDWA(uint16_t Opcode) const {
398 5772 : return get(Opcode).TSFlags & SIInstrFlags::SDWA;
399 : }
400 :
401 : static bool isVOPC(const MachineInstr &MI) {
402 7506128 : return MI.getDesc().TSFlags & SIInstrFlags::VOPC;
403 : }
404 :
405 : bool isVOPC(uint16_t Opcode) const {
406 240998 : return get(Opcode).TSFlags & SIInstrFlags::VOPC;
407 : }
408 :
409 : static bool isMUBUF(const MachineInstr &MI) {
410 2967227 : return MI.getDesc().TSFlags & SIInstrFlags::MUBUF;
411 : }
412 :
413 : bool isMUBUF(uint16_t Opcode) const {
414 285995 : return get(Opcode).TSFlags & SIInstrFlags::MUBUF;
415 : }
416 :
417 : static bool isMTBUF(const MachineInstr &MI) {
418 1220590 : return MI.getDesc().TSFlags & SIInstrFlags::MTBUF;
419 : }
420 :
421 : bool isMTBUF(uint16_t Opcode) const {
422 67811 : return get(Opcode).TSFlags & SIInstrFlags::MTBUF;
423 : }
424 :
425 : static bool isSMRD(const MachineInstr &MI) {
426 16319883 : return MI.getDesc().TSFlags & SIInstrFlags::SMRD;
427 : }
428 :
429 : bool isSMRD(uint16_t Opcode) const {
430 311115 : return get(Opcode).TSFlags & SIInstrFlags::SMRD;
431 : }
432 :
433 : bool isBufferSMRD(const MachineInstr &MI) const;
434 :
435 : static bool isDS(const MachineInstr &MI) {
436 2451769 : return MI.getDesc().TSFlags & SIInstrFlags::DS;
437 : }
438 :
439 : bool isDS(uint16_t Opcode) const {
440 314738 : return get(Opcode).TSFlags & SIInstrFlags::DS;
441 : }
442 :
443 : static bool isMIMG(const MachineInstr &MI) {
444 1006274 : return MI.getDesc().TSFlags & SIInstrFlags::MIMG;
445 : }
446 :
447 : bool isMIMG(uint16_t Opcode) const {
448 856474 : return get(Opcode).TSFlags & SIInstrFlags::MIMG;
449 : }
450 :
451 : static bool isGather4(const MachineInstr &MI) {
452 : return MI.getDesc().TSFlags & SIInstrFlags::Gather4;
453 : }
454 :
455 : bool isGather4(uint16_t Opcode) const {
456 823 : return get(Opcode).TSFlags & SIInstrFlags::Gather4;
457 : }
458 :
459 : static bool isFLAT(const MachineInstr &MI) {
460 12841138 : return MI.getDesc().TSFlags & SIInstrFlags::FLAT;
461 : }
462 :
463 : // Is a FLAT encoded instruction which accesses a specific segment,
464 : // i.e. global_* or scratch_*.
465 : static bool isSegmentSpecificFLAT(const MachineInstr &MI) {
466 : auto Flags = MI.getDesc().TSFlags;
467 41224 : return (Flags & SIInstrFlags::FLAT) && !(Flags & SIInstrFlags::LGKM_CNT);
468 : }
469 :
470 : // Any FLAT encoded instruction, including global_* and scratch_*.
471 : bool isFLAT(uint16_t Opcode) const {
472 : return get(Opcode).TSFlags & SIInstrFlags::FLAT;
473 : }
474 :
475 : static bool isEXP(const MachineInstr &MI) {
476 517 : return MI.getDesc().TSFlags & SIInstrFlags::EXP;
477 : }
478 :
479 : bool isEXP(uint16_t Opcode) const {
480 : return get(Opcode).TSFlags & SIInstrFlags::EXP;
481 : }
482 :
483 : static bool isWQM(const MachineInstr &MI) {
484 : return MI.getDesc().TSFlags & SIInstrFlags::WQM;
485 : }
486 :
487 : bool isWQM(uint16_t Opcode) const {
488 859910 : return get(Opcode).TSFlags & SIInstrFlags::WQM;
489 : }
490 :
491 : static bool isDisableWQM(const MachineInstr &MI) {
492 429337 : return MI.getDesc().TSFlags & SIInstrFlags::DisableWQM;
493 : }
494 :
495 : bool isDisableWQM(uint16_t Opcode) const {
496 : return get(Opcode).TSFlags & SIInstrFlags::DisableWQM;
497 : }
498 :
499 : static bool isVGPRSpill(const MachineInstr &MI) {
500 1244 : return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill;
501 : }
502 :
503 : bool isVGPRSpill(uint16_t Opcode) const {
504 : return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill;
505 : }
506 :
507 : static bool isSGPRSpill(const MachineInstr &MI) {
508 6900 : return MI.getDesc().TSFlags & SIInstrFlags::SGPRSpill;
509 : }
510 :
511 : bool isSGPRSpill(uint16_t Opcode) const {
512 : return get(Opcode).TSFlags & SIInstrFlags::SGPRSpill;
513 : }
514 :
515 : static bool isDPP(const MachineInstr &MI) {
516 744998 : return MI.getDesc().TSFlags & SIInstrFlags::DPP;
517 : }
518 :
519 : bool isDPP(uint16_t Opcode) const {
520 : return get(Opcode).TSFlags & SIInstrFlags::DPP;
521 : }
522 :
523 : static bool isVOP3P(const MachineInstr &MI) {
524 : return MI.getDesc().TSFlags & SIInstrFlags::VOP3P;
525 : }
526 :
527 : bool isVOP3P(uint16_t Opcode) const {
528 : return get(Opcode).TSFlags & SIInstrFlags::VOP3P;
529 : }
530 :
531 : static bool isVINTRP(const MachineInstr &MI) {
532 131878 : return MI.getDesc().TSFlags & SIInstrFlags::VINTRP;
533 : }
534 :
535 : bool isVINTRP(uint16_t Opcode) const {
536 : return get(Opcode).TSFlags & SIInstrFlags::VINTRP;
537 : }
538 :
539 : static bool isScalarUnit(const MachineInstr &MI) {
540 0 : return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD);
541 : }
542 :
543 : static bool usesVM_CNT(const MachineInstr &MI) {
544 22146 : return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT;
545 : }
546 :
547 : static bool usesLGKM_CNT(const MachineInstr &MI) {
548 22162 : return MI.getDesc().TSFlags & SIInstrFlags::LGKM_CNT;
549 : }
550 :
551 : static bool sopkIsZext(const MachineInstr &MI) {
552 13823 : return MI.getDesc().TSFlags & SIInstrFlags::SOPK_ZEXT;
553 : }
554 :
555 : bool sopkIsZext(uint16_t Opcode) const {
556 154 : return get(Opcode).TSFlags & SIInstrFlags::SOPK_ZEXT;
557 : }
558 :
559 : /// \returns true if this is an s_store_dword* instruction. This is more
560 : /// specific than than isSMEM && mayStore.
561 : static bool isScalarStore(const MachineInstr &MI) {
562 357193 : return MI.getDesc().TSFlags & SIInstrFlags::SCALAR_STORE;
563 : }
564 :
565 : bool isScalarStore(uint16_t Opcode) const {
566 : return get(Opcode).TSFlags & SIInstrFlags::SCALAR_STORE;
567 : }
568 :
569 : static bool isFixedSize(const MachineInstr &MI) {
570 732495 : return MI.getDesc().TSFlags & SIInstrFlags::FIXED_SIZE;
571 : }
572 :
573 : bool isFixedSize(uint16_t Opcode) const {
574 : return get(Opcode).TSFlags & SIInstrFlags::FIXED_SIZE;
575 : }
576 :
577 : static bool hasFPClamp(const MachineInstr &MI) {
578 : return MI.getDesc().TSFlags & SIInstrFlags::FPClamp;
579 : }
580 :
581 : bool hasFPClamp(uint16_t Opcode) const {
582 : return get(Opcode).TSFlags & SIInstrFlags::FPClamp;
583 : }
584 :
585 : static bool hasIntClamp(const MachineInstr &MI) {
586 : return MI.getDesc().TSFlags & SIInstrFlags::IntClamp;
587 : }
588 :
589 0 : uint64_t getClampMask(const MachineInstr &MI) const {
590 : const uint64_t ClampFlags = SIInstrFlags::FPClamp |
591 : SIInstrFlags::IntClamp |
592 : SIInstrFlags::ClampLo |
593 : SIInstrFlags::ClampHi;
594 268 : return MI.getDesc().TSFlags & ClampFlags;
595 : }
596 :
597 : bool isVGPRCopy(const MachineInstr &MI) const {
598 : assert(MI.isCopy());
599 993530 : unsigned Dest = MI.getOperand(0).getReg();
600 993530 : const MachineFunction &MF = *MI.getParent()->getParent();
601 993530 : const MachineRegisterInfo &MRI = MF.getRegInfo();
602 993530 : return !RI.isSGPRReg(MRI, Dest);
603 : }
604 :
605 : /// Whether we must prevent this instruction from executing with EXEC = 0.
606 : bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const;
607 :
608 : bool isInlineConstant(const APInt &Imm) const;
609 :
610 : bool isInlineConstant(const MachineOperand &MO, uint8_t OperandType) const;
611 :
612 0 : bool isInlineConstant(const MachineOperand &MO,
613 : const MCOperandInfo &OpInfo) const {
614 2518081 : return isInlineConstant(MO, OpInfo.OperandType);
615 : }
616 :
617 : /// \p returns true if \p UseMO is substituted with \p DefMO in \p MI it would
618 : /// be an inline immediate.
619 207 : bool isInlineConstant(const MachineInstr &MI,
620 : const MachineOperand &UseMO,
621 : const MachineOperand &DefMO) const {
622 : assert(UseMO.getParent() == &MI);
623 207 : int OpIdx = MI.getOperandNo(&UseMO);
624 207 : if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands) {
625 : return false;
626 : }
627 :
628 207 : return isInlineConstant(DefMO, MI.getDesc().OpInfo[OpIdx]);
629 : }
630 :
631 : /// \p returns true if the operand \p OpIdx in \p MI is a valid inline
632 : /// immediate.
633 : bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx) const {
634 : const MachineOperand &MO = MI.getOperand(OpIdx);
635 2156220 : return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
636 : }
637 :
638 149938 : bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx,
639 : const MachineOperand &MO) const {
640 149938 : if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands)
641 : return false;
642 :
643 85893 : if (MI.isCopy()) {
644 12214 : unsigned Size = getOpSize(MI, OpIdx);
645 : assert(Size == 8 || Size == 4);
646 :
647 12214 : uint8_t OpType = (Size == 8) ?
648 : AMDGPU::OPERAND_REG_IMM_INT64 : AMDGPU::OPERAND_REG_IMM_INT32;
649 12214 : return isInlineConstant(MO, OpType);
650 : }
651 :
652 73679 : return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
653 : }
654 :
655 34791 : bool isInlineConstant(const MachineOperand &MO) const {
656 34791 : const MachineInstr *Parent = MO.getParent();
657 34791 : return isInlineConstant(*Parent, Parent->getOperandNo(&MO));
658 : }
659 :
660 : bool isLiteralConstant(const MachineOperand &MO,
661 : const MCOperandInfo &OpInfo) const {
662 : return MO.isImm() && !isInlineConstant(MO, OpInfo.OperandType);
663 : }
664 :
665 : bool isLiteralConstant(const MachineInstr &MI, int OpIdx) const {
666 : const MachineOperand &MO = MI.getOperand(OpIdx);
667 : return MO.isImm() && !isInlineConstant(MI, OpIdx);
668 : }
669 :
670 : // Returns true if this operand could potentially require a 32-bit literal
671 : // operand, but not necessarily. A FrameIndex for example could resolve to an
672 : // inline immediate value that will not require an additional 4-bytes; this
673 : // assumes that it will.
674 : bool isLiteralConstantLike(const MachineOperand &MO,
675 : const MCOperandInfo &OpInfo) const;
676 :
677 : bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
678 : const MachineOperand &MO) const;
679 :
680 : /// Return true if this 64-bit VALU instruction has a 32-bit encoding.
681 : /// This function will return false if you pass it a 32-bit instruction.
682 : bool hasVALU32BitEncoding(unsigned Opcode) const;
683 :
684 : /// Returns true if this operand uses the constant bus.
685 : bool usesConstantBus(const MachineRegisterInfo &MRI,
686 : const MachineOperand &MO,
687 : const MCOperandInfo &OpInfo) const;
688 :
689 : /// Return true if this instruction has any modifiers.
690 : /// e.g. src[012]_mod, omod, clamp.
691 : bool hasModifiers(unsigned Opcode) const;
692 :
693 : bool hasModifiersSet(const MachineInstr &MI,
694 : unsigned OpName) const;
695 : bool hasAnyModifiersSet(const MachineInstr &MI) const;
696 :
697 : bool canShrink(const MachineInstr &MI,
698 : const MachineRegisterInfo &MRI) const;
699 :
700 : MachineInstr *buildShrunkInst(MachineInstr &MI,
701 : unsigned NewOpcode) const;
702 :
703 : bool verifyInstruction(const MachineInstr &MI,
704 : StringRef &ErrInfo) const override;
705 :
706 : unsigned getVALUOp(const MachineInstr &MI) const;
707 :
708 : /// Return the correct register class for \p OpNo. For target-specific
709 : /// instructions, this will return the register class that has been defined
710 : /// in tablegen. For generic instructions, like REG_SEQUENCE it will return
711 : /// the register class of its machine operand.
712 : /// to infer the correct register class base on the other operands.
713 : const TargetRegisterClass *getOpRegClass(const MachineInstr &MI,
714 : unsigned OpNo) const;
715 :
716 : /// Return the size in bytes of the operand OpNo on the given
717 : // instruction opcode.
718 : unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const {
719 : const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo];
720 :
721 : if (OpInfo.RegClass == -1) {
722 : // If this is an immediate operand, this must be a 32-bit literal.
723 : assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE);
724 : return 4;
725 : }
726 :
727 : return RI.getRegSizeInBits(*RI.getRegClass(OpInfo.RegClass)) / 8;
728 : }
729 :
730 : /// This form should usually be preferred since it handles operands
731 : /// with unknown register classes.
732 405871 : unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const {
733 405871 : const MachineOperand &MO = MI.getOperand(OpNo);
734 405871 : if (MO.isReg()) {
735 405871 : if (unsigned SubReg = MO.getSubReg()) {
736 : assert(RI.getRegSizeInBits(*RI.getSubClassWithSubReg(
737 : MI.getParent()->getParent()->getRegInfo().
738 : getRegClass(MO.getReg()), SubReg)) >= 32 &&
739 : "Sub-dword subregs are not supported");
740 306726 : return RI.getSubRegIndexLaneMask(SubReg).getNumLanes() * 4;
741 : }
742 : }
743 252508 : return RI.getRegSizeInBits(*getOpRegClass(MI, OpNo)) / 8;
744 : }
745 :
746 : /// \returns true if it is legal for the operand at index \p OpNo
747 : /// to read a VGPR.
748 : bool canReadVGPR(const MachineInstr &MI, unsigned OpNo) const;
749 :
750 : /// Legalize the \p OpIndex operand of this instruction by inserting
751 : /// a MOV. For example:
752 : /// ADD_I32_e32 VGPR0, 15
753 : /// to
754 : /// MOV VGPR1, 15
755 : /// ADD_I32_e32 VGPR0, VGPR1
756 : ///
757 : /// If the operand being legalized is a register, then a COPY will be used
758 : /// instead of MOV.
759 : void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const;
760 :
761 : /// Check if \p MO is a legal operand if it was the \p OpIdx Operand
762 : /// for \p MI.
763 : bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
764 : const MachineOperand *MO = nullptr) const;
765 :
766 : /// Check if \p MO would be a valid operand for the given operand
767 : /// definition \p OpInfo. Note this does not attempt to validate constant bus
768 : /// restrictions (e.g. literal constant usage).
769 : bool isLegalVSrcOperand(const MachineRegisterInfo &MRI,
770 : const MCOperandInfo &OpInfo,
771 : const MachineOperand &MO) const;
772 :
773 : /// Check if \p MO (a register operand) is a legal register for the
774 : /// given operand description.
775 : bool isLegalRegOperand(const MachineRegisterInfo &MRI,
776 : const MCOperandInfo &OpInfo,
777 : const MachineOperand &MO) const;
778 :
779 : /// Legalize operands in \p MI by either commuting it or inserting a
780 : /// copy of src1.
781 : void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const;
782 :
783 : /// Fix operands in \p MI to satisfy constant bus requirements.
784 : void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const;
785 :
786 : /// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only
787 : /// be used when it is know that the value in SrcReg is same across all
788 : /// threads in the wave.
789 : /// \returns The SGPR register that \p SrcReg was copied to.
790 : unsigned readlaneVGPRToSGPR(unsigned SrcReg, MachineInstr &UseMI,
791 : MachineRegisterInfo &MRI) const;
792 :
793 : void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const;
794 :
795 : void legalizeGenericOperand(MachineBasicBlock &InsertMBB,
796 : MachineBasicBlock::iterator I,
797 : const TargetRegisterClass *DstRC,
798 : MachineOperand &Op, MachineRegisterInfo &MRI,
799 : const DebugLoc &DL) const;
800 :
801 : /// Legalize all operands in this instruction. This function may create new
802 : /// instructions and control-flow around \p MI. If present, \p MDT is
803 : /// updated.
804 : void legalizeOperands(MachineInstr &MI,
805 : MachineDominatorTree *MDT = nullptr) const;
806 :
807 : /// Replace this instruction's opcode with the equivalent VALU
808 : /// opcode. This function will also move the users of \p MI to the
809 : /// VALU if necessary. If present, \p MDT is updated.
810 : void moveToVALU(MachineInstr &MI, MachineDominatorTree *MDT = nullptr) const;
811 :
812 : void insertWaitStates(MachineBasicBlock &MBB,MachineBasicBlock::iterator MI,
813 : int Count) const;
814 :
815 : void insertNoop(MachineBasicBlock &MBB,
816 : MachineBasicBlock::iterator MI) const override;
817 :
818 : void insertReturn(MachineBasicBlock &MBB) const;
819 : /// Return the number of wait states that result from executing this
820 : /// instruction.
821 : unsigned getNumWaitStates(const MachineInstr &MI) const;
822 :
823 : /// Returns the operand named \p Op. If \p MI does not have an
824 : /// operand named \c Op, this function returns nullptr.
825 : LLVM_READONLY
826 : MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const;
827 :
828 : LLVM_READONLY
829 : const MachineOperand *getNamedOperand(const MachineInstr &MI,
830 : unsigned OpName) const {
831 12025427 : return getNamedOperand(const_cast<MachineInstr &>(MI), OpName);
832 : }
833 :
834 : /// Get required immediate operand
835 0 : int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const {
836 11 : int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
837 36 : return MI.getOperand(Idx).getImm();
838 : }
839 :
840 : uint64_t getDefaultRsrcDataFormat() const;
841 : uint64_t getScratchRsrcWords23() const;
842 :
843 : bool isLowLatencyInstruction(const MachineInstr &MI) const;
844 : bool isHighLatencyInstruction(const MachineInstr &MI) const;
845 :
846 : /// Return the descriptor of the target-specific machine instruction
847 : /// that corresponds to the specified pseudo or native opcode.
848 : const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const {
849 734868 : return get(pseudoToMCOpcode(Opcode));
850 : }
851 :
852 : unsigned isStackAccess(const MachineInstr &MI, int &FrameIndex) const;
853 : unsigned isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex) const;
854 :
855 : unsigned isLoadFromStackSlot(const MachineInstr &MI,
856 : int &FrameIndex) const override;
857 : unsigned isStoreToStackSlot(const MachineInstr &MI,
858 : int &FrameIndex) const override;
859 :
860 : unsigned getInstBundleSize(const MachineInstr &MI) const;
861 : unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
862 :
863 : bool mayAccessFlatAddressSpace(const MachineInstr &MI) const;
864 :
865 : bool isNonUniformBranchInstr(MachineInstr &Instr) const;
866 :
867 : void convertNonUniformIfRegion(MachineBasicBlock *IfEntry,
868 : MachineBasicBlock *IfEnd) const;
869 :
870 : void convertNonUniformLoopRegion(MachineBasicBlock *LoopEntry,
871 : MachineBasicBlock *LoopEnd) const;
872 :
873 : std::pair<unsigned, unsigned>
874 : decomposeMachineOperandsTargetFlags(unsigned TF) const override;
875 :
876 : ArrayRef<std::pair<int, const char *>>
877 : getSerializableTargetIndices() const override;
878 :
879 : ArrayRef<std::pair<unsigned, const char *>>
880 : getSerializableDirectMachineOperandTargetFlags() const override;
881 :
882 : ScheduleHazardRecognizer *
883 : CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
884 : const ScheduleDAG *DAG) const override;
885 :
886 : ScheduleHazardRecognizer *
887 : CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override;
888 :
889 : bool isBasicBlockPrologue(const MachineInstr &MI) const override;
890 :
891 : /// Return a partially built integer add instruction without carry.
892 : /// Caller must add source operands.
893 : /// For pre-GFX9 it will generate unused carry destination operand.
894 : /// TODO: After GFX9 it should return a no-carry operation.
895 : MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB,
896 : MachineBasicBlock::iterator I,
897 : const DebugLoc &DL,
898 : unsigned DestReg) const;
899 :
900 : static bool isKillTerminator(unsigned Opcode);
901 : const MCInstrDesc &getKillTerminatorFromPseudo(unsigned Opcode) const;
902 :
903 : static bool isLegalMUBUFImmOffset(unsigned Imm) {
904 : return isUInt<12>(Imm);
905 : }
906 :
907 : /// \brief Return a target-specific opcode if Opcode is a pseudo instruction.
908 : /// Return -1 if the target-specific opcode for the pseudo instruction does
909 : /// not exist. If Opcode is not a pseudo instruction, this is identity.
910 : int pseudoToMCOpcode(int Opcode) const;
911 :
912 : };
913 :
914 : namespace AMDGPU {
915 :
916 : LLVM_READONLY
917 : int getVOPe64(uint16_t Opcode);
918 :
919 : LLVM_READONLY
920 : int getVOPe32(uint16_t Opcode);
921 :
922 : LLVM_READONLY
923 : int getSDWAOp(uint16_t Opcode);
924 :
925 : LLVM_READONLY
926 : int getBasicFromSDWAOp(uint16_t Opcode);
927 :
928 : LLVM_READONLY
929 : int getCommuteRev(uint16_t Opcode);
930 :
931 : LLVM_READONLY
932 : int getCommuteOrig(uint16_t Opcode);
933 :
934 : LLVM_READONLY
935 : int getAddr64Inst(uint16_t Opcode);
936 :
937 : /// Check if \p Opcode is an Addr64 opcode.
938 : ///
939 : /// \returns \p Opcode if it is an Addr64 opcode, otherwise -1.
940 : LLVM_READONLY
941 : int getIfAddr64Inst(uint16_t Opcode);
942 :
943 : LLVM_READONLY
944 : int getMUBUFNoLdsInst(uint16_t Opcode);
945 :
946 : LLVM_READONLY
947 : int getAtomicRetOp(uint16_t Opcode);
948 :
949 : LLVM_READONLY
950 : int getAtomicNoRetOp(uint16_t Opcode);
951 :
952 : LLVM_READONLY
953 : int getSOPKOp(uint16_t Opcode);
954 :
955 : const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL;
956 : const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19);
957 : const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21);
958 : const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23);
959 :
960 : // For MachineOperands.
961 : enum TargetFlags {
962 : TF_LONG_BRANCH_FORWARD = 1 << 0,
963 : TF_LONG_BRANCH_BACKWARD = 1 << 1
964 : };
965 :
966 : } // end namespace AMDGPU
967 :
968 : namespace SI {
969 : namespace KernelInputOffsets {
970 :
971 : /// Offsets in bytes from the start of the input buffer
972 : enum Offsets {
973 : NGROUPS_X = 0,
974 : NGROUPS_Y = 4,
975 : NGROUPS_Z = 8,
976 : GLOBAL_SIZE_X = 12,
977 : GLOBAL_SIZE_Y = 16,
978 : GLOBAL_SIZE_Z = 20,
979 : LOCAL_SIZE_X = 24,
980 : LOCAL_SIZE_Y = 28,
981 : LOCAL_SIZE_Z = 32
982 : };
983 :
984 : } // end namespace KernelInputOffsets
985 : } // end namespace SI
986 :
987 : } // end namespace llvm
988 :
989 : #endif // LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
|