1//===-- SIInstrInfo.cpp - SI Instruction Information  ---------------------===//
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 SI Implementation of TargetInstrInfo.
12//
13//===----------------------------------------------------------------------===//
14
15
16#include "SIInstrInfo.h"
17#include "AMDGPUTargetMachine.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
20#include "llvm/MC/MCInstrDesc.h"
21#include <stdio.h>
22
23using namespace llvm;
24
25SIInstrInfo::SIInstrInfo(AMDGPUTargetMachine &tm)
26  : AMDGPUInstrInfo(tm),
27    RI(tm, *this)
28    { }
29
30const SIRegisterInfo &SIInstrInfo::getRegisterInfo() const {
31  return RI;
32}
33
34void
35SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
36                         MachineBasicBlock::iterator MI, DebugLoc DL,
37                         unsigned DestReg, unsigned SrcReg,
38                         bool KillSrc) const {
39
40  // If we are trying to copy to or from SCC, there is a bug somewhere else in
41  // the backend.  While it may be theoretically possible to do this, it should
42  // never be necessary.
43  assert(DestReg != AMDGPU::SCC && SrcReg != AMDGPU::SCC);
44
45  const int16_t Sub0_15[] = {
46    AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
47    AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
48    AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
49    AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15, 0
50  };
51
52  const int16_t Sub0_7[] = {
53    AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
54    AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7, 0
55  };
56
57  const int16_t Sub0_3[] = {
58    AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 0
59  };
60
61  const int16_t Sub0_2[] = {
62    AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, 0
63  };
64
65  const int16_t Sub0_1[] = {
66    AMDGPU::sub0, AMDGPU::sub1, 0
67  };
68
69  unsigned Opcode;
70  const int16_t *SubIndices;
71
72  if (AMDGPU::M0 == DestReg) {
73    // Check if M0 isn't already set to this value
74    for (MachineBasicBlock::reverse_iterator E = MBB.rend(),
75      I = MachineBasicBlock::reverse_iterator(MI); I != E; ++I) {
76
77      if (!I->definesRegister(AMDGPU::M0))
78        continue;
79
80      unsigned Opc = I->getOpcode();
81      if (Opc != TargetOpcode::COPY && Opc != AMDGPU::S_MOV_B32)
82        break;
83
84      if (!I->readsRegister(SrcReg))
85        break;
86
87      // The copy isn't necessary
88      return;
89    }
90  }
91
92  if (AMDGPU::SReg_32RegClass.contains(DestReg)) {
93    assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
94    BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
95            .addReg(SrcReg, getKillRegState(KillSrc));
96    return;
97
98  } else if (AMDGPU::SReg_64RegClass.contains(DestReg)) {
99    assert(AMDGPU::SReg_64RegClass.contains(SrcReg));
100    BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
101            .addReg(SrcReg, getKillRegState(KillSrc));
102    return;
103
104  } else if (AMDGPU::SReg_128RegClass.contains(DestReg)) {
105    assert(AMDGPU::SReg_128RegClass.contains(SrcReg));
106    Opcode = AMDGPU::S_MOV_B32;
107    SubIndices = Sub0_3;
108
109  } else if (AMDGPU::SReg_256RegClass.contains(DestReg)) {
110    assert(AMDGPU::SReg_256RegClass.contains(SrcReg));
111    Opcode = AMDGPU::S_MOV_B32;
112    SubIndices = Sub0_7;
113
114  } else if (AMDGPU::SReg_512RegClass.contains(DestReg)) {
115    assert(AMDGPU::SReg_512RegClass.contains(SrcReg));
116    Opcode = AMDGPU::S_MOV_B32;
117    SubIndices = Sub0_15;
118
119  } else if (AMDGPU::VReg_32RegClass.contains(DestReg)) {
120    assert(AMDGPU::VReg_32RegClass.contains(SrcReg) ||
121	   AMDGPU::SReg_32RegClass.contains(SrcReg));
122    BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DestReg)
123            .addReg(SrcReg, getKillRegState(KillSrc));
124    return;
125
126  } else if (AMDGPU::VReg_64RegClass.contains(DestReg)) {
127    assert(AMDGPU::VReg_64RegClass.contains(SrcReg) ||
128	   AMDGPU::SReg_64RegClass.contains(SrcReg));
129    Opcode = AMDGPU::V_MOV_B32_e32;
130    SubIndices = Sub0_1;
131
132  } else if (AMDGPU::VReg_96RegClass.contains(DestReg)) {
133    assert(AMDGPU::VReg_96RegClass.contains(SrcReg));
134    Opcode = AMDGPU::V_MOV_B32_e32;
135    SubIndices = Sub0_2;
136
137  } else if (AMDGPU::VReg_128RegClass.contains(DestReg)) {
138    assert(AMDGPU::VReg_128RegClass.contains(SrcReg) ||
139	   AMDGPU::SReg_128RegClass.contains(SrcReg));
140    Opcode = AMDGPU::V_MOV_B32_e32;
141    SubIndices = Sub0_3;
142
143  } else if (AMDGPU::VReg_256RegClass.contains(DestReg)) {
144    assert(AMDGPU::VReg_256RegClass.contains(SrcReg) ||
145	   AMDGPU::SReg_256RegClass.contains(SrcReg));
146    Opcode = AMDGPU::V_MOV_B32_e32;
147    SubIndices = Sub0_7;
148
149  } else if (AMDGPU::VReg_512RegClass.contains(DestReg)) {
150    assert(AMDGPU::VReg_512RegClass.contains(SrcReg) ||
151	   AMDGPU::SReg_512RegClass.contains(SrcReg));
152    Opcode = AMDGPU::V_MOV_B32_e32;
153    SubIndices = Sub0_15;
154
155  } else {
156    llvm_unreachable("Can't copy register!");
157  }
158
159  while (unsigned SubIdx = *SubIndices++) {
160    MachineInstrBuilder Builder = BuildMI(MBB, MI, DL,
161      get(Opcode), RI.getSubReg(DestReg, SubIdx));
162
163    Builder.addReg(RI.getSubReg(SrcReg, SubIdx), getKillRegState(KillSrc));
164
165    if (*SubIndices)
166      Builder.addReg(DestReg, RegState::Define | RegState::Implicit);
167  }
168}
169
170unsigned SIInstrInfo::commuteOpcode(unsigned Opcode) const {
171
172  int NewOpc;
173
174  // Try to map original to commuted opcode
175  if ((NewOpc = AMDGPU::getCommuteRev(Opcode)) != -1)
176    return NewOpc;
177
178  // Try to map commuted to original opcode
179  if ((NewOpc = AMDGPU::getCommuteOrig(Opcode)) != -1)
180    return NewOpc;
181
182  return Opcode;
183}
184
185MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
186                                              bool NewMI) const {
187
188  if (MI->getNumOperands() < 3 || !MI->getOperand(1).isReg() ||
189      !MI->getOperand(2).isReg())
190    return 0;
191
192  MI = TargetInstrInfo::commuteInstruction(MI, NewMI);
193
194  if (MI)
195    MI->setDesc(get(commuteOpcode(MI->getOpcode())));
196
197  return MI;
198}
199
200MachineInstr * SIInstrInfo::getMovImmInstr(MachineFunction *MF, unsigned DstReg,
201                                           int64_t Imm) const {
202  MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::V_MOV_B32_e32), DebugLoc());
203  MachineInstrBuilder MIB(*MF, MI);
204  MIB.addReg(DstReg, RegState::Define);
205  MIB.addImm(Imm);
206
207  return MI;
208
209}
210
211bool SIInstrInfo::isMov(unsigned Opcode) const {
212  switch(Opcode) {
213  default: return false;
214  case AMDGPU::S_MOV_B32:
215  case AMDGPU::S_MOV_B64:
216  case AMDGPU::V_MOV_B32_e32:
217  case AMDGPU::V_MOV_B32_e64:
218    return true;
219  }
220}
221
222bool
223SIInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
224  return RC != &AMDGPU::EXECRegRegClass;
225}
226
227//===----------------------------------------------------------------------===//
228// Indirect addressing callbacks
229//===----------------------------------------------------------------------===//
230
231unsigned SIInstrInfo::calculateIndirectAddress(unsigned RegIndex,
232                                                 unsigned Channel) const {
233  assert(Channel == 0);
234  return RegIndex;
235}
236
237
238int SIInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
239  llvm_unreachable("Unimplemented");
240}
241
242int SIInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
243  llvm_unreachable("Unimplemented");
244}
245
246const TargetRegisterClass *SIInstrInfo::getIndirectAddrStoreRegClass(
247                                                     unsigned SourceReg) const {
248  llvm_unreachable("Unimplemented");
249}
250
251const TargetRegisterClass *SIInstrInfo::getIndirectAddrLoadRegClass() const {
252  llvm_unreachable("Unimplemented");
253}
254
255MachineInstrBuilder SIInstrInfo::buildIndirectWrite(
256                                   MachineBasicBlock *MBB,
257                                   MachineBasicBlock::iterator I,
258                                   unsigned ValueReg,
259                                   unsigned Address, unsigned OffsetReg) const {
260  llvm_unreachable("Unimplemented");
261}
262
263MachineInstrBuilder SIInstrInfo::buildIndirectRead(
264                                   MachineBasicBlock *MBB,
265                                   MachineBasicBlock::iterator I,
266                                   unsigned ValueReg,
267                                   unsigned Address, unsigned OffsetReg) const {
268  llvm_unreachable("Unimplemented");
269}
270
271const TargetRegisterClass *SIInstrInfo::getSuperIndirectRegClass() const {
272  llvm_unreachable("Unimplemented");
273}
274