LLVM  3.7.0
AMDGPUInstrInfo.cpp
Go to the documentation of this file.
1 //===-- AMDGPUInstrInfo.cpp - Base class for AMD GPU InstrInfo ------------===//
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 /// \brief Implementation of the TargetInstrInfo class that is common to all
12 /// AMD GPUs.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "AMDGPUInstrInfo.h"
17 #include "AMDGPURegisterInfo.h"
18 #include "AMDGPUTargetMachine.h"
22 
23 using namespace llvm;
24 
25 #define GET_INSTRINFO_CTOR_DTOR
26 #define GET_INSTRINFO_NAMED_OPS
27 #define GET_INSTRMAP_INFO
28 #include "AMDGPUGenInstrInfo.inc"
29 
30 // Pin the vtable to this file.
31 void AMDGPUInstrInfo::anchor() {}
32 
34  : AMDGPUGenInstrInfo(-1, -1), ST(st) {}
35 
37  return RI;
38 }
39 
41  unsigned &SrcReg, unsigned &DstReg,
42  unsigned &SubIdx) const {
43 // TODO: Implement this function
44  return false;
45 }
46 
48  int &FrameIndex) const {
49 // TODO: Implement this function
50  return 0;
51 }
52 
54  int &FrameIndex) const {
55 // TODO: Implement this function
56  return 0;
57 }
58 
60  const MachineMemOperand *&MMO,
61  int &FrameIndex) const {
62 // TODO: Implement this function
63  return false;
64 }
66  int &FrameIndex) const {
67 // TODO: Implement this function
68  return 0;
69 }
71  int &FrameIndex) const {
72 // TODO: Implement this function
73  return 0;
74 }
76  const MachineMemOperand *&MMO,
77  int &FrameIndex) const {
78 // TODO: Implement this function
79  return false;
80 }
81 
85  LiveVariables *LV) const {
86 // TODO: Implement this function
87  return nullptr;
88 }
89 
90 void
93  unsigned SrcReg, bool isKill,
94  int FrameIndex,
95  const TargetRegisterClass *RC,
96  const TargetRegisterInfo *TRI) const {
97  llvm_unreachable("Not Implemented");
98 }
99 
100 void
103  unsigned DestReg, int FrameIndex,
104  const TargetRegisterClass *RC,
105  const TargetRegisterInfo *TRI) const {
106  llvm_unreachable("Not Implemented");
107 }
108 
110  MachineBasicBlock *MBB = MI->getParent();
111  int OffsetOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
113  // addr is a custom operand with multiple MI operands, and only the
114  // first MI operand is given a name.
115  int RegOpIdx = OffsetOpIdx + 1;
116  int ChanOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
117  AMDGPU::OpName::chan);
118  if (isRegisterLoad(*MI)) {
119  int DstOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
120  AMDGPU::OpName::dst);
121  unsigned RegIndex = MI->getOperand(RegOpIdx).getImm();
122  unsigned Channel = MI->getOperand(ChanOpIdx).getImm();
123  unsigned Address = calculateIndirectAddress(RegIndex, Channel);
124  unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg();
125  if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) {
126  buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(),
128  } else {
129  buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(),
130  Address, OffsetReg);
131  }
132  } else if (isRegisterStore(*MI)) {
133  int ValOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
134  AMDGPU::OpName::val);
135  unsigned RegIndex = MI->getOperand(RegOpIdx).getImm();
136  unsigned Channel = MI->getOperand(ChanOpIdx).getImm();
137  unsigned Address = calculateIndirectAddress(RegIndex, Channel);
138  unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg();
139  if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) {
140  buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
141  MI->getOperand(ValOpIdx).getReg());
142  } else {
143  buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(),
144  calculateIndirectAddress(RegIndex, Channel),
145  OffsetReg);
146  }
147  } else {
148  return false;
149  }
150 
151  MBB->erase(MI);
152  return true;
153 }
154 
157  MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
158 // TODO: Implement this function
159  return nullptr;
160 }
163  MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
164  // TODO: Implement this function
165  return nullptr;
166 }
168  ArrayRef<unsigned> Ops) const {
169  // TODO: Implement this function
170  return false;
171 }
172 bool
174  unsigned Reg, bool UnfoldLoad,
175  bool UnfoldStore,
176  SmallVectorImpl<MachineInstr*> &NewMIs) const {
177  // TODO: Implement this function
178  return false;
179 }
180 
181 bool
183  SmallVectorImpl<SDNode*> &NewNodes) const {
184  // TODO: Implement this function
185  return false;
186 }
187 
188 unsigned
190  bool UnfoldLoad, bool UnfoldStore,
191  unsigned *LoadRegIndex) const {
192  // TODO: Implement this function
193  return 0;
194 }
195 
197  return true;
198 }
199 
200 // FIXME: This behaves strangely. If, for example, you have 32 load + stores,
201 // the first 16 loads will be interleaved with the stores, and the next 16 will
202 // be clustered as expected. It should really split into 2 16 store batches.
203 //
204 // Loads are clustered until this returns false, rather than trying to schedule
205 // groups of stores. This also means we have to deal with saying different
206 // address space loads should be clustered, and ones which might cause bank
207 // conflicts.
208 //
209 // This might be deprecated so it might not be worth that much effort to fix.
211  int64_t Offset0, int64_t Offset1,
212  unsigned NumLoads) const {
213  assert(Offset1 > Offset0 &&
214  "Second offset should be larger than first offset!");
215  // If we have less than 16 loads in a row, and the offsets are within 64
216  // bytes, then schedule together.
217 
218  // A cacheline is 64 bytes (for global memory).
219  return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
220 }
221 
222 bool
224  const {
225  // TODO: Implement this function
226  return true;
227 }
230  // TODO: Implement this function
231 }
232 
234  // TODO: Implement this function
235  return false;
236 }
237 
239  ArrayRef<MachineOperand> Pred2) const {
240  // TODO: Implement this function
241  return false;
242 }
243 
245  std::vector<MachineOperand> &Pred) const {
246  // TODO: Implement this function
247  return false;
248 }
249 
251  // TODO: Implement this function
252  return MI->getDesc().isPredicable();
253 }
254 
255 bool
257  // TODO: Implement this function
258  return true;
259 }
260 
262  return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_STORE;
263 }
264 
266  return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_LOAD;
267 }
268 
270  const MachineRegisterInfo &MRI = MF.getRegInfo();
271  const MachineFrameInfo *MFI = MF.getFrameInfo();
272  int Offset = -1;
273 
274  if (MFI->getNumObjects() == 0) {
275  return -1;
276  }
277 
278  if (MRI.livein_empty()) {
279  return 0;
280  }
281 
282  const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
284  LE = MRI.livein_end();
285  LI != LE; ++LI) {
286  unsigned Reg = LI->first;
288  !IndirectRC->contains(Reg))
289  continue;
290 
291  unsigned RegIndex;
292  unsigned RegEnd;
293  for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
294  ++RegIndex) {
295  if (IndirectRC->getRegister(RegIndex) == Reg)
296  break;
297  }
298  Offset = std::max(Offset, (int)RegIndex);
299  }
300 
301  return Offset + 1;
302 }
303 
305  int Offset = 0;
306  const MachineFrameInfo *MFI = MF.getFrameInfo();
307 
308  // Variable sized objects are not supported
309  assert(!MFI->hasVarSizedObjects());
310 
311  if (MFI->getNumObjects() == 0) {
312  return -1;
313  }
314 
315  Offset = MF.getSubtarget().getFrameLowering()->getFrameIndexOffset(MF, -1);
316 
317  return getIndirectIndexBegin(MF) + Offset;
318 }
319 
320 int AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const {
321  switch (Channels) {
322  default: return Opcode;
323  case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1);
324  case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2);
325  case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3);
326  }
327 }
328 
329 // Wrapper for Tablegen'd function. enum Subtarget is not defined in any
330 // header files, so we need to wrap it in a function that takes unsigned
331 // instead.
332 namespace llvm {
333 namespace AMDGPU {
334 static int getMCOpcode(uint16_t Opcode, unsigned Gen) {
335  return getMCOpcodeGen(Opcode, (enum Subtarget)Gen);
336 }
337 }
338 }
339 
340 // This must be kept in sync with the SISubtarget class in SIInstrInfo.td
342  SI = 0,
343  VI = 1
344 };
345 
346 static enum SISubtarget AMDGPUSubtargetToSISubtarget(unsigned Gen) {
347  switch (Gen) {
348  default:
349  return SI;
351  return VI;
352  }
353 }
354 
355 int AMDGPUInstrInfo::pseudoToMCOpcode(int Opcode) const {
356  int MCOp = AMDGPU::getMCOpcode(
358 
359  // -1 means that Opcode is already a native instruction.
360  if (MCOp == -1)
361  return Opcode;
362 
363  // (uint16_t)-1 means that Opcode is a pseudo instruction that has
364  // no encoding in the given subtarget generation.
365  if (MCOp == (uint16_t)-1)
366  return -1;
367 
368  return MCOp;
369 }
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
int getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const
Given a MIMG Opcode that writes all 4 channels, return the equivalent opcode that writes Channels Cha...
bool isCoalescableExtInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg, unsigned &SubIdx) const override
unsigned getRegister(unsigned i) const
getRegister - Return the specified register in the class.
livein_iterator livein_end() const
#define AMDGPU_FLAG_REGISTER_STORE
unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const override
static bool isVirtualRegister(unsigned Reg)
isVirtualRegister - Return true if the specified register number is in the virtual register namespace...
#define AMDGPU_FLAG_REGISTER_LOAD
bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1, int64_t Offset2, unsigned NumLoads) const override
unsigned getNumObjects() const
Return the number of objects.
AMDGPUInstrInfo(const AMDGPUSubtarget &st)
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:264
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
bool DefinesPredicate(MachineInstr *MI, std::vector< MachineOperand > &Pred) const override
bool hasStoreFromStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, int &FrameIndex) const
bool ReverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
MachineMemOperand - A description of a memory reference used in the backend.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const AMDGPUSubtarget & ST
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
bool isPredicated(const MachineInstr *MI) const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
virtual const AMDGPURegisterInfo & getRegisterInfo() const =0
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APInt.h:33
Reg
All possible values of the reg field in the ModR/M byte.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
static int getMCOpcode(uint16_t Opcode, unsigned Gen)
unsigned getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore, unsigned *LoadRegIndex=nullptr) const override
unsigned isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const override
bool isPredicable() const
Return true if this instruction has a predicate operand that controls execution.
Definition: MCInstrDesc.h:264
TargetRegisterInfo interface that is implemented by all hw codegen targets.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
bool canFoldMemoryOperand(const MachineInstr *MI, ArrayRef< unsigned > Ops) const override
Generation getGeneration() const
MachineInstr * convertToThreeAddress(MachineFunction::iterator &MFI, MachineBasicBlock::iterator &MBBI, LiveVariables *LV) const override
static enum SISubtarget AMDGPUSubtargetToSISubtarget(unsigned Gen)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
virtual unsigned calculateIndirectAddress(unsigned RegIndex, unsigned Channel) const =0
Calculate the "Indirect Address" for the given RegIndex and Channel.
bundle_iterator< MachineInstr, instr_iterator > iterator
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, ArrayRef< unsigned > Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex) const override
bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const override
virtual MachineInstrBuilder buildIndirectWrite(MachineBasicBlock *MBB, MachineBasicBlock::iterator I, unsigned ValueReg, unsigned Address, unsigned OffsetReg) const =0
Build instruction(s) for an indirect register write.
bool hasLoadFromStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, int &FrameIndex) const override
bool isRegisterLoad(const MachineInstr &MI) const
bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override
bool isPredicable(MachineInstr *MI) const override
bool enableClusterLoads() const override
virtual const TargetRegisterClass * getIndirectAddrRegClass() const =0
virtual MachineInstr * buildMovInstr(MachineBasicBlock *MBB, MachineBasicBlock::iterator I, unsigned DstReg, unsigned SrcReg) const =0
Build a MOV instruction.
The AMDGPU TargetMachine interface definition for hw codgen targets.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, unsigned Reg, bool UnfoldLoad, bool UnfoldStore, SmallVectorImpl< MachineInstr * > &NewMIs) const override
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const
getFrameIndexOffset - Returns the displacement from the frame register to the stack frame of the spec...
bool SubsumesPredicate(ArrayRef< MachineOperand > Pred1, ArrayRef< MachineOperand > Pred2) const override
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:179
unsigned isStoreFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
livein_iterator livein_begin() const
MachineFrameInfo * getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Represents one node in the SelectionDAG.
unsigned isStoreFromStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
int getIndirectIndexEnd(const MachineFunction &MF) const
SISubtarget
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:51
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
#define N
bool isRegisterStore(const MachineInstr &MI) const
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
std::vector< std::pair< unsigned, unsigned > >::const_iterator livein_iterator
int getIndirectIndexBegin(const MachineFunction &MF) const
BasicBlockListType::iterator iterator
int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex)
virtual MachineInstrBuilder buildIndirectRead(MachineBasicBlock *MBB, MachineBasicBlock::iterator I, unsigned ValueReg, unsigned Address, unsigned OffsetReg) const =0
Build instruction(s) for an indirect register read.
void * addr
bool contains(unsigned Reg) const
contains - Return true if the specified register is included in this register class.