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/IR/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 {
69    llvm_unreachable("Don't know how to copy a register");
70  }
71}
72
73bool NVPTXInstrInfo::isMoveInstr(const MachineInstr &MI,
74                                 unsigned &SrcReg,
75                                 unsigned &DestReg) const {
76  // Look for the appropriate part of TSFlags
77  bool isMove = false;
78
79  unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::SimpleMoveMask) >>
80      NVPTX::SimpleMoveShift;
81  isMove = (TSFlags == 1);
82
83  if (isMove) {
84    MachineOperand dest = MI.getOperand(0);
85    MachineOperand src = MI.getOperand(1);
86    assert(dest.isReg() && "dest of a movrr is not a reg");
87    assert(src.isReg() && "src of a movrr is not a reg");
88
89    SrcReg = src.getReg();
90    DestReg = dest.getReg();
91    return true;
92  }
93
94  return false;
95}
96
97bool  NVPTXInstrInfo::isReadSpecialReg(MachineInstr &MI) const
98{
99  switch (MI.getOpcode()) {
100  default: return false;
101  case NVPTX::INT_PTX_SREG_NTID_X:
102  case NVPTX::INT_PTX_SREG_NTID_Y:
103  case NVPTX::INT_PTX_SREG_NTID_Z:
104  case NVPTX::INT_PTX_SREG_TID_X:
105  case NVPTX::INT_PTX_SREG_TID_Y:
106  case NVPTX::INT_PTX_SREG_TID_Z:
107  case NVPTX::INT_PTX_SREG_CTAID_X:
108  case NVPTX::INT_PTX_SREG_CTAID_Y:
109  case NVPTX::INT_PTX_SREG_CTAID_Z:
110  case NVPTX::INT_PTX_SREG_NCTAID_X:
111  case NVPTX::INT_PTX_SREG_NCTAID_Y:
112  case NVPTX::INT_PTX_SREG_NCTAID_Z:
113  case NVPTX::INT_PTX_SREG_WARPSIZE:
114    return true;
115  }
116}
117
118
119bool NVPTXInstrInfo::isLoadInstr(const MachineInstr &MI,
120                                 unsigned &AddrSpace) const {
121  bool isLoad = false;
122  unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::isLoadMask) >>
123      NVPTX::isLoadShift;
124  isLoad = (TSFlags == 1);
125  if (isLoad)
126    AddrSpace = getLdStCodeAddrSpace(MI);
127  return isLoad;
128}
129
130bool NVPTXInstrInfo::isStoreInstr(const MachineInstr &MI,
131                                  unsigned &AddrSpace) const {
132  bool isStore = false;
133  unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::isStoreMask) >>
134      NVPTX::isStoreShift;
135  isStore = (TSFlags == 1);
136  if (isStore)
137    AddrSpace = getLdStCodeAddrSpace(MI);
138  return isStore;
139}
140
141
142bool NVPTXInstrInfo::CanTailMerge(const MachineInstr *MI) const {
143  unsigned addrspace = 0;
144  if (MI->getOpcode() == NVPTX::INT_CUDA_SYNCTHREADS)
145    return false;
146  if (isLoadInstr(*MI, addrspace))
147    if (addrspace == NVPTX::PTXLdStInstCode::SHARED)
148      return false;
149  if (isStoreInstr(*MI, addrspace))
150    if (addrspace == NVPTX::PTXLdStInstCode::SHARED)
151      return false;
152  return true;
153}
154
155
156/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
157/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
158/// implemented for a target).  Upon success, this returns false and returns
159/// with the following information in various cases:
160///
161/// 1. If this block ends with no branches (it just falls through to its succ)
162///    just return false, leaving TBB/FBB null.
163/// 2. If this block ends with only an unconditional branch, it sets TBB to be
164///    the destination block.
165/// 3. If this block ends with an conditional branch and it falls through to
166///    an successor block, it sets TBB to be the branch destination block and a
167///    list of operands that evaluate the condition. These
168///    operands can be passed to other TargetInstrInfo methods to create new
169///    branches.
170/// 4. If this block ends with an conditional branch and an unconditional
171///    block, it returns the 'true' destination in TBB, the 'false' destination
172///    in FBB, and a list of operands that evaluate the condition. These
173///    operands can be passed to other TargetInstrInfo methods to create new
174///    branches.
175///
176/// Note that RemoveBranch and InsertBranch must be implemented to support
177/// cases where this method returns success.
178///
179bool NVPTXInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
180                                   MachineBasicBlock *&TBB,
181                                   MachineBasicBlock *&FBB,
182                                   SmallVectorImpl<MachineOperand> &Cond,
183                                   bool AllowModify) const {
184  // If the block has no terminators, it just falls into the block after it.
185  MachineBasicBlock::iterator I = MBB.end();
186  if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
187    return false;
188
189  // Get the last instruction in the block.
190  MachineInstr *LastInst = I;
191
192  // If there is only one terminator instruction, process it.
193  if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
194    if (LastInst->getOpcode() == NVPTX::GOTO) {
195      TBB = LastInst->getOperand(0).getMBB();
196      return false;
197    } else if (LastInst->getOpcode() == NVPTX::CBranch) {
198      // Block ends with fall-through condbranch.
199      TBB = LastInst->getOperand(1).getMBB();
200      Cond.push_back(LastInst->getOperand(0));
201      return false;
202    }
203    // Otherwise, don't know what this is.
204    return true;
205  }
206
207  // Get the instruction before it if it's a terminator.
208  MachineInstr *SecondLastInst = I;
209
210  // If there are three terminators, we don't know what sort of block this is.
211  if (SecondLastInst && I != MBB.begin() &&
212      isUnpredicatedTerminator(--I))
213    return true;
214
215  // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it.
216  if (SecondLastInst->getOpcode() == NVPTX::CBranch &&
217      LastInst->getOpcode() == NVPTX::GOTO) {
218    TBB =  SecondLastInst->getOperand(1).getMBB();
219    Cond.push_back(SecondLastInst->getOperand(0));
220    FBB = LastInst->getOperand(0).getMBB();
221    return false;
222  }
223
224  // If the block ends with two NVPTX:GOTOs, handle it.  The second one is not
225  // executed, so remove it.
226  if (SecondLastInst->getOpcode() == NVPTX::GOTO &&
227      LastInst->getOpcode() == NVPTX::GOTO) {
228    TBB = SecondLastInst->getOperand(0).getMBB();
229    I = LastInst;
230    if (AllowModify)
231      I->eraseFromParent();
232    return false;
233  }
234
235  // Otherwise, can't handle this.
236  return true;
237}
238
239unsigned NVPTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
240  MachineBasicBlock::iterator I = MBB.end();
241  if (I == MBB.begin()) return 0;
242  --I;
243  if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch)
244    return 0;
245
246  // Remove the branch.
247  I->eraseFromParent();
248
249  I = MBB.end();
250
251  if (I == MBB.begin()) return 1;
252  --I;
253  if (I->getOpcode() != NVPTX::CBranch)
254    return 1;
255
256  // Remove the branch.
257  I->eraseFromParent();
258  return 2;
259}
260
261unsigned
262NVPTXInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
263                             MachineBasicBlock *FBB,
264                             const SmallVectorImpl<MachineOperand> &Cond,
265                             DebugLoc DL) const {
266  // Shouldn't be a fall through.
267  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
268  assert((Cond.size() == 1 || Cond.size() == 0) &&
269         "NVPTX branch conditions have two components!");
270
271  // One-way branch.
272  if (FBB == 0) {
273    if (Cond.empty())   // Unconditional branch
274      BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB);
275    else                // Conditional branch
276      BuildMI(&MBB, DL, get(NVPTX::CBranch))
277      .addReg(Cond[0].getReg()).addMBB(TBB);
278    return 1;
279  }
280
281  // Two-way Conditional Branch.
282  BuildMI(&MBB, DL, get(NVPTX::CBranch))
283  .addReg(Cond[0].getReg()).addMBB(TBB);
284  BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB);
285  return 2;
286}
287