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/MachineRegisterInfo.h"
20#include "llvm/CodeGen/SelectionDAG.h"
21#include "llvm/CodeGen/SelectionDAGNodes.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/TargetRegistry.h"
24#include "llvm/Support/raw_ostream.h"
25
26#define GET_INSTRINFO_CTOR
27#include "PTXGenInstrInfo.inc"
28
29using namespace llvm;
30
31PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM)
32  : PTXGenInstrInfo(),
33    RI(_TM, *this), TM(_TM) {}
34
35static const struct map_entry {
36  const TargetRegisterClass *cls;
37  const int opcode;
38} map[] = {
39  { &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 }
45};
46
47void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
48                               MachineBasicBlock::iterator I, DebugLoc DL,
49                               unsigned DstReg, unsigned SrcReg,
50                               bool KillSrc) const {
51
52  const MachineRegisterInfo& MRI = MBB.getParent()->getRegInfo();
53  //assert(MRI.getRegClass(SrcReg) == MRI.getRegClass(DstReg) &&
54  //  "Invalid register copy between two register classes");
55
56  for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++i) {
57    if (map[i].cls == MRI.getRegClass(DstReg)) {
58      const MCInstrDesc &MCID = get(map[i].opcode);
59      MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).
60        addReg(SrcReg, getKillRegState(KillSrc));
61      AddDefaultPredicate(MI);
62      return;
63    }
64  }
65
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) {
80      const MCInstrDesc &MCID = get(map[i].opcode);
81      MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg);
82      AddDefaultPredicate(MI);
83      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;
95    case PTX::MOVU16rr:
96    case PTX::MOVU32rr:
97    case PTX::MOVU64rr:
98    case PTX::MOVF32rr:
99    case PTX::MOVF64rr:
100    case PTX::MOVPREDrr:
101      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}
110
111// predicate support
112
113bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
114  int i = MI->findFirstPredOperandIdx();
115  return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
116}
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 {
141  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;
152}
153
154bool PTXInstrInfo::
155DefinesPredicate(MachineInstr *MI,
156                 std::vector<MachineOperand> &Pred) const {
157  // If an instruction sets a predicate register, it defines a predicate.
158
159  // TODO supprot 5-operand format of setp instruction
160
161  if (MI->getNumOperands() < 1)
162    return false;
163
164  const MachineOperand &MO = MI->getOperand(0);
165
166  if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass)
167    return false;
168
169  Pred.push_back(MO);
170  Pred.push_back(MachineOperand::CreateImm(PTXPredicate::None));
171  return true;
172}
173
174// 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;
189  const MCInstrDesc &desc1 = instLast1.getDesc();
190  // 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;
195  const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
196
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 {
253  unsigned count = 0;
254  while (!MBB.empty())
255    if (IsAnyKindOfBranch(MBB.back())) {
256      MBB.pop_back();
257      ++count;
258    } else
259      break;
260  DEBUG(dbgs() << "RemoveBranch: MBB:   " << MBB.getName().str() << "\n");
261  DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n");
262  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");
272  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");
278  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(PTXPredicate::None);
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(PTXPredicate::None);
295    return 1;
296  }
297}
298
299// Memory operand folding for spills
300void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
301                                       MachineBasicBlock::iterator MII,
302                                     unsigned SrcReg, bool isKill, int FrameIdx,
303                                       const TargetRegisterClass *RC,
304                                       const TargetRegisterInfo *TRI) const {
305  assert(false && "storeRegToStackSlot should not be called for PTX");
306}
307
308void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
309                                        MachineBasicBlock::iterator MII,
310                                        unsigned DestReg, int FrameIdx,
311                                        const TargetRegisterClass *RC,
312                                        const TargetRegisterInfo *TRI) const {
313  assert(false && "loadRegFromStackSlot should not be called for PTX");
314}
315
316// static helper routines
317
318MachineSDNode *PTXInstrInfo::
319GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
320                  DebugLoc dl, EVT VT, SDValue Op1) {
321  SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
322  SDValue predOp = DAG->getTargetConstant(PTXPredicate::None, MVT::i32);
323  SDValue ops[] = { Op1, predReg, predOp };
324  return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
325}
326
327MachineSDNode *PTXInstrInfo::
328GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
329                  DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
330  SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
331  SDValue predOp = DAG->getTargetConstant(PTXPredicate::None, MVT::i32);
332  SDValue ops[] = { Op1, Op2, predReg, predOp };
333  return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
334}
335
336void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
337  if (MI->findFirstPredOperandIdx() == -1) {
338    MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
339    MI->addOperand(MachineOperand::CreateImm(PTXPredicate::None));
340  }
341}
342
343bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
344  const MCInstrDesc &desc = inst.getDesc();
345  return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
346}
347
348bool PTXInstrInfo::
349IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
350  for (MachineBasicBlock::const_succ_iterator
351      i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
352    if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
353      return true;
354  return false;
355}
356
357MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
358  // FIXME So far all branch instructions put destination in 1st operand
359  const MachineOperand& target = inst.getOperand(0);
360  assert(target.isMBB() && "FIXME: detect branch target operand");
361  return target.getMBB();
362}
363