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
27 using namespace llvm;
28
29 // FIXME: Add the subtarget support on this constructor.
NVPTXInstrInfo(NVPTXTargetMachine & tm)30 NVPTXInstrInfo::NVPTXInstrInfo(NVPTXTargetMachine &tm)
31 : NVPTXGenInstrInfo(),
32 TM(tm),
33 RegInfo(*this, *TM.getSubtargetImpl()) {}
34
35
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,DebugLoc DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const36 void 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
isMoveInstr(const MachineInstr & MI,unsigned & SrcReg,unsigned & DestReg) const113 bool 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
isReadSpecialReg(MachineInstr & MI) const137 bool 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
isLoadInstr(const MachineInstr & MI,unsigned & AddrSpace) const159 bool 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
isStoreInstr(const MachineInstr & MI,unsigned & AddrSpace) const170 bool 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
CanTailMerge(const MachineInstr * MI) const182 bool 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 ///
AnalyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const219 bool 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
RemoveBranch(MachineBasicBlock & MBB) const279 unsigned 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
301 unsigned
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,const SmallVectorImpl<MachineOperand> & Cond,DebugLoc DL) const302 NVPTXInstrInfo::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