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
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 {
69 llvm_unreachable("Don't know how to copy a register");
70 }
71 }
72
isMoveInstr(const MachineInstr & MI,unsigned & SrcReg,unsigned & DestReg) const73 bool 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
isReadSpecialReg(MachineInstr & MI) const97 bool 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
isLoadInstr(const MachineInstr & MI,unsigned & AddrSpace) const119 bool 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
isStoreInstr(const MachineInstr & MI,unsigned & AddrSpace) const130 bool 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
CanTailMerge(const MachineInstr * MI) const142 bool 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 ///
AnalyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const179 bool 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
RemoveBranch(MachineBasicBlock & MBB) const239 unsigned 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
261 unsigned
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,const SmallVectorImpl<MachineOperand> & Cond,DebugLoc DL) const262 NVPTXInstrInfo::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