1249259Sdim//===-- AMDGPUInstrInfo.cpp - Base class for AMD GPU InstrInfo ------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim/// \file
11249259Sdim/// \brief Implementation of the TargetInstrInfo class that is common to all
12249259Sdim/// AMD GPUs.
13249259Sdim//
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16249259Sdim#include "AMDGPUInstrInfo.h"
17249259Sdim#include "AMDGPURegisterInfo.h"
18249259Sdim#include "AMDGPUTargetMachine.h"
19249259Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
20249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
21249259Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22249259Sdim
23263509Sdim#define GET_INSTRINFO_CTOR_DTOR
24263509Sdim#define GET_INSTRINFO_NAMED_OPS
25249259Sdim#define GET_INSTRMAP_INFO
26249259Sdim#include "AMDGPUGenInstrInfo.inc"
27249259Sdim
28249259Sdimusing namespace llvm;
29249259Sdim
30263509Sdim
31263509Sdim// Pin the vtable to this file.
32263509Sdimvoid AMDGPUInstrInfo::anchor() {}
33263509Sdim
34249259SdimAMDGPUInstrInfo::AMDGPUInstrInfo(TargetMachine &tm)
35263509Sdim  : AMDGPUGenInstrInfo(-1,-1), RI(tm), TM(tm) { }
36249259Sdim
37249259Sdimconst AMDGPURegisterInfo &AMDGPUInstrInfo::getRegisterInfo() const {
38249259Sdim  return RI;
39249259Sdim}
40249259Sdim
41249259Sdimbool AMDGPUInstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
42249259Sdim                                           unsigned &SrcReg, unsigned &DstReg,
43249259Sdim                                           unsigned &SubIdx) const {
44249259Sdim// TODO: Implement this function
45249259Sdim  return false;
46249259Sdim}
47249259Sdim
48249259Sdimunsigned AMDGPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
49249259Sdim                                             int &FrameIndex) const {
50249259Sdim// TODO: Implement this function
51249259Sdim  return 0;
52249259Sdim}
53249259Sdim
54249259Sdimunsigned AMDGPUInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI,
55249259Sdim                                                   int &FrameIndex) const {
56249259Sdim// TODO: Implement this function
57249259Sdim  return 0;
58249259Sdim}
59249259Sdim
60249259Sdimbool AMDGPUInstrInfo::hasLoadFromStackSlot(const MachineInstr *MI,
61249259Sdim                                          const MachineMemOperand *&MMO,
62249259Sdim                                          int &FrameIndex) const {
63249259Sdim// TODO: Implement this function
64249259Sdim  return false;
65249259Sdim}
66249259Sdimunsigned AMDGPUInstrInfo::isStoreFromStackSlot(const MachineInstr *MI,
67249259Sdim                                              int &FrameIndex) const {
68249259Sdim// TODO: Implement this function
69249259Sdim  return 0;
70249259Sdim}
71249259Sdimunsigned AMDGPUInstrInfo::isStoreFromStackSlotPostFE(const MachineInstr *MI,
72249259Sdim                                                    int &FrameIndex) const {
73249259Sdim// TODO: Implement this function
74249259Sdim  return 0;
75249259Sdim}
76249259Sdimbool AMDGPUInstrInfo::hasStoreFromStackSlot(const MachineInstr *MI,
77249259Sdim                                           const MachineMemOperand *&MMO,
78249259Sdim                                           int &FrameIndex) const {
79249259Sdim// TODO: Implement this function
80249259Sdim  return false;
81249259Sdim}
82249259Sdim
83249259SdimMachineInstr *
84249259SdimAMDGPUInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
85249259Sdim                                      MachineBasicBlock::iterator &MBBI,
86249259Sdim                                      LiveVariables *LV) const {
87249259Sdim// TODO: Implement this function
88249259Sdim  return NULL;
89249259Sdim}
90249259Sdimbool AMDGPUInstrInfo::getNextBranchInstr(MachineBasicBlock::iterator &iter,
91249259Sdim                                        MachineBasicBlock &MBB) const {
92249259Sdim  while (iter != MBB.end()) {
93249259Sdim    switch (iter->getOpcode()) {
94249259Sdim    default:
95249259Sdim      break;
96249259Sdim    case AMDGPU::BRANCH_COND_i32:
97249259Sdim    case AMDGPU::BRANCH_COND_f32:
98249259Sdim    case AMDGPU::BRANCH:
99249259Sdim      return true;
100249259Sdim    };
101249259Sdim    ++iter;
102249259Sdim  }
103249259Sdim  return false;
104249259Sdim}
105249259Sdim
106249259Sdimvoid
107249259SdimAMDGPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
108249259Sdim                                    MachineBasicBlock::iterator MI,
109249259Sdim                                    unsigned SrcReg, bool isKill,
110249259Sdim                                    int FrameIndex,
111249259Sdim                                    const TargetRegisterClass *RC,
112249259Sdim                                    const TargetRegisterInfo *TRI) const {
113249259Sdim  assert(!"Not Implemented");
114249259Sdim}
115249259Sdim
116249259Sdimvoid
117249259SdimAMDGPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
118249259Sdim                                     MachineBasicBlock::iterator MI,
119249259Sdim                                     unsigned DestReg, int FrameIndex,
120249259Sdim                                     const TargetRegisterClass *RC,
121249259Sdim                                     const TargetRegisterInfo *TRI) const {
122249259Sdim  assert(!"Not Implemented");
123249259Sdim}
124249259Sdim
125263509Sdimbool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const {
126263509Sdim  MachineBasicBlock *MBB = MI->getParent();
127263509Sdim   int OffsetOpIdx =
128263509Sdim       AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::addr);
129263509Sdim   // addr is a custom operand with multiple MI operands, and only the
130263509Sdim   // first MI operand is given a name.
131263509Sdim  int RegOpIdx = OffsetOpIdx + 1;
132263509Sdim  int ChanOpIdx =
133263509Sdim      AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::chan);
134263509Sdim
135263509Sdim  if (isRegisterLoad(*MI)) {
136263509Sdim    int DstOpIdx =
137263509Sdim        AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst);
138263509Sdim    unsigned RegIndex = MI->getOperand(RegOpIdx).getImm();
139263509Sdim    unsigned Channel = MI->getOperand(ChanOpIdx).getImm();
140263509Sdim    unsigned Address = calculateIndirectAddress(RegIndex, Channel);
141263509Sdim    unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg();
142263509Sdim    if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) {
143263509Sdim      buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(),
144263509Sdim                    getIndirectAddrRegClass()->getRegister(Address));
145263509Sdim    } else {
146263509Sdim      buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(),
147263509Sdim                        Address, OffsetReg);
148263509Sdim    }
149263509Sdim  } else if (isRegisterStore(*MI)) {
150263509Sdim    int ValOpIdx =
151263509Sdim        AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::val);
152263509Sdim    AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst);
153263509Sdim    unsigned RegIndex = MI->getOperand(RegOpIdx).getImm();
154263509Sdim    unsigned Channel = MI->getOperand(ChanOpIdx).getImm();
155263509Sdim    unsigned Address = calculateIndirectAddress(RegIndex, Channel);
156263509Sdim    unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg();
157263509Sdim    if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) {
158263509Sdim      buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
159263509Sdim                    MI->getOperand(ValOpIdx).getReg());
160263509Sdim    } else {
161263509Sdim      buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(),
162263509Sdim                         calculateIndirectAddress(RegIndex, Channel),
163263509Sdim                         OffsetReg);
164263509Sdim    }
165263509Sdim  } else {
166263509Sdim    return false;
167263509Sdim  }
168263509Sdim
169263509Sdim  MBB->erase(MI);
170263509Sdim  return true;
171263509Sdim}
172263509Sdim
173263509Sdim
174249259SdimMachineInstr *
175249259SdimAMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
176249259Sdim                                      MachineInstr *MI,
177249259Sdim                                      const SmallVectorImpl<unsigned> &Ops,
178249259Sdim                                      int FrameIndex) const {
179249259Sdim// TODO: Implement this function
180249259Sdim  return 0;
181249259Sdim}
182249259SdimMachineInstr*
183249259SdimAMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
184249259Sdim                                      MachineInstr *MI,
185249259Sdim                                      const SmallVectorImpl<unsigned> &Ops,
186249259Sdim                                      MachineInstr *LoadMI) const {
187249259Sdim  // TODO: Implement this function
188249259Sdim  return 0;
189249259Sdim}
190249259Sdimbool
191249259SdimAMDGPUInstrInfo::canFoldMemoryOperand(const MachineInstr *MI,
192249259Sdim                                     const SmallVectorImpl<unsigned> &Ops) const {
193249259Sdim  // TODO: Implement this function
194249259Sdim  return false;
195249259Sdim}
196249259Sdimbool
197249259SdimAMDGPUInstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI,
198249259Sdim                                 unsigned Reg, bool UnfoldLoad,
199249259Sdim                                 bool UnfoldStore,
200249259Sdim                                 SmallVectorImpl<MachineInstr*> &NewMIs) const {
201249259Sdim  // TODO: Implement this function
202249259Sdim  return false;
203249259Sdim}
204249259Sdim
205249259Sdimbool
206249259SdimAMDGPUInstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
207249259Sdim                                    SmallVectorImpl<SDNode*> &NewNodes) const {
208249259Sdim  // TODO: Implement this function
209249259Sdim  return false;
210249259Sdim}
211249259Sdim
212249259Sdimunsigned
213249259SdimAMDGPUInstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc,
214249259Sdim                                           bool UnfoldLoad, bool UnfoldStore,
215249259Sdim                                           unsigned *LoadRegIndex) const {
216249259Sdim  // TODO: Implement this function
217249259Sdim  return 0;
218249259Sdim}
219249259Sdim
220249259Sdimbool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2,
221249259Sdim                                             int64_t Offset1, int64_t Offset2,
222249259Sdim                                             unsigned NumLoads) const {
223249259Sdim  assert(Offset2 > Offset1
224249259Sdim         && "Second offset should be larger than first offset!");
225249259Sdim  // If we have less than 16 loads in a row, and the offsets are within 16,
226249259Sdim  // then schedule together.
227249259Sdim  // TODO: Make the loads schedule near if it fits in a cacheline
228249259Sdim  return (NumLoads < 16 && (Offset2 - Offset1) < 16);
229249259Sdim}
230249259Sdim
231249259Sdimbool
232249259SdimAMDGPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond)
233249259Sdim  const {
234249259Sdim  // TODO: Implement this function
235249259Sdim  return true;
236249259Sdim}
237249259Sdimvoid AMDGPUInstrInfo::insertNoop(MachineBasicBlock &MBB,
238249259Sdim                                MachineBasicBlock::iterator MI) const {
239249259Sdim  // TODO: Implement this function
240249259Sdim}
241249259Sdim
242249259Sdimbool AMDGPUInstrInfo::isPredicated(const MachineInstr *MI) const {
243249259Sdim  // TODO: Implement this function
244249259Sdim  return false;
245249259Sdim}
246249259Sdimbool
247249259SdimAMDGPUInstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
248249259Sdim                                  const SmallVectorImpl<MachineOperand> &Pred2)
249249259Sdim  const {
250249259Sdim  // TODO: Implement this function
251249259Sdim  return false;
252249259Sdim}
253249259Sdim
254249259Sdimbool AMDGPUInstrInfo::DefinesPredicate(MachineInstr *MI,
255249259Sdim                                      std::vector<MachineOperand> &Pred) const {
256249259Sdim  // TODO: Implement this function
257249259Sdim  return false;
258249259Sdim}
259249259Sdim
260249259Sdimbool AMDGPUInstrInfo::isPredicable(MachineInstr *MI) const {
261249259Sdim  // TODO: Implement this function
262249259Sdim  return MI->getDesc().isPredicable();
263249259Sdim}
264249259Sdim
265249259Sdimbool
266249259SdimAMDGPUInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
267249259Sdim  // TODO: Implement this function
268249259Sdim  return true;
269249259Sdim}
270249259Sdim
271249259Sdimbool AMDGPUInstrInfo::isRegisterStore(const MachineInstr &MI) const {
272249259Sdim  return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_STORE;
273249259Sdim}
274249259Sdim
275249259Sdimbool AMDGPUInstrInfo::isRegisterLoad(const MachineInstr &MI) const {
276249259Sdim  return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_LOAD;
277249259Sdim}
278249259Sdim
279263509Sdimint AMDGPUInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
280263509Sdim  const MachineRegisterInfo &MRI = MF.getRegInfo();
281263509Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
282263509Sdim  int Offset = -1;
283249259Sdim
284263509Sdim  if (MFI->getNumObjects() == 0) {
285263509Sdim    return -1;
286263509Sdim  }
287263509Sdim
288263509Sdim  if (MRI.livein_empty()) {
289263509Sdim    return 0;
290263509Sdim  }
291263509Sdim
292263509Sdim  const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
293263509Sdim  for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
294263509Sdim                                            LE = MRI.livein_end();
295263509Sdim                                            LI != LE; ++LI) {
296263509Sdim    unsigned Reg = LI->first;
297263509Sdim    if (TargetRegisterInfo::isVirtualRegister(Reg) ||
298263509Sdim        !IndirectRC->contains(Reg))
299263509Sdim      continue;
300263509Sdim
301263509Sdim    unsigned RegIndex;
302263509Sdim    unsigned RegEnd;
303263509Sdim    for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
304263509Sdim                                                          ++RegIndex) {
305263509Sdim      if (IndirectRC->getRegister(RegIndex) == Reg)
306263509Sdim        break;
307263509Sdim    }
308263509Sdim    Offset = std::max(Offset, (int)RegIndex);
309263509Sdim  }
310263509Sdim
311263509Sdim  return Offset + 1;
312263509Sdim}
313263509Sdim
314263509Sdimint AMDGPUInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
315263509Sdim  int Offset = 0;
316263509Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
317263509Sdim
318263509Sdim  // Variable sized objects are not supported
319263509Sdim  assert(!MFI->hasVarSizedObjects());
320263509Sdim
321263509Sdim  if (MFI->getNumObjects() == 0) {
322263509Sdim    return -1;
323263509Sdim  }
324263509Sdim
325263509Sdim  Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1);
326263509Sdim
327263509Sdim  return getIndirectIndexBegin(MF) + Offset;
328263509Sdim}
329263509Sdim
330263509Sdim
331249259Sdimvoid AMDGPUInstrInfo::convertToISA(MachineInstr & MI, MachineFunction &MF,
332249259Sdim    DebugLoc DL) const {
333249259Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
334249259Sdim  const AMDGPURegisterInfo & RI = getRegisterInfo();
335249259Sdim
336249259Sdim  for (unsigned i = 0; i < MI.getNumOperands(); i++) {
337249259Sdim    MachineOperand &MO = MI.getOperand(i);
338249259Sdim    // Convert dst regclass to one that is supported by the ISA
339249259Sdim    if (MO.isReg() && MO.isDef()) {
340249259Sdim      if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
341249259Sdim        const TargetRegisterClass * oldRegClass = MRI.getRegClass(MO.getReg());
342249259Sdim        const TargetRegisterClass * newRegClass = RI.getISARegClass(oldRegClass);
343249259Sdim
344249259Sdim        assert(newRegClass);
345249259Sdim
346249259Sdim        MRI.setRegClass(MO.getReg(), newRegClass);
347249259Sdim      }
348249259Sdim    }
349249259Sdim  }
350249259Sdim}
351263509Sdim
352263509Sdimint AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const {
353263509Sdim  switch (Channels) {
354263509Sdim  default: return Opcode;
355263509Sdim  case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1);
356263509Sdim  case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2);
357263509Sdim  case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3);
358263509Sdim  }
359263509Sdim}
360