blob: c8278197f00e4b68de99cd213ddd4716359bf249 [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"
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000019#include "llvm/CodeGen/SelectionDAG.h"
20#include "llvm/CodeGen/SelectionDAGNodes.h"
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +000021#include "llvm/Support/Debug.h"
22#include "llvm/Support/raw_ostream.h"
Eric Christopher50880d02010-09-18 18:52:28 +000023
24using namespace llvm;
25
26#include "PTXGenInstrInfo.inc"
27
28PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM)
29 : TargetInstrInfoImpl(PTXInsts, array_lengthof(PTXInsts)),
30 RI(_TM, *this), TM(_TM) {}
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000031
32static const struct map_entry {
33 const TargetRegisterClass *cls;
34 const int opcode;
35} map[] = {
Justin Holewinski1b91bcd2011-06-16 17:49:58 +000036 { &PTX::RegI16RegClass, PTX::MOVU16rr },
37 { &PTX::RegI32RegClass, PTX::MOVU32rr },
38 { &PTX::RegI64RegClass, PTX::MOVU64rr },
39 { &PTX::RegF32RegClass, PTX::MOVF32rr },
40 { &PTX::RegF64RegClass, PTX::MOVF64rr },
41 { &PTX::RegPredRegClass, PTX::MOVPREDrr }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000042};
43
44void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
45 MachineBasicBlock::iterator I, DebugLoc DL,
46 unsigned DstReg, unsigned SrcReg,
47 bool KillSrc) const {
Che-Liang Chiouf7172022011-02-28 06:34:09 +000048 for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) {
49 if (map[i].cls->contains(DstReg, SrcReg)) {
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000050 const TargetInstrDesc &TID = get(map[i].opcode);
51 MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg).
52 addReg(SrcReg, getKillRegState(KillSrc));
53 AddDefaultPredicate(MI);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000054 return;
55 }
Che-Liang Chiouf7172022011-02-28 06:34:09 +000056 }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000057
58 llvm_unreachable("Impossible reg-to-reg copy");
59}
60
61bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
62 MachineBasicBlock::iterator I,
63 unsigned DstReg, unsigned SrcReg,
64 const TargetRegisterClass *DstRC,
65 const TargetRegisterClass *SrcRC,
66 DebugLoc DL) const {
67 if (DstRC != SrcRC)
68 return false;
69
70 for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i)
71 if (DstRC == map[i].cls) {
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000072 const TargetInstrDesc &TID = get(map[i].opcode);
73 MachineInstr *MI = BuildMI(MBB, I, DL, TID, DstReg).addReg(SrcReg);
74 AddDefaultPredicate(MI);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000075 return true;
76 }
77
78 return false;
79}
80
81bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
82 unsigned &SrcReg, unsigned &DstReg,
83 unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
84 switch (MI.getOpcode()) {
85 default:
86 return false;
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000087 case PTX::MOVU16rr:
88 case PTX::MOVU32rr:
89 case PTX::MOVU64rr:
90 case PTX::MOVF32rr:
91 case PTX::MOVF64rr:
92 case PTX::MOVPREDrr:
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000093 assert(MI.getNumOperands() >= 2 &&
94 MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
95 "Invalid register-register move instruction");
96 SrcSubIdx = DstSubIdx = 0; // No sub-registers
97 DstReg = MI.getOperand(0).getReg();
98 SrcReg = MI.getOperand(1).getReg();
99 return true;
100 }
101}
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000102
103// predicate support
104
105bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
106 int i = MI->findFirstPredOperandIdx();
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000107 return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000108}
109
110bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
111 return !isPredicated(MI) && get(MI->getOpcode()).isTerminator();
112}
113
114bool PTXInstrInfo::
115PredicateInstruction(MachineInstr *MI,
116 const SmallVectorImpl<MachineOperand> &Pred) const {
117 if (Pred.size() < 2)
118 llvm_unreachable("lesser than 2 predicate operands are provided");
119
120 int i = MI->findFirstPredOperandIdx();
121 if (i == -1)
122 llvm_unreachable("missing predicate operand");
123
124 MI->getOperand(i).setReg(Pred[0].getReg());
125 MI->getOperand(i+1).setImm(Pred[1].getImm());
126
127 return true;
128}
129
130bool PTXInstrInfo::
131SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
132 const SmallVectorImpl<MachineOperand> &Pred2) const {
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000133 const MachineOperand &PredReg1 = Pred1[0];
134 const MachineOperand &PredReg2 = Pred2[0];
135 if (PredReg1.getReg() != PredReg2.getReg())
136 return false;
137
138 const MachineOperand &PredOp1 = Pred1[1];
139 const MachineOperand &PredOp2 = Pred2[1];
140 if (PredOp1.getImm() != PredOp2.getImm())
141 return false;
142
143 return true;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000144}
145
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000146bool PTXInstrInfo::
147DefinesPredicate(MachineInstr *MI,
148 std::vector<MachineOperand> &Pred) const {
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000149 // If an instruction sets a predicate register, it defines a predicate.
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000150
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000151 // TODO supprot 5-operand format of setp instruction
152
153 if (MI->getNumOperands() < 1)
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000154 return false;
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000155
156 const MachineOperand &MO = MI->getOperand(0);
157
Justin Holewinski1b91bcd2011-06-16 17:49:58 +0000158 if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass)
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000159 return false;
160
161 Pred.push_back(MO);
162 Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
163 return true;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000164}
165
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000166// branch support
167
168bool PTXInstrInfo::
169AnalyzeBranch(MachineBasicBlock &MBB,
170 MachineBasicBlock *&TBB,
171 MachineBasicBlock *&FBB,
172 SmallVectorImpl<MachineOperand> &Cond,
173 bool AllowModify) const {
174 // TODO implement cases when AllowModify is true
175
176 if (MBB.empty())
177 return true;
178
179 MachineBasicBlock::const_iterator iter = MBB.end();
180 const MachineInstr& instLast1 = *--iter;
181 const TargetInstrDesc &desc1 = instLast1.getDesc();
182 // for special case that MBB has only 1 instruction
183 const bool IsSizeOne = MBB.size() == 1;
184 // if IsSizeOne is true, *--iter and instLast2 are invalid
185 // we put a dummy value in instLast2 and desc2 since they are used
186 const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter;
187 const TargetInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
188
189 DEBUG(dbgs() << "\n");
190 DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n");
191 DEBUG(dbgs() << "AnalyzeBranch: MBB: " << MBB.getName().str() << "\n");
192 DEBUG(dbgs() << "AnalyzeBranch: TBB: " << TBB << "\n");
193 DEBUG(dbgs() << "AnalyzeBranch: FBB: " << FBB << "\n");
194
195 // this block ends with no branches
196 if (!IsAnyKindOfBranch(instLast1)) {
197 DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n");
198 return false;
199 }
200
201 // this block ends with only an unconditional branch
202 if (desc1.isUnconditionalBranch() &&
203 // when IsSizeOne is true, it "absorbs" the evaluation of instLast2
204 (IsSizeOne || !IsAnyKindOfBranch(instLast2))) {
205 DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n");
206 TBB = GetBranchTarget(instLast1);
207 return false;
208 }
209
210 // this block ends with a conditional branch and
211 // it falls through to a successor block
212 if (desc1.isConditionalBranch() &&
213 IsAnySuccessorAlsoLayoutSuccessor(MBB)) {
214 DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n");
215 TBB = GetBranchTarget(instLast1);
216 int i = instLast1.findFirstPredOperandIdx();
217 Cond.push_back(instLast1.getOperand(i));
218 Cond.push_back(instLast1.getOperand(i+1));
219 return false;
220 }
221
222 // when IsSizeOne is true, we are done
223 if (IsSizeOne)
224 return true;
225
226 // this block ends with a conditional branch
227 // followed by an unconditional branch
228 if (desc2.isConditionalBranch() &&
229 desc1.isUnconditionalBranch()) {
230 DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n");
231 TBB = GetBranchTarget(instLast2);
232 FBB = GetBranchTarget(instLast1);
233 int i = instLast2.findFirstPredOperandIdx();
234 Cond.push_back(instLast2.getOperand(i));
235 Cond.push_back(instLast2.getOperand(i+1));
236 return false;
237 }
238
239 // branch cannot be understood
240 DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n");
241 return true;
242}
243
244unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000245 unsigned count = 0;
246 while (!MBB.empty())
247 if (IsAnyKindOfBranch(MBB.back())) {
248 MBB.pop_back();
249 ++count;
250 } else
251 break;
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000252 DEBUG(dbgs() << "RemoveBranch: MBB: " << MBB.getName().str() << "\n");
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000253 DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n");
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000254 return count;
255}
256
257unsigned PTXInstrInfo::
258InsertBranch(MachineBasicBlock &MBB,
259 MachineBasicBlock *TBB,
260 MachineBasicBlock *FBB,
261 const SmallVectorImpl<MachineOperand> &Cond,
262 DebugLoc DL) const {
263 DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n");
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000264 DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: " << TBB->getName().str()
265 << "\n";
266 else dbgs() << "InsertBranch: TBB: (NULL)\n");
267 DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: " << FBB->getName().str()
268 << "\n";
269 else dbgs() << "InsertBranch: FBB: (NULL)\n");
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000270 DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n");
271
272 assert(TBB && "TBB is NULL");
273
274 if (FBB) {
275 BuildMI(&MBB, DL, get(PTX::BRAdp))
276 .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
277 BuildMI(&MBB, DL, get(PTX::BRAd))
278 .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
279 return 2;
280 } else if (Cond.size()) {
281 BuildMI(&MBB, DL, get(PTX::BRAdp))
282 .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
283 return 1;
284 } else {
285 BuildMI(&MBB, DL, get(PTX::BRAd))
286 .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
287 return 1;
288 }
289}
290
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000291// Memory operand folding for spills
292void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
293 MachineBasicBlock::iterator MII,
294 unsigned SrcReg, bool isKill, int FrameIdx,
295 const TargetRegisterClass *RC,
296 const TargetRegisterInfo *TRI) const {
297 MachineInstr& MI = *MII;
298 DebugLoc DL = MI.getDebugLoc();
299
300 DEBUG(dbgs() << "storeRegToStackSlot: " << MI);
301
302 int OpCode;
303
304 // Select the appropriate opcode based on the register class
305 if (RC == PTX::RegI16RegisterClass) {
306 OpCode = PTX::STACKSTOREI16;
307 }
308 else if (RC == PTX::RegI32RegisterClass) {
309 OpCode = PTX::STACKSTOREI32;
310 }
311 else if (RC == PTX::RegI64RegisterClass) {
312 OpCode = PTX::STACKSTOREI32;
313 }
314 else if (RC == PTX::RegF32RegisterClass) {
315 OpCode = PTX::STACKSTOREF32;
316 }
317 else if (RC == PTX::RegF64RegisterClass) {
318 OpCode = PTX::STACKSTOREF64;
319 }
320
321 // Build the store instruction (really a mov)
322 MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
323 MIB.addImm(FrameIdx);
324 MIB.addReg(SrcReg);
325
326 AddDefaultPredicate(MIB);
327}
328
329void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
330 MachineBasicBlock::iterator MII,
331 unsigned DestReg, int FrameIdx,
332 const TargetRegisterClass *RC,
333 const TargetRegisterInfo *TRI) const {
334 MachineInstr& MI = *MII;
335 DebugLoc DL = MI.getDebugLoc();
336
337 DEBUG(dbgs() << "loadRegToStackSlot: " << MI);
338
339 int OpCode;
340
341 // Select the appropriate opcode based on the register class
342 if (RC == PTX::RegI16RegisterClass) {
343 OpCode = PTX::STACKLOADI16;
344 }
345 else if (RC == PTX::RegI32RegisterClass) {
346 OpCode = PTX::STACKLOADI32;
347 }
348 else if (RC == PTX::RegI64RegisterClass) {
349 OpCode = PTX::STACKLOADI32;
350 }
351 else if (RC == PTX::RegF32RegisterClass) {
352 OpCode = PTX::STACKLOADF32;
353 }
354 else if (RC == PTX::RegF64RegisterClass) {
355 OpCode = PTX::STACKLOADF64;
356 }
357
358 // Build the load instruction (really a mov)
359 MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
360 MIB.addReg(DestReg);
361 MIB.addImm(FrameIdx);
362
363 AddDefaultPredicate(MIB);
364}
365
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000366// static helper routines
367
368MachineSDNode *PTXInstrInfo::
369GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
370 DebugLoc dl, EVT VT, SDValue Op1) {
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000371 SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
372 SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000373 SDValue ops[] = { Op1, predReg, predOp };
374 return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
375}
376
377MachineSDNode *PTXInstrInfo::
378GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
379 DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000380 SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
381 SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000382 SDValue ops[] = { Op1, Op2, predReg, predOp };
383 return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
384}
385
386void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
387 if (MI->findFirstPredOperandIdx() == -1) {
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000388 MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000389 MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000390 }
391}
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000392
393bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
394 const TargetInstrDesc &desc = inst.getDesc();
395 return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
396}
397
398bool PTXInstrInfo::
399IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
400 for (MachineBasicBlock::const_succ_iterator
401 i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
402 if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
403 return true;
404 return false;
405}
406
407MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
408 // FIXME So far all branch instructions put destination in 1st operand
409 const MachineOperand& target = inst.getOperand(0);
410 assert(target.isMBB() && "FIXME: detect branch target operand");
411 return target.getMBB();
412}