• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- 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 
14 #define DEBUG_TYPE "ptx-instrinfo"
15 
16 #include "PTX.h"
17 #include "PTXInstrInfo.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/SelectionDAG.h"
20 #include "llvm/CodeGen/SelectionDAGNodes.h"
21 #include "llvm/Target/TargetRegistry.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 #define GET_INSTRINFO_CTOR
26 #include "PTXGenInstrInfo.inc"
27 
28 using namespace llvm;
29 
PTXInstrInfo(PTXTargetMachine & _TM)30 PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM)
31   : PTXGenInstrInfo(),
32     RI(_TM, *this), TM(_TM) {}
33 
34 static const struct map_entry {
35   const TargetRegisterClass *cls;
36   const int opcode;
37 } map[] = {
38   { &PTX::RegI16RegClass, PTX::MOVU16rr },
39   { &PTX::RegI32RegClass, PTX::MOVU32rr },
40   { &PTX::RegI64RegClass, PTX::MOVU64rr },
41   { &PTX::RegF32RegClass, PTX::MOVF32rr },
42   { &PTX::RegF64RegClass, PTX::MOVF64rr },
43   { &PTX::RegPredRegClass,   PTX::MOVPREDrr }
44 };
45 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,DebugLoc DL,unsigned DstReg,unsigned SrcReg,bool KillSrc) const46 void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
47                                MachineBasicBlock::iterator I, DebugLoc DL,
48                                unsigned DstReg, unsigned SrcReg,
49                                bool KillSrc) const {
50   for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) {
51     if (map[i].cls->contains(DstReg, SrcReg)) {
52       const MCInstrDesc &MCID = get(map[i].opcode);
53       MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).
54         addReg(SrcReg, getKillRegState(KillSrc));
55       AddDefaultPredicate(MI);
56       return;
57     }
58   }
59 
60   llvm_unreachable("Impossible reg-to-reg copy");
61 }
62 
copyRegToReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned DstReg,unsigned SrcReg,const TargetRegisterClass * DstRC,const TargetRegisterClass * SrcRC,DebugLoc DL) const63 bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
64                                 MachineBasicBlock::iterator I,
65                                 unsigned DstReg, unsigned SrcReg,
66                                 const TargetRegisterClass *DstRC,
67                                 const TargetRegisterClass *SrcRC,
68                                 DebugLoc DL) const {
69   if (DstRC != SrcRC)
70     return false;
71 
72   for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i)
73     if (DstRC == map[i].cls) {
74       const MCInstrDesc &MCID = get(map[i].opcode);
75       MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg);
76       AddDefaultPredicate(MI);
77       return true;
78     }
79 
80   return false;
81 }
82 
isMoveInstr(const MachineInstr & MI,unsigned & SrcReg,unsigned & DstReg,unsigned & SrcSubIdx,unsigned & DstSubIdx) const83 bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
84                                unsigned &SrcReg, unsigned &DstReg,
85                                unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
86   switch (MI.getOpcode()) {
87     default:
88       return false;
89     case PTX::MOVU16rr:
90     case PTX::MOVU32rr:
91     case PTX::MOVU64rr:
92     case PTX::MOVF32rr:
93     case PTX::MOVF64rr:
94     case PTX::MOVPREDrr:
95       assert(MI.getNumOperands() >= 2 &&
96              MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
97              "Invalid register-register move instruction");
98       SrcSubIdx = DstSubIdx = 0; // No sub-registers
99       DstReg = MI.getOperand(0).getReg();
100       SrcReg = MI.getOperand(1).getReg();
101       return true;
102   }
103 }
104 
105 // predicate support
106 
isPredicated(const MachineInstr * MI) const107 bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
108   int i = MI->findFirstPredOperandIdx();
109   return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
110 }
111 
isUnpredicatedTerminator(const MachineInstr * MI) const112 bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
113   return !isPredicated(MI) && get(MI->getOpcode()).isTerminator();
114 }
115 
116 bool PTXInstrInfo::
PredicateInstruction(MachineInstr * MI,const SmallVectorImpl<MachineOperand> & Pred) const117 PredicateInstruction(MachineInstr *MI,
118                      const SmallVectorImpl<MachineOperand> &Pred) const {
119   if (Pred.size() < 2)
120     llvm_unreachable("lesser than 2 predicate operands are provided");
121 
122   int i = MI->findFirstPredOperandIdx();
123   if (i == -1)
124     llvm_unreachable("missing predicate operand");
125 
126   MI->getOperand(i).setReg(Pred[0].getReg());
127   MI->getOperand(i+1).setImm(Pred[1].getImm());
128 
129   return true;
130 }
131 
132 bool PTXInstrInfo::
SubsumesPredicate(const SmallVectorImpl<MachineOperand> & Pred1,const SmallVectorImpl<MachineOperand> & Pred2) const133 SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
134                   const SmallVectorImpl<MachineOperand> &Pred2) const {
135   const MachineOperand &PredReg1 = Pred1[0];
136   const MachineOperand &PredReg2 = Pred2[0];
137   if (PredReg1.getReg() != PredReg2.getReg())
138     return false;
139 
140   const MachineOperand &PredOp1 = Pred1[1];
141   const MachineOperand &PredOp2 = Pred2[1];
142   if (PredOp1.getImm() != PredOp2.getImm())
143     return false;
144 
145   return true;
146 }
147 
148 bool PTXInstrInfo::
DefinesPredicate(MachineInstr * MI,std::vector<MachineOperand> & Pred) const149 DefinesPredicate(MachineInstr *MI,
150                  std::vector<MachineOperand> &Pred) const {
151   // If an instruction sets a predicate register, it defines a predicate.
152 
153   // TODO supprot 5-operand format of setp instruction
154 
155   if (MI->getNumOperands() < 1)
156     return false;
157 
158   const MachineOperand &MO = MI->getOperand(0);
159 
160   if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass)
161     return false;
162 
163   Pred.push_back(MO);
164   Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
165   return true;
166 }
167 
168 // branch support
169 
170 bool PTXInstrInfo::
AnalyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const171 AnalyzeBranch(MachineBasicBlock &MBB,
172               MachineBasicBlock *&TBB,
173               MachineBasicBlock *&FBB,
174               SmallVectorImpl<MachineOperand> &Cond,
175               bool AllowModify) const {
176   // TODO implement cases when AllowModify is true
177 
178   if (MBB.empty())
179     return true;
180 
181   MachineBasicBlock::const_iterator iter = MBB.end();
182   const MachineInstr& instLast1 = *--iter;
183   const MCInstrDesc &desc1 = instLast1.getDesc();
184   // for special case that MBB has only 1 instruction
185   const bool IsSizeOne = MBB.size() == 1;
186   // if IsSizeOne is true, *--iter and instLast2 are invalid
187   // we put a dummy value in instLast2 and desc2 since they are used
188   const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter;
189   const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
190 
191   DEBUG(dbgs() << "\n");
192   DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n");
193   DEBUG(dbgs() << "AnalyzeBranch: MBB:    " << MBB.getName().str() << "\n");
194   DEBUG(dbgs() << "AnalyzeBranch: TBB:    " << TBB << "\n");
195   DEBUG(dbgs() << "AnalyzeBranch: FBB:    " << FBB << "\n");
196 
197   // this block ends with no branches
198   if (!IsAnyKindOfBranch(instLast1)) {
199     DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n");
200     return false;
201   }
202 
203   // this block ends with only an unconditional branch
204   if (desc1.isUnconditionalBranch() &&
205       // when IsSizeOne is true, it "absorbs" the evaluation of instLast2
206       (IsSizeOne || !IsAnyKindOfBranch(instLast2))) {
207     DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n");
208     TBB = GetBranchTarget(instLast1);
209     return false;
210   }
211 
212   // this block ends with a conditional branch and
213   // it falls through to a successor block
214   if (desc1.isConditionalBranch() &&
215       IsAnySuccessorAlsoLayoutSuccessor(MBB)) {
216     DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n");
217     TBB = GetBranchTarget(instLast1);
218     int i = instLast1.findFirstPredOperandIdx();
219     Cond.push_back(instLast1.getOperand(i));
220     Cond.push_back(instLast1.getOperand(i+1));
221     return false;
222   }
223 
224   // when IsSizeOne is true, we are done
225   if (IsSizeOne)
226     return true;
227 
228   // this block ends with a conditional branch
229   // followed by an unconditional branch
230   if (desc2.isConditionalBranch() &&
231       desc1.isUnconditionalBranch()) {
232     DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n");
233     TBB = GetBranchTarget(instLast2);
234     FBB = GetBranchTarget(instLast1);
235     int i = instLast2.findFirstPredOperandIdx();
236     Cond.push_back(instLast2.getOperand(i));
237     Cond.push_back(instLast2.getOperand(i+1));
238     return false;
239   }
240 
241   // branch cannot be understood
242   DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n");
243   return true;
244 }
245 
RemoveBranch(MachineBasicBlock & MBB) const246 unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
247   unsigned count = 0;
248   while (!MBB.empty())
249     if (IsAnyKindOfBranch(MBB.back())) {
250       MBB.pop_back();
251       ++count;
252     } else
253       break;
254   DEBUG(dbgs() << "RemoveBranch: MBB:   " << MBB.getName().str() << "\n");
255   DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n");
256   return count;
257 }
258 
259 unsigned PTXInstrInfo::
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,const SmallVectorImpl<MachineOperand> & Cond,DebugLoc DL) const260 InsertBranch(MachineBasicBlock &MBB,
261              MachineBasicBlock *TBB,
262              MachineBasicBlock *FBB,
263              const SmallVectorImpl<MachineOperand> &Cond,
264              DebugLoc DL) const {
265   DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n");
266   DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: " << TBB->getName().str()
267                         << "\n";
268         else     dbgs() << "InsertBranch: TBB: (NULL)\n");
269   DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: " << FBB->getName().str()
270                         << "\n";
271         else     dbgs() << "InsertBranch: FBB: (NULL)\n");
272   DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n");
273 
274   assert(TBB && "TBB is NULL");
275 
276   if (FBB) {
277     BuildMI(&MBB, DL, get(PTX::BRAdp))
278       .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
279     BuildMI(&MBB, DL, get(PTX::BRAd))
280       .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
281     return 2;
282   } else if (Cond.size()) {
283     BuildMI(&MBB, DL, get(PTX::BRAdp))
284       .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
285     return 1;
286   } else {
287     BuildMI(&MBB, DL, get(PTX::BRAd))
288       .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
289     return 1;
290   }
291 }
292 
293 // Memory operand folding for spills
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MII,unsigned SrcReg,bool isKill,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const294 void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
295                                        MachineBasicBlock::iterator MII,
296                                      unsigned SrcReg, bool isKill, int FrameIdx,
297                                        const TargetRegisterClass *RC,
298                                        const TargetRegisterInfo *TRI) const {
299   MachineInstr& MI = *MII;
300   DebugLoc DL = MI.getDebugLoc();
301 
302   DEBUG(dbgs() << "storeRegToStackSlot: " << MI);
303 
304   int OpCode;
305 
306   // Select the appropriate opcode based on the register class
307   if (RC == PTX::RegI16RegisterClass) {
308     OpCode = PTX::STACKSTOREI16;
309   }  else if (RC == PTX::RegI32RegisterClass) {
310     OpCode = PTX::STACKSTOREI32;
311   }  else if (RC == PTX::RegI64RegisterClass) {
312     OpCode = PTX::STACKSTOREI32;
313   }  else if (RC == PTX::RegF32RegisterClass) {
314     OpCode = PTX::STACKSTOREF32;
315   }  else if (RC == PTX::RegF64RegisterClass) {
316     OpCode = PTX::STACKSTOREF64;
317   } else {
318     llvm_unreachable("Unknown PTX register class!");
319   }
320 
321   // Build the store instruction (really a mov)
322   MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
323   MIB.addFrameIndex(FrameIdx);
324   MIB.addReg(SrcReg);
325 
326   AddDefaultPredicate(MIB);
327 }
328 
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MII,unsigned DestReg,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const329 void 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   } else if (RC == PTX::RegI32RegisterClass) {
345     OpCode = PTX::STACKLOADI32;
346   } else if (RC == PTX::RegI64RegisterClass) {
347     OpCode = PTX::STACKLOADI32;
348   } else if (RC == PTX::RegF32RegisterClass) {
349     OpCode = PTX::STACKLOADF32;
350   } else if (RC == PTX::RegF64RegisterClass) {
351     OpCode = PTX::STACKLOADF64;
352   } else {
353     llvm_unreachable("Unknown PTX register class!");
354   }
355 
356   // Build the load instruction (really a mov)
357   MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
358   MIB.addReg(DestReg);
359   MIB.addFrameIndex(FrameIdx);
360 
361   AddDefaultPredicate(MIB);
362 }
363 
364 // static helper routines
365 
366 MachineSDNode *PTXInstrInfo::
GetPTXMachineNode(SelectionDAG * DAG,unsigned Opcode,DebugLoc dl,EVT VT,SDValue Op1)367 GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
368                   DebugLoc dl, EVT VT, SDValue Op1) {
369   SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
370   SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
371   SDValue ops[] = { Op1, predReg, predOp };
372   return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
373 }
374 
375 MachineSDNode *PTXInstrInfo::
GetPTXMachineNode(SelectionDAG * DAG,unsigned Opcode,DebugLoc dl,EVT VT,SDValue Op1,SDValue Op2)376 GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
377                   DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
378   SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
379   SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
380   SDValue ops[] = { Op1, Op2, predReg, predOp };
381   return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
382 }
383 
AddDefaultPredicate(MachineInstr * MI)384 void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
385   if (MI->findFirstPredOperandIdx() == -1) {
386     MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
387     MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
388   }
389 }
390 
IsAnyKindOfBranch(const MachineInstr & inst)391 bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
392   const MCInstrDesc &desc = inst.getDesc();
393   return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
394 }
395 
396 bool PTXInstrInfo::
IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock & MBB)397 IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
398   for (MachineBasicBlock::const_succ_iterator
399       i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
400     if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
401       return true;
402   return false;
403 }
404 
GetBranchTarget(const MachineInstr & inst)405 MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
406   // FIXME So far all branch instructions put destination in 1st operand
407   const MachineOperand& target = inst.getOperand(0);
408   assert(target.isMBB() && "FIXME: detect branch target operand");
409   return target.getMBB();
410 }
411