1//===- NVPTXInstrInfo.cpp - NVPTX 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// This file contains the NVPTX implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "NVPTX.h"
15#include "NVPTXInstrInfo.h"
16#include "NVPTXTargetMachine.h"
17#define GET_INSTRINFO_CTOR
18#include "NVPTXGenInstrInfo.inc"
19#include "llvm/Function.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include <cstdio>
25
26
27using namespace llvm;
28
29// FIXME: Add the subtarget support on this constructor.
30NVPTXInstrInfo::NVPTXInstrInfo(NVPTXTargetMachine &tm)
31: NVPTXGenInstrInfo(),
32  TM(tm),
33  RegInfo(*this, *TM.getSubtargetImpl()) {}
34
35
36void NVPTXInstrInfo::copyPhysReg (MachineBasicBlock &MBB,
37                                  MachineBasicBlock::iterator I, DebugLoc DL,
38                                  unsigned DestReg, unsigned SrcReg,
39                                  bool KillSrc) const {
40  if (NVPTX::Int32RegsRegClass.contains(DestReg) &&
41      NVPTX::Int32RegsRegClass.contains(SrcReg))
42    BuildMI(MBB, I, DL, get(NVPTX::IMOV32rr), DestReg)
43    .addReg(SrcReg, getKillRegState(KillSrc));
44  else if (NVPTX::Int8RegsRegClass.contains(DestReg) &&
45      NVPTX::Int8RegsRegClass.contains(SrcReg))
46    BuildMI(MBB, I, DL, get(NVPTX::IMOV8rr), DestReg)
47    .addReg(SrcReg, getKillRegState(KillSrc));
48  else if (NVPTX::Int1RegsRegClass.contains(DestReg) &&
49      NVPTX::Int1RegsRegClass.contains(SrcReg))
50    BuildMI(MBB, I, DL, get(NVPTX::IMOV1rr), DestReg)
51    .addReg(SrcReg, getKillRegState(KillSrc));
52  else if (NVPTX::Float32RegsRegClass.contains(DestReg) &&
53      NVPTX::Float32RegsRegClass.contains(SrcReg))
54    BuildMI(MBB, I, DL, get(NVPTX::FMOV32rr), DestReg)
55    .addReg(SrcReg, getKillRegState(KillSrc));
56  else if (NVPTX::Int16RegsRegClass.contains(DestReg) &&
57      NVPTX::Int16RegsRegClass.contains(SrcReg))
58    BuildMI(MBB, I, DL, get(NVPTX::IMOV16rr), DestReg)
59    .addReg(SrcReg, getKillRegState(KillSrc));
60  else if (NVPTX::Int64RegsRegClass.contains(DestReg) &&
61      NVPTX::Int64RegsRegClass.contains(SrcReg))
62    BuildMI(MBB, I, DL, get(NVPTX::IMOV64rr), DestReg)
63    .addReg(SrcReg, getKillRegState(KillSrc));
64  else if (NVPTX::Float64RegsRegClass.contains(DestReg) &&
65      NVPTX::Float64RegsRegClass.contains(SrcReg))
66    BuildMI(MBB, I, DL, get(NVPTX::FMOV64rr), DestReg)
67    .addReg(SrcReg, getKillRegState(KillSrc));
68  else if (NVPTX::V4F32RegsRegClass.contains(DestReg) &&
69      NVPTX::V4F32RegsRegClass.contains(SrcReg))
70    BuildMI(MBB, I, DL, get(NVPTX::V4f32Mov), DestReg)
71    .addReg(SrcReg, getKillRegState(KillSrc));
72  else if (NVPTX::V4I32RegsRegClass.contains(DestReg) &&
73      NVPTX::V4I32RegsRegClass.contains(SrcReg))
74    BuildMI(MBB, I, DL, get(NVPTX::V4i32Mov), DestReg)
75    .addReg(SrcReg, getKillRegState(KillSrc));
76  else if (NVPTX::V2F32RegsRegClass.contains(DestReg) &&
77      NVPTX::V2F32RegsRegClass.contains(SrcReg))
78    BuildMI(MBB, I, DL, get(NVPTX::V2f32Mov), DestReg)
79    .addReg(SrcReg, getKillRegState(KillSrc));
80  else if (NVPTX::V2I32RegsRegClass.contains(DestReg) &&
81      NVPTX::V2I32RegsRegClass.contains(SrcReg))
82    BuildMI(MBB, I, DL, get(NVPTX::V2i32Mov), DestReg)
83    .addReg(SrcReg, getKillRegState(KillSrc));
84  else if (NVPTX::V4I8RegsRegClass.contains(DestReg) &&
85      NVPTX::V4I8RegsRegClass.contains(SrcReg))
86    BuildMI(MBB, I, DL, get(NVPTX::V4i8Mov), DestReg)
87    .addReg(SrcReg, getKillRegState(KillSrc));
88  else if (NVPTX::V2I8RegsRegClass.contains(DestReg) &&
89      NVPTX::V2I8RegsRegClass.contains(SrcReg))
90    BuildMI(MBB, I, DL, get(NVPTX::V2i8Mov), DestReg)
91    .addReg(SrcReg, getKillRegState(KillSrc));
92  else if (NVPTX::V4I16RegsRegClass.contains(DestReg) &&
93      NVPTX::V4I16RegsRegClass.contains(SrcReg))
94    BuildMI(MBB, I, DL, get(NVPTX::V4i16Mov), DestReg)
95    .addReg(SrcReg, getKillRegState(KillSrc));
96  else if (NVPTX::V2I16RegsRegClass.contains(DestReg) &&
97      NVPTX::V2I16RegsRegClass.contains(SrcReg))
98    BuildMI(MBB, I, DL, get(NVPTX::V2i16Mov), DestReg)
99    .addReg(SrcReg, getKillRegState(KillSrc));
100  else if (NVPTX::V2I64RegsRegClass.contains(DestReg) &&
101      NVPTX::V2I64RegsRegClass.contains(SrcReg))
102    BuildMI(MBB, I, DL, get(NVPTX::V2i64Mov), DestReg)
103    .addReg(SrcReg, getKillRegState(KillSrc));
104  else if (NVPTX::V2F64RegsRegClass.contains(DestReg) &&
105      NVPTX::V2F64RegsRegClass.contains(SrcReg))
106    BuildMI(MBB, I, DL, get(NVPTX::V2f64Mov), DestReg)
107    .addReg(SrcReg, getKillRegState(KillSrc));
108  else {
109    llvm_unreachable("Don't know how to copy a register");
110  }
111}
112
113bool NVPTXInstrInfo::isMoveInstr(const MachineInstr &MI,
114                                 unsigned &SrcReg,
115                                 unsigned &DestReg) const {
116  // Look for the appropriate part of TSFlags
117  bool isMove = false;
118
119  unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::SimpleMoveMask) >>
120      NVPTX::SimpleMoveShift;
121  isMove = (TSFlags == 1);
122
123  if (isMove) {
124    MachineOperand dest = MI.getOperand(0);
125    MachineOperand src = MI.getOperand(1);
126    assert(dest.isReg() && "dest of a movrr is not a reg");
127    assert(src.isReg() && "src of a movrr is not a reg");
128
129    SrcReg = src.getReg();
130    DestReg = dest.getReg();
131    return true;
132  }
133
134  return false;
135}
136
137bool  NVPTXInstrInfo::isReadSpecialReg(MachineInstr &MI) const
138{
139  switch (MI.getOpcode()) {
140  default: return false;
141  case NVPTX::INT_PTX_SREG_NTID_X:
142  case NVPTX::INT_PTX_SREG_NTID_Y:
143  case NVPTX::INT_PTX_SREG_NTID_Z:
144  case NVPTX::INT_PTX_SREG_TID_X:
145  case NVPTX::INT_PTX_SREG_TID_Y:
146  case NVPTX::INT_PTX_SREG_TID_Z:
147  case NVPTX::INT_PTX_SREG_CTAID_X:
148  case NVPTX::INT_PTX_SREG_CTAID_Y:
149  case NVPTX::INT_PTX_SREG_CTAID_Z:
150  case NVPTX::INT_PTX_SREG_NCTAID_X:
151  case NVPTX::INT_PTX_SREG_NCTAID_Y:
152  case NVPTX::INT_PTX_SREG_NCTAID_Z:
153  case NVPTX::INT_PTX_SREG_WARPSIZE:
154    return true;
155  }
156}
157
158
159bool NVPTXInstrInfo::isLoadInstr(const MachineInstr &MI,
160                                 unsigned &AddrSpace) const {
161  bool isLoad = false;
162  unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::isLoadMask) >>
163      NVPTX::isLoadShift;
164  isLoad = (TSFlags == 1);
165  if (isLoad)
166    AddrSpace = getLdStCodeAddrSpace(MI);
167  return isLoad;
168}
169
170bool NVPTXInstrInfo::isStoreInstr(const MachineInstr &MI,
171                                  unsigned &AddrSpace) const {
172  bool isStore = false;
173  unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::isStoreMask) >>
174      NVPTX::isStoreShift;
175  isStore = (TSFlags == 1);
176  if (isStore)
177    AddrSpace = getLdStCodeAddrSpace(MI);
178  return isStore;
179}
180
181
182bool NVPTXInstrInfo::CanTailMerge(const MachineInstr *MI) const {
183  unsigned addrspace = 0;
184  if (MI->getOpcode() == NVPTX::INT_CUDA_SYNCTHREADS)
185    return false;
186  if (isLoadInstr(*MI, addrspace))
187    if (addrspace == NVPTX::PTXLdStInstCode::SHARED)
188      return false;
189  if (isStoreInstr(*MI, addrspace))
190    if (addrspace == NVPTX::PTXLdStInstCode::SHARED)
191      return false;
192  return true;
193}
194
195
196/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
197/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
198/// implemented for a target).  Upon success, this returns false and returns
199/// with the following information in various cases:
200///
201/// 1. If this block ends with no branches (it just falls through to its succ)
202///    just return false, leaving TBB/FBB null.
203/// 2. If this block ends with only an unconditional branch, it sets TBB to be
204///    the destination block.
205/// 3. If this block ends with an conditional branch and it falls through to
206///    an successor block, it sets TBB to be the branch destination block and a
207///    list of operands that evaluate the condition. These
208///    operands can be passed to other TargetInstrInfo methods to create new
209///    branches.
210/// 4. If this block ends with an conditional branch and an unconditional
211///    block, it returns the 'true' destination in TBB, the 'false' destination
212///    in FBB, and a list of operands that evaluate the condition. These
213///    operands can be passed to other TargetInstrInfo methods to create new
214///    branches.
215///
216/// Note that RemoveBranch and InsertBranch must be implemented to support
217/// cases where this method returns success.
218///
219bool NVPTXInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
220                                   MachineBasicBlock *&TBB,
221                                   MachineBasicBlock *&FBB,
222                                   SmallVectorImpl<MachineOperand> &Cond,
223                                   bool AllowModify) const {
224  // If the block has no terminators, it just falls into the block after it.
225  MachineBasicBlock::iterator I = MBB.end();
226  if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
227    return false;
228
229  // Get the last instruction in the block.
230  MachineInstr *LastInst = I;
231
232  // If there is only one terminator instruction, process it.
233  if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
234    if (LastInst->getOpcode() == NVPTX::GOTO) {
235      TBB = LastInst->getOperand(0).getMBB();
236      return false;
237    } else if (LastInst->getOpcode() == NVPTX::CBranch) {
238      // Block ends with fall-through condbranch.
239      TBB = LastInst->getOperand(1).getMBB();
240      Cond.push_back(LastInst->getOperand(0));
241      return false;
242    }
243    // Otherwise, don't know what this is.
244    return true;
245  }
246
247  // Get the instruction before it if it's a terminator.
248  MachineInstr *SecondLastInst = I;
249
250  // If there are three terminators, we don't know what sort of block this is.
251  if (SecondLastInst && I != MBB.begin() &&
252      isUnpredicatedTerminator(--I))
253    return true;
254
255  // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it.
256  if (SecondLastInst->getOpcode() == NVPTX::CBranch &&
257      LastInst->getOpcode() == NVPTX::GOTO) {
258    TBB =  SecondLastInst->getOperand(1).getMBB();
259    Cond.push_back(SecondLastInst->getOperand(0));
260    FBB = LastInst->getOperand(0).getMBB();
261    return false;
262  }
263
264  // If the block ends with two NVPTX:GOTOs, handle it.  The second one is not
265  // executed, so remove it.
266  if (SecondLastInst->getOpcode() == NVPTX::GOTO &&
267      LastInst->getOpcode() == NVPTX::GOTO) {
268    TBB = SecondLastInst->getOperand(0).getMBB();
269    I = LastInst;
270    if (AllowModify)
271      I->eraseFromParent();
272    return false;
273  }
274
275  // Otherwise, can't handle this.
276  return true;
277}
278
279unsigned NVPTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
280  MachineBasicBlock::iterator I = MBB.end();
281  if (I == MBB.begin()) return 0;
282  --I;
283  if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch)
284    return 0;
285
286  // Remove the branch.
287  I->eraseFromParent();
288
289  I = MBB.end();
290
291  if (I == MBB.begin()) return 1;
292  --I;
293  if (I->getOpcode() != NVPTX::CBranch)
294    return 1;
295
296  // Remove the branch.
297  I->eraseFromParent();
298  return 2;
299}
300
301unsigned
302NVPTXInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
303                             MachineBasicBlock *FBB,
304                             const SmallVectorImpl<MachineOperand> &Cond,
305                             DebugLoc DL) const {
306  // Shouldn't be a fall through.
307  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
308  assert((Cond.size() == 1 || Cond.size() == 0) &&
309         "NVPTX branch conditions have two components!");
310
311  // One-way branch.
312  if (FBB == 0) {
313    if (Cond.empty())   // Unconditional branch
314      BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB);
315    else                // Conditional branch
316      BuildMI(&MBB, DL, get(NVPTX::CBranch))
317      .addReg(Cond[0].getReg()).addMBB(TBB);
318    return 1;
319  }
320
321  // Two-way Conditional Branch.
322  BuildMI(&MBB, DL, get(NVPTX::CBranch))
323  .addReg(Cond[0].getReg()).addMBB(TBB);
324  BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB);
325  return 2;
326}
327