blob: cf6a89973e1d3c1c0a4a3cf2dcc28f3888fbc1d4 [file] [log] [blame]
Eric Christopher50880d02010-09-18 18:52:28 +00001//===- PTXInstrInfo.cpp - PTX 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 PTX implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +000014#define DEBUG_TYPE "ptx-instrinfo"
15
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000016#include "PTX.h"
Eric Christopher50880d02010-09-18 18:52:28 +000017#include "PTXInstrInfo.h"
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000018#include "llvm/CodeGen/MachineInstrBuilder.h"
Justin Holewinski297984d2011-09-22 16:45:40 +000019#include "llvm/CodeGen/MachineRegisterInfo.h"
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000020#include "llvm/CodeGen/SelectionDAG.h"
21#include "llvm/CodeGen/SelectionDAGNodes.h"
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +000022#include "llvm/Support/Debug.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000023#include "llvm/Support/TargetRegistry.h"
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +000024#include "llvm/Support/raw_ostream.h"
Eric Christopher50880d02010-09-18 18:52:28 +000025
Evan Cheng4db3cff2011-07-01 17:57:27 +000026#define GET_INSTRINFO_CTOR
Eric Christopher50880d02010-09-18 18:52:28 +000027#include "PTXGenInstrInfo.inc"
28
Evan Cheng22fee2d2011-06-28 20:07:07 +000029using namespace llvm;
30
Eric Christopher50880d02010-09-18 18:52:28 +000031PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM)
Evan Cheng4db3cff2011-07-01 17:57:27 +000032 : PTXGenInstrInfo(),
Eric Christopher50880d02010-09-18 18:52:28 +000033 RI(_TM, *this), TM(_TM) {}
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000034
35static const struct map_entry {
36 const TargetRegisterClass *cls;
37 const int opcode;
38} map[] = {
Justin Holewinski1b91bcd2011-06-16 17:49:58 +000039 { &PTX::RegI16RegClass, PTX::MOVU16rr },
40 { &PTX::RegI32RegClass, PTX::MOVU32rr },
41 { &PTX::RegI64RegClass, PTX::MOVU64rr },
42 { &PTX::RegF32RegClass, PTX::MOVF32rr },
43 { &PTX::RegF64RegClass, PTX::MOVF64rr },
44 { &PTX::RegPredRegClass, PTX::MOVPREDrr }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000045};
46
47void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
48 MachineBasicBlock::iterator I, DebugLoc DL,
49 unsigned DstReg, unsigned SrcReg,
50 bool KillSrc) const {
Justin Holewinski297984d2011-09-22 16:45:40 +000051
52 const MachineRegisterInfo& MRI = MBB.getParent()->getRegInfo();
Justin Holewinski5422a0f2011-09-22 16:45:46 +000053 //assert(MRI.getRegClass(SrcReg) == MRI.getRegClass(DstReg) &&
54 // "Invalid register copy between two register classes");
Justin Holewinski297984d2011-09-22 16:45:40 +000055
56 for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++i) {
Justin Holewinski5422a0f2011-09-22 16:45:46 +000057 if (map[i].cls == MRI.getRegClass(DstReg)) {
Evan Chenge837dea2011-06-28 19:10:37 +000058 const MCInstrDesc &MCID = get(map[i].opcode);
59 MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000060 addReg(SrcReg, getKillRegState(KillSrc));
61 AddDefaultPredicate(MI);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000062 return;
63 }
Che-Liang Chiouf7172022011-02-28 06:34:09 +000064 }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000065
66 llvm_unreachable("Impossible reg-to-reg copy");
67}
68
69bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
70 MachineBasicBlock::iterator I,
71 unsigned DstReg, unsigned SrcReg,
72 const TargetRegisterClass *DstRC,
73 const TargetRegisterClass *SrcRC,
74 DebugLoc DL) const {
75 if (DstRC != SrcRC)
76 return false;
77
78 for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i)
79 if (DstRC == map[i].cls) {
Evan Chenge837dea2011-06-28 19:10:37 +000080 const MCInstrDesc &MCID = get(map[i].opcode);
81 MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000082 AddDefaultPredicate(MI);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000083 return true;
84 }
85
86 return false;
87}
88
89bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
90 unsigned &SrcReg, unsigned &DstReg,
91 unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
92 switch (MI.getOpcode()) {
93 default:
94 return false;
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000095 case PTX::MOVU16rr:
96 case PTX::MOVU32rr:
97 case PTX::MOVU64rr:
98 case PTX::MOVF32rr:
99 case PTX::MOVF64rr:
100 case PTX::MOVPREDrr:
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000101 assert(MI.getNumOperands() >= 2 &&
102 MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
103 "Invalid register-register move instruction");
104 SrcSubIdx = DstSubIdx = 0; // No sub-registers
105 DstReg = MI.getOperand(0).getReg();
106 SrcReg = MI.getOperand(1).getReg();
107 return true;
108 }
109}
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000110
111// predicate support
112
113bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
114 int i = MI->findFirstPredOperandIdx();
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000115 return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000116}
117
118bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
119 return !isPredicated(MI) && get(MI->getOpcode()).isTerminator();
120}
121
122bool PTXInstrInfo::
123PredicateInstruction(MachineInstr *MI,
124 const SmallVectorImpl<MachineOperand> &Pred) const {
125 if (Pred.size() < 2)
126 llvm_unreachable("lesser than 2 predicate operands are provided");
127
128 int i = MI->findFirstPredOperandIdx();
129 if (i == -1)
130 llvm_unreachable("missing predicate operand");
131
132 MI->getOperand(i).setReg(Pred[0].getReg());
133 MI->getOperand(i+1).setImm(Pred[1].getImm());
134
135 return true;
136}
137
138bool PTXInstrInfo::
139SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
140 const SmallVectorImpl<MachineOperand> &Pred2) const {
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000141 const MachineOperand &PredReg1 = Pred1[0];
142 const MachineOperand &PredReg2 = Pred2[0];
143 if (PredReg1.getReg() != PredReg2.getReg())
144 return false;
145
146 const MachineOperand &PredOp1 = Pred1[1];
147 const MachineOperand &PredOp2 = Pred2[1];
148 if (PredOp1.getImm() != PredOp2.getImm())
149 return false;
150
151 return true;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000152}
153
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000154bool PTXInstrInfo::
155DefinesPredicate(MachineInstr *MI,
156 std::vector<MachineOperand> &Pred) const {
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000157 // If an instruction sets a predicate register, it defines a predicate.
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000158
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000159 // TODO supprot 5-operand format of setp instruction
160
161 if (MI->getNumOperands() < 1)
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000162 return false;
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000163
164 const MachineOperand &MO = MI->getOperand(0);
165
Justin Holewinski1b91bcd2011-06-16 17:49:58 +0000166 if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass)
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000167 return false;
168
169 Pred.push_back(MO);
170 Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
171 return true;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000172}
173
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000174// branch support
175
176bool PTXInstrInfo::
177AnalyzeBranch(MachineBasicBlock &MBB,
178 MachineBasicBlock *&TBB,
179 MachineBasicBlock *&FBB,
180 SmallVectorImpl<MachineOperand> &Cond,
181 bool AllowModify) const {
182 // TODO implement cases when AllowModify is true
183
184 if (MBB.empty())
185 return true;
186
187 MachineBasicBlock::const_iterator iter = MBB.end();
188 const MachineInstr& instLast1 = *--iter;
Evan Chenge837dea2011-06-28 19:10:37 +0000189 const MCInstrDesc &desc1 = instLast1.getDesc();
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000190 // for special case that MBB has only 1 instruction
191 const bool IsSizeOne = MBB.size() == 1;
192 // if IsSizeOne is true, *--iter and instLast2 are invalid
193 // we put a dummy value in instLast2 and desc2 since they are used
194 const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter;
Evan Chenge837dea2011-06-28 19:10:37 +0000195 const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000196
197 DEBUG(dbgs() << "\n");
198 DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n");
199 DEBUG(dbgs() << "AnalyzeBranch: MBB: " << MBB.getName().str() << "\n");
200 DEBUG(dbgs() << "AnalyzeBranch: TBB: " << TBB << "\n");
201 DEBUG(dbgs() << "AnalyzeBranch: FBB: " << FBB << "\n");
202
203 // this block ends with no branches
204 if (!IsAnyKindOfBranch(instLast1)) {
205 DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n");
206 return false;
207 }
208
209 // this block ends with only an unconditional branch
210 if (desc1.isUnconditionalBranch() &&
211 // when IsSizeOne is true, it "absorbs" the evaluation of instLast2
212 (IsSizeOne || !IsAnyKindOfBranch(instLast2))) {
213 DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n");
214 TBB = GetBranchTarget(instLast1);
215 return false;
216 }
217
218 // this block ends with a conditional branch and
219 // it falls through to a successor block
220 if (desc1.isConditionalBranch() &&
221 IsAnySuccessorAlsoLayoutSuccessor(MBB)) {
222 DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n");
223 TBB = GetBranchTarget(instLast1);
224 int i = instLast1.findFirstPredOperandIdx();
225 Cond.push_back(instLast1.getOperand(i));
226 Cond.push_back(instLast1.getOperand(i+1));
227 return false;
228 }
229
230 // when IsSizeOne is true, we are done
231 if (IsSizeOne)
232 return true;
233
234 // this block ends with a conditional branch
235 // followed by an unconditional branch
236 if (desc2.isConditionalBranch() &&
237 desc1.isUnconditionalBranch()) {
238 DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n");
239 TBB = GetBranchTarget(instLast2);
240 FBB = GetBranchTarget(instLast1);
241 int i = instLast2.findFirstPredOperandIdx();
242 Cond.push_back(instLast2.getOperand(i));
243 Cond.push_back(instLast2.getOperand(i+1));
244 return false;
245 }
246
247 // branch cannot be understood
248 DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n");
249 return true;
250}
251
252unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000253 unsigned count = 0;
254 while (!MBB.empty())
255 if (IsAnyKindOfBranch(MBB.back())) {
256 MBB.pop_back();
257 ++count;
258 } else
259 break;
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000260 DEBUG(dbgs() << "RemoveBranch: MBB: " << MBB.getName().str() << "\n");
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000261 DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n");
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000262 return count;
263}
264
265unsigned PTXInstrInfo::
266InsertBranch(MachineBasicBlock &MBB,
267 MachineBasicBlock *TBB,
268 MachineBasicBlock *FBB,
269 const SmallVectorImpl<MachineOperand> &Cond,
270 DebugLoc DL) const {
271 DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n");
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000272 DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: " << TBB->getName().str()
273 << "\n";
274 else dbgs() << "InsertBranch: TBB: (NULL)\n");
275 DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: " << FBB->getName().str()
276 << "\n";
277 else dbgs() << "InsertBranch: FBB: (NULL)\n");
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000278 DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n");
279
280 assert(TBB && "TBB is NULL");
281
282 if (FBB) {
283 BuildMI(&MBB, DL, get(PTX::BRAdp))
284 .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
285 BuildMI(&MBB, DL, get(PTX::BRAd))
286 .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
287 return 2;
288 } else if (Cond.size()) {
289 BuildMI(&MBB, DL, get(PTX::BRAdp))
290 .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
291 return 1;
292 } else {
293 BuildMI(&MBB, DL, get(PTX::BRAd))
294 .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
295 return 1;
296 }
297}
298
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000299// Memory operand folding for spills
300void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
301 MachineBasicBlock::iterator MII,
Justin Holewinski08d03162011-06-22 16:07:03 +0000302 unsigned SrcReg, bool isKill, int FrameIdx,
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000303 const TargetRegisterClass *RC,
304 const TargetRegisterInfo *TRI) const {
305 MachineInstr& MI = *MII;
306 DebugLoc DL = MI.getDebugLoc();
307
308 DEBUG(dbgs() << "storeRegToStackSlot: " << MI);
309
310 int OpCode;
311
312 // Select the appropriate opcode based on the register class
Dan Bailey84149462011-06-25 18:16:28 +0000313 if (RC == PTX::RegI16RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000314 OpCode = PTX::STACKSTOREI16;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000315 } else if (RC == PTX::RegI32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000316 OpCode = PTX::STACKSTOREI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000317 } else if (RC == PTX::RegI64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000318 OpCode = PTX::STACKSTOREI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000319 } else if (RC == PTX::RegF32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000320 OpCode = PTX::STACKSTOREF32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000321 } else if (RC == PTX::RegF64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000322 OpCode = PTX::STACKSTOREF64;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000323 } else {
324 llvm_unreachable("Unknown PTX register class!");
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000325 }
326
327 // Build the store instruction (really a mov)
328 MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
Justin Holewinski08d03162011-06-22 16:07:03 +0000329 MIB.addFrameIndex(FrameIdx);
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000330 MIB.addReg(SrcReg);
331
332 AddDefaultPredicate(MIB);
333}
334
335void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
336 MachineBasicBlock::iterator MII,
337 unsigned DestReg, int FrameIdx,
338 const TargetRegisterClass *RC,
339 const TargetRegisterInfo *TRI) const {
340 MachineInstr& MI = *MII;
341 DebugLoc DL = MI.getDebugLoc();
342
343 DEBUG(dbgs() << "loadRegToStackSlot: " << MI);
344
345 int OpCode;
346
347 // Select the appropriate opcode based on the register class
Dan Bailey84149462011-06-25 18:16:28 +0000348 if (RC == PTX::RegI16RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000349 OpCode = PTX::STACKLOADI16;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000350 } else if (RC == PTX::RegI32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000351 OpCode = PTX::STACKLOADI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000352 } else if (RC == PTX::RegI64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000353 OpCode = PTX::STACKLOADI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000354 } else if (RC == PTX::RegF32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000355 OpCode = PTX::STACKLOADF32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000356 } else if (RC == PTX::RegF64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000357 OpCode = PTX::STACKLOADF64;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000358 } else {
359 llvm_unreachable("Unknown PTX register class!");
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000360 }
361
362 // Build the load instruction (really a mov)
363 MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
364 MIB.addReg(DestReg);
Justin Holewinski08d03162011-06-22 16:07:03 +0000365 MIB.addFrameIndex(FrameIdx);
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000366
367 AddDefaultPredicate(MIB);
368}
369
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000370// static helper routines
371
372MachineSDNode *PTXInstrInfo::
373GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
374 DebugLoc dl, EVT VT, SDValue Op1) {
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000375 SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
376 SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000377 SDValue ops[] = { Op1, predReg, predOp };
378 return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
379}
380
381MachineSDNode *PTXInstrInfo::
382GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
383 DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000384 SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
385 SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000386 SDValue ops[] = { Op1, Op2, predReg, predOp };
387 return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
388}
389
390void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
391 if (MI->findFirstPredOperandIdx() == -1) {
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000392 MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000393 MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000394 }
395}
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000396
397bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
Evan Chenge837dea2011-06-28 19:10:37 +0000398 const MCInstrDesc &desc = inst.getDesc();
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000399 return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
400}
401
402bool PTXInstrInfo::
403IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
404 for (MachineBasicBlock::const_succ_iterator
405 i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
406 if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
407 return true;
408 return false;
409}
410
411MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
412 // FIXME So far all branch instructions put destination in 1st operand
413 const MachineOperand& target = inst.getOperand(0);
414 assert(target.isMBB() && "FIXME: detect branch target operand");
415 return target.getMBB();
416}