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"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/MachineRegisterInfo.h"
22
23using 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.
31void AMDGPUInstrInfo::anchor() {}
32
33AMDGPUInstrInfo::AMDGPUInstrInfo(const AMDGPUSubtarget &st)
34  : AMDGPUGenInstrInfo(-1,-1), RI(st), ST(st) { }
35
36const AMDGPURegisterInfo &AMDGPUInstrInfo::getRegisterInfo() const {
37  return RI;
38}
39
40bool AMDGPUInstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
41                                           unsigned &SrcReg, unsigned &DstReg,
42                                           unsigned &SubIdx) const {
43// TODO: Implement this function
44  return false;
45}
46
47unsigned AMDGPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
48                                             int &FrameIndex) const {
49// TODO: Implement this function
50  return 0;
51}
52
53unsigned AMDGPUInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI,
54                                                   int &FrameIndex) const {
55// TODO: Implement this function
56  return 0;
57}
58
59bool AMDGPUInstrInfo::hasLoadFromStackSlot(const MachineInstr *MI,
60                                          const MachineMemOperand *&MMO,
61                                          int &FrameIndex) const {
62// TODO: Implement this function
63  return false;
64}
65unsigned AMDGPUInstrInfo::isStoreFromStackSlot(const MachineInstr *MI,
66                                              int &FrameIndex) const {
67// TODO: Implement this function
68  return 0;
69}
70unsigned AMDGPUInstrInfo::isStoreFromStackSlotPostFE(const MachineInstr *MI,
71                                                    int &FrameIndex) const {
72// TODO: Implement this function
73  return 0;
74}
75bool AMDGPUInstrInfo::hasStoreFromStackSlot(const MachineInstr *MI,
76                                           const MachineMemOperand *&MMO,
77                                           int &FrameIndex) const {
78// TODO: Implement this function
79  return false;
80}
81
82MachineInstr *
83AMDGPUInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
84                                      MachineBasicBlock::iterator &MBBI,
85                                      LiveVariables *LV) const {
86// TODO: Implement this function
87  return nullptr;
88}
89bool AMDGPUInstrInfo::getNextBranchInstr(MachineBasicBlock::iterator &iter,
90                                        MachineBasicBlock &MBB) const {
91  while (iter != MBB.end()) {
92    switch (iter->getOpcode()) {
93    default:
94      break;
95    case AMDGPU::BRANCH_COND_i32:
96    case AMDGPU::BRANCH_COND_f32:
97    case AMDGPU::BRANCH:
98      return true;
99    };
100    ++iter;
101  }
102  return false;
103}
104
105void
106AMDGPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
107                                    MachineBasicBlock::iterator MI,
108                                    unsigned SrcReg, bool isKill,
109                                    int FrameIndex,
110                                    const TargetRegisterClass *RC,
111                                    const TargetRegisterInfo *TRI) const {
112  llvm_unreachable("Not Implemented");
113}
114
115void
116AMDGPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
117                                     MachineBasicBlock::iterator MI,
118                                     unsigned DestReg, int FrameIndex,
119                                     const TargetRegisterClass *RC,
120                                     const TargetRegisterInfo *TRI) const {
121  llvm_unreachable("Not Implemented");
122}
123
124bool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const {
125  MachineBasicBlock *MBB = MI->getParent();
126  int OffsetOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
127                                               AMDGPU::OpName::addr);
128   // addr is a custom operand with multiple MI operands, and only the
129   // first MI operand is given a name.
130  int RegOpIdx = OffsetOpIdx + 1;
131  int ChanOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
132                                             AMDGPU::OpName::chan);
133  if (isRegisterLoad(*MI)) {
134    int DstOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
135                                              AMDGPU::OpName::dst);
136    unsigned RegIndex = MI->getOperand(RegOpIdx).getImm();
137    unsigned Channel = MI->getOperand(ChanOpIdx).getImm();
138    unsigned Address = calculateIndirectAddress(RegIndex, Channel);
139    unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg();
140    if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) {
141      buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(),
142                    getIndirectAddrRegClass()->getRegister(Address));
143    } else {
144      buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(),
145                        Address, OffsetReg);
146    }
147  } else if (isRegisterStore(*MI)) {
148    int ValOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
149                                              AMDGPU::OpName::val);
150    AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst);
151    unsigned RegIndex = MI->getOperand(RegOpIdx).getImm();
152    unsigned Channel = MI->getOperand(ChanOpIdx).getImm();
153    unsigned Address = calculateIndirectAddress(RegIndex, Channel);
154    unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg();
155    if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) {
156      buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
157                    MI->getOperand(ValOpIdx).getReg());
158    } else {
159      buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(),
160                         calculateIndirectAddress(RegIndex, Channel),
161                         OffsetReg);
162    }
163  } else {
164    return false;
165  }
166
167  MBB->erase(MI);
168  return true;
169}
170
171
172MachineInstr *
173AMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
174                                      MachineInstr *MI,
175                                      const SmallVectorImpl<unsigned> &Ops,
176                                      int FrameIndex) const {
177// TODO: Implement this function
178  return nullptr;
179}
180MachineInstr*
181AMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
182                                      MachineInstr *MI,
183                                      const SmallVectorImpl<unsigned> &Ops,
184                                      MachineInstr *LoadMI) const {
185  // TODO: Implement this function
186  return nullptr;
187}
188bool
189AMDGPUInstrInfo::canFoldMemoryOperand(const MachineInstr *MI,
190                                     const SmallVectorImpl<unsigned> &Ops) const {
191  // TODO: Implement this function
192  return false;
193}
194bool
195AMDGPUInstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI,
196                                 unsigned Reg, bool UnfoldLoad,
197                                 bool UnfoldStore,
198                                 SmallVectorImpl<MachineInstr*> &NewMIs) const {
199  // TODO: Implement this function
200  return false;
201}
202
203bool
204AMDGPUInstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
205                                    SmallVectorImpl<SDNode*> &NewNodes) const {
206  // TODO: Implement this function
207  return false;
208}
209
210unsigned
211AMDGPUInstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc,
212                                           bool UnfoldLoad, bool UnfoldStore,
213                                           unsigned *LoadRegIndex) const {
214  // TODO: Implement this function
215  return 0;
216}
217
218bool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2,
219                                             int64_t Offset1, int64_t Offset2,
220                                             unsigned NumLoads) const {
221  assert(Offset2 > Offset1
222         && "Second offset should be larger than first offset!");
223  // If we have less than 16 loads in a row, and the offsets are within 16,
224  // then schedule together.
225  // TODO: Make the loads schedule near if it fits in a cacheline
226  return (NumLoads < 16 && (Offset2 - Offset1) < 16);
227}
228
229bool
230AMDGPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond)
231  const {
232  // TODO: Implement this function
233  return true;
234}
235void AMDGPUInstrInfo::insertNoop(MachineBasicBlock &MBB,
236                                MachineBasicBlock::iterator MI) const {
237  // TODO: Implement this function
238}
239
240bool AMDGPUInstrInfo::isPredicated(const MachineInstr *MI) const {
241  // TODO: Implement this function
242  return false;
243}
244bool
245AMDGPUInstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
246                                  const SmallVectorImpl<MachineOperand> &Pred2)
247  const {
248  // TODO: Implement this function
249  return false;
250}
251
252bool AMDGPUInstrInfo::DefinesPredicate(MachineInstr *MI,
253                                      std::vector<MachineOperand> &Pred) const {
254  // TODO: Implement this function
255  return false;
256}
257
258bool AMDGPUInstrInfo::isPredicable(MachineInstr *MI) const {
259  // TODO: Implement this function
260  return MI->getDesc().isPredicable();
261}
262
263bool
264AMDGPUInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
265  // TODO: Implement this function
266  return true;
267}
268
269bool AMDGPUInstrInfo::isRegisterStore(const MachineInstr &MI) const {
270  return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_STORE;
271}
272
273bool AMDGPUInstrInfo::isRegisterLoad(const MachineInstr &MI) const {
274  return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_LOAD;
275}
276
277int AMDGPUInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
278  const MachineRegisterInfo &MRI = MF.getRegInfo();
279  const MachineFrameInfo *MFI = MF.getFrameInfo();
280  int Offset = -1;
281
282  if (MFI->getNumObjects() == 0) {
283    return -1;
284  }
285
286  if (MRI.livein_empty()) {
287    return 0;
288  }
289
290  const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
291  for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
292                                            LE = MRI.livein_end();
293                                            LI != LE; ++LI) {
294    unsigned Reg = LI->first;
295    if (TargetRegisterInfo::isVirtualRegister(Reg) ||
296        !IndirectRC->contains(Reg))
297      continue;
298
299    unsigned RegIndex;
300    unsigned RegEnd;
301    for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
302                                                          ++RegIndex) {
303      if (IndirectRC->getRegister(RegIndex) == Reg)
304        break;
305    }
306    Offset = std::max(Offset, (int)RegIndex);
307  }
308
309  return Offset + 1;
310}
311
312int AMDGPUInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
313  int Offset = 0;
314  const MachineFrameInfo *MFI = MF.getFrameInfo();
315
316  // Variable sized objects are not supported
317  assert(!MFI->hasVarSizedObjects());
318
319  if (MFI->getNumObjects() == 0) {
320    return -1;
321  }
322
323  Offset = MF.getTarget().getFrameLowering()->getFrameIndexOffset(MF, -1);
324
325  return getIndirectIndexBegin(MF) + Offset;
326}
327
328int AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const {
329  switch (Channels) {
330  default: return Opcode;
331  case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1);
332  case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2);
333  case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3);
334  }
335}
336
337// Wrapper for Tablegen'd function.  enum Subtarget is not defined in any
338// header files, so we need to wrap it in a function that takes unsigned
339// instead.
340namespace llvm {
341namespace AMDGPU {
342int getMCOpcode(uint16_t Opcode, unsigned Gen) {
343  return getMCOpcode(Opcode);
344}
345}
346}
347