blob: 1bbd8d5bc58f6a3ddd03305d7591f3d6a271661d [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
Evan Cheng22fee2d2011-06-28 20:07:07 +000024#define GET_INSTRINFO_MC_DESC
Eric Christopher50880d02010-09-18 18:52:28 +000025#include "PTXGenInstrInfo.inc"
26
Evan Cheng22fee2d2011-06-28 20:07:07 +000027using namespace llvm;
28
Eric Christopher50880d02010-09-18 18:52:28 +000029PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM)
30 : TargetInstrInfoImpl(PTXInsts, array_lengthof(PTXInsts)),
31 RI(_TM, *this), TM(_TM) {}
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000032
33static const struct map_entry {
34 const TargetRegisterClass *cls;
35 const int opcode;
36} map[] = {
Justin Holewinski1b91bcd2011-06-16 17:49:58 +000037 { &PTX::RegI16RegClass, PTX::MOVU16rr },
38 { &PTX::RegI32RegClass, PTX::MOVU32rr },
39 { &PTX::RegI64RegClass, PTX::MOVU64rr },
40 { &PTX::RegF32RegClass, PTX::MOVF32rr },
41 { &PTX::RegF64RegClass, PTX::MOVF64rr },
42 { &PTX::RegPredRegClass, PTX::MOVPREDrr }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000043};
44
45void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
46 MachineBasicBlock::iterator I, DebugLoc DL,
47 unsigned DstReg, unsigned SrcReg,
48 bool KillSrc) const {
Che-Liang Chiouf7172022011-02-28 06:34:09 +000049 for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) {
50 if (map[i].cls->contains(DstReg, SrcReg)) {
Evan Chenge837dea2011-06-28 19:10:37 +000051 const MCInstrDesc &MCID = get(map[i].opcode);
52 MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000053 addReg(SrcReg, getKillRegState(KillSrc));
54 AddDefaultPredicate(MI);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000055 return;
56 }
Che-Liang Chiouf7172022011-02-28 06:34:09 +000057 }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000058
59 llvm_unreachable("Impossible reg-to-reg copy");
60}
61
62bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
63 MachineBasicBlock::iterator I,
64 unsigned DstReg, unsigned SrcReg,
65 const TargetRegisterClass *DstRC,
66 const TargetRegisterClass *SrcRC,
67 DebugLoc DL) const {
68 if (DstRC != SrcRC)
69 return false;
70
71 for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i)
72 if (DstRC == map[i].cls) {
Evan Chenge837dea2011-06-28 19:10:37 +000073 const MCInstrDesc &MCID = get(map[i].opcode);
74 MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +000075 AddDefaultPredicate(MI);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000076 return true;
77 }
78
79 return false;
80}
81
82bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
83 unsigned &SrcReg, unsigned &DstReg,
84 unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
85 switch (MI.getOpcode()) {
86 default:
87 return false;
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000088 case PTX::MOVU16rr:
89 case PTX::MOVU32rr:
90 case PTX::MOVU64rr:
91 case PTX::MOVF32rr:
92 case PTX::MOVF64rr:
93 case PTX::MOVPREDrr:
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000094 assert(MI.getNumOperands() >= 2 &&
95 MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
96 "Invalid register-register move instruction");
97 SrcSubIdx = DstSubIdx = 0; // No sub-registers
98 DstReg = MI.getOperand(0).getReg();
99 SrcReg = MI.getOperand(1).getReg();
100 return true;
101 }
102}
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000103
104// predicate support
105
106bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
107 int i = MI->findFirstPredOperandIdx();
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000108 return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000109}
110
111bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
112 return !isPredicated(MI) && get(MI->getOpcode()).isTerminator();
113}
114
115bool PTXInstrInfo::
116PredicateInstruction(MachineInstr *MI,
117 const SmallVectorImpl<MachineOperand> &Pred) const {
118 if (Pred.size() < 2)
119 llvm_unreachable("lesser than 2 predicate operands are provided");
120
121 int i = MI->findFirstPredOperandIdx();
122 if (i == -1)
123 llvm_unreachable("missing predicate operand");
124
125 MI->getOperand(i).setReg(Pred[0].getReg());
126 MI->getOperand(i+1).setImm(Pred[1].getImm());
127
128 return true;
129}
130
131bool PTXInstrInfo::
132SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
133 const SmallVectorImpl<MachineOperand> &Pred2) const {
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000134 const MachineOperand &PredReg1 = Pred1[0];
135 const MachineOperand &PredReg2 = Pred2[0];
136 if (PredReg1.getReg() != PredReg2.getReg())
137 return false;
138
139 const MachineOperand &PredOp1 = Pred1[1];
140 const MachineOperand &PredOp2 = Pred2[1];
141 if (PredOp1.getImm() != PredOp2.getImm())
142 return false;
143
144 return true;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000145}
146
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000147bool PTXInstrInfo::
148DefinesPredicate(MachineInstr *MI,
149 std::vector<MachineOperand> &Pred) const {
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000150 // If an instruction sets a predicate register, it defines a predicate.
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000151
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000152 // TODO supprot 5-operand format of setp instruction
153
154 if (MI->getNumOperands() < 1)
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000155 return false;
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000156
157 const MachineOperand &MO = MI->getOperand(0);
158
Justin Holewinski1b91bcd2011-06-16 17:49:58 +0000159 if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass)
Che-Liang Chiou357be5e2011-04-02 08:51:39 +0000160 return false;
161
162 Pred.push_back(MO);
163 Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
164 return true;
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000165}
166
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000167// branch support
168
169bool PTXInstrInfo::
170AnalyzeBranch(MachineBasicBlock &MBB,
171 MachineBasicBlock *&TBB,
172 MachineBasicBlock *&FBB,
173 SmallVectorImpl<MachineOperand> &Cond,
174 bool AllowModify) const {
175 // TODO implement cases when AllowModify is true
176
177 if (MBB.empty())
178 return true;
179
180 MachineBasicBlock::const_iterator iter = MBB.end();
181 const MachineInstr& instLast1 = *--iter;
Evan Chenge837dea2011-06-28 19:10:37 +0000182 const MCInstrDesc &desc1 = instLast1.getDesc();
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000183 // for special case that MBB has only 1 instruction
184 const bool IsSizeOne = MBB.size() == 1;
185 // if IsSizeOne is true, *--iter and instLast2 are invalid
186 // we put a dummy value in instLast2 and desc2 since they are used
187 const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter;
Evan Chenge837dea2011-06-28 19:10:37 +0000188 const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000189
190 DEBUG(dbgs() << "\n");
191 DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n");
192 DEBUG(dbgs() << "AnalyzeBranch: MBB: " << MBB.getName().str() << "\n");
193 DEBUG(dbgs() << "AnalyzeBranch: TBB: " << TBB << "\n");
194 DEBUG(dbgs() << "AnalyzeBranch: FBB: " << FBB << "\n");
195
196 // this block ends with no branches
197 if (!IsAnyKindOfBranch(instLast1)) {
198 DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n");
199 return false;
200 }
201
202 // this block ends with only an unconditional branch
203 if (desc1.isUnconditionalBranch() &&
204 // when IsSizeOne is true, it "absorbs" the evaluation of instLast2
205 (IsSizeOne || !IsAnyKindOfBranch(instLast2))) {
206 DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n");
207 TBB = GetBranchTarget(instLast1);
208 return false;
209 }
210
211 // this block ends with a conditional branch and
212 // it falls through to a successor block
213 if (desc1.isConditionalBranch() &&
214 IsAnySuccessorAlsoLayoutSuccessor(MBB)) {
215 DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n");
216 TBB = GetBranchTarget(instLast1);
217 int i = instLast1.findFirstPredOperandIdx();
218 Cond.push_back(instLast1.getOperand(i));
219 Cond.push_back(instLast1.getOperand(i+1));
220 return false;
221 }
222
223 // when IsSizeOne is true, we are done
224 if (IsSizeOne)
225 return true;
226
227 // this block ends with a conditional branch
228 // followed by an unconditional branch
229 if (desc2.isConditionalBranch() &&
230 desc1.isUnconditionalBranch()) {
231 DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n");
232 TBB = GetBranchTarget(instLast2);
233 FBB = GetBranchTarget(instLast1);
234 int i = instLast2.findFirstPredOperandIdx();
235 Cond.push_back(instLast2.getOperand(i));
236 Cond.push_back(instLast2.getOperand(i+1));
237 return false;
238 }
239
240 // branch cannot be understood
241 DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n");
242 return true;
243}
244
245unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000246 unsigned count = 0;
247 while (!MBB.empty())
248 if (IsAnyKindOfBranch(MBB.back())) {
249 MBB.pop_back();
250 ++count;
251 } else
252 break;
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000253 DEBUG(dbgs() << "RemoveBranch: MBB: " << MBB.getName().str() << "\n");
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000254 DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n");
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000255 return count;
256}
257
258unsigned PTXInstrInfo::
259InsertBranch(MachineBasicBlock &MBB,
260 MachineBasicBlock *TBB,
261 MachineBasicBlock *FBB,
262 const SmallVectorImpl<MachineOperand> &Cond,
263 DebugLoc DL) const {
264 DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n");
Che-Liang Chioufb4a8342011-03-28 10:23:13 +0000265 DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: " << TBB->getName().str()
266 << "\n";
267 else dbgs() << "InsertBranch: TBB: (NULL)\n");
268 DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: " << FBB->getName().str()
269 << "\n";
270 else dbgs() << "InsertBranch: FBB: (NULL)\n");
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000271 DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n");
272
273 assert(TBB && "TBB is NULL");
274
275 if (FBB) {
276 BuildMI(&MBB, DL, get(PTX::BRAdp))
277 .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
278 BuildMI(&MBB, DL, get(PTX::BRAd))
279 .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
280 return 2;
281 } else if (Cond.size()) {
282 BuildMI(&MBB, DL, get(PTX::BRAdp))
283 .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
284 return 1;
285 } else {
286 BuildMI(&MBB, DL, get(PTX::BRAd))
287 .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
288 return 1;
289 }
290}
291
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000292// Memory operand folding for spills
293void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
294 MachineBasicBlock::iterator MII,
Justin Holewinski08d03162011-06-22 16:07:03 +0000295 unsigned SrcReg, bool isKill, int FrameIdx,
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000296 const TargetRegisterClass *RC,
297 const TargetRegisterInfo *TRI) const {
298 MachineInstr& MI = *MII;
299 DebugLoc DL = MI.getDebugLoc();
300
301 DEBUG(dbgs() << "storeRegToStackSlot: " << MI);
302
303 int OpCode;
304
305 // Select the appropriate opcode based on the register class
Dan Bailey84149462011-06-25 18:16:28 +0000306 if (RC == PTX::RegI16RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000307 OpCode = PTX::STACKSTOREI16;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000308 } else if (RC == PTX::RegI32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000309 OpCode = PTX::STACKSTOREI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000310 } else if (RC == PTX::RegI64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000311 OpCode = PTX::STACKSTOREI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000312 } else if (RC == PTX::RegF32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000313 OpCode = PTX::STACKSTOREF32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000314 } else if (RC == PTX::RegF64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000315 OpCode = PTX::STACKSTOREF64;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000316 } else {
317 llvm_unreachable("Unknown PTX register class!");
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000318 }
319
320 // Build the store instruction (really a mov)
321 MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
Justin Holewinski08d03162011-06-22 16:07:03 +0000322 MIB.addFrameIndex(FrameIdx);
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000323 MIB.addReg(SrcReg);
324
325 AddDefaultPredicate(MIB);
326}
327
328void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
329 MachineBasicBlock::iterator MII,
330 unsigned DestReg, int FrameIdx,
331 const TargetRegisterClass *RC,
332 const TargetRegisterInfo *TRI) const {
333 MachineInstr& MI = *MII;
334 DebugLoc DL = MI.getDebugLoc();
335
336 DEBUG(dbgs() << "loadRegToStackSlot: " << MI);
337
338 int OpCode;
339
340 // Select the appropriate opcode based on the register class
Dan Bailey84149462011-06-25 18:16:28 +0000341 if (RC == PTX::RegI16RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000342 OpCode = PTX::STACKLOADI16;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000343 } else if (RC == PTX::RegI32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000344 OpCode = PTX::STACKLOADI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000345 } else if (RC == PTX::RegI64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000346 OpCode = PTX::STACKLOADI32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000347 } else if (RC == PTX::RegF32RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000348 OpCode = PTX::STACKLOADF32;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000349 } else if (RC == PTX::RegF64RegisterClass) {
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000350 OpCode = PTX::STACKLOADF64;
Justin Holewinskicad129b2011-06-20 17:08:56 +0000351 } else {
352 llvm_unreachable("Unknown PTX register class!");
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000353 }
354
355 // Build the load instruction (really a mov)
356 MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
357 MIB.addReg(DestReg);
Justin Holewinski08d03162011-06-22 16:07:03 +0000358 MIB.addFrameIndex(FrameIdx);
Justin Holewinskidf1c8d82011-06-20 15:56:20 +0000359
360 AddDefaultPredicate(MIB);
361}
362
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000363// static helper routines
364
365MachineSDNode *PTXInstrInfo::
366GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
367 DebugLoc dl, EVT VT, SDValue Op1) {
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000368 SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
369 SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000370 SDValue ops[] = { Op1, predReg, predOp };
371 return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
372}
373
374MachineSDNode *PTXInstrInfo::
375GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
376 DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000377 SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
378 SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000379 SDValue ops[] = { Op1, Op2, predReg, predOp };
380 return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
381}
382
383void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
384 if (MI->findFirstPredOperandIdx() == -1) {
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000385 MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
Che-Liang Chiouf78847e2011-03-14 11:26:01 +0000386 MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
Che-Liang Chiouc2ec0f92011-03-13 17:26:00 +0000387 }
388}
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000389
390bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
Evan Chenge837dea2011-06-28 19:10:37 +0000391 const MCInstrDesc &desc = inst.getDesc();
Che-Liang Chiou5e0872e2011-03-22 14:12:00 +0000392 return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
393}
394
395bool PTXInstrInfo::
396IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
397 for (MachineBasicBlock::const_succ_iterator
398 i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
399 if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
400 return true;
401 return false;
402}
403
404MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
405 // FIXME So far all branch instructions put destination in 1st operand
406 const MachineOperand& target = inst.getOperand(0);
407 assert(target.isMBB() && "FIXME: detect branch target operand");
408 return target.getMBB();
409}