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 29 using namespace llvm; 30 31 PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM) 32 : PTXGenInstrInfo(), 33 RI(_TM, *this), TM(_TM) {} 34 35 static 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 47 void 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 69 bool 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 89 bool 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 113 bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const { 114 int i = MI->findFirstPredOperandIdx(); 115 return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister; 116 } 117 118 bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { 119 return !isPredicated(MI) && get(MI->getOpcode()).isTerminator(); 120 } 121 122 bool PTXInstrInfo:: 123 PredicateInstruction(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 138 bool PTXInstrInfo:: 139 SubsumesPredicate(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 154 bool PTXInstrInfo:: 155 DefinesPredicate(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 176 bool PTXInstrInfo:: 177 AnalyzeBranch(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 252 unsigned 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 265 unsigned PTXInstrInfo:: 266 InsertBranch(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 300 void 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 308 void 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 318 MachineSDNode *PTXInstrInfo:: 319 GetPTXMachineNode(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 327 MachineSDNode *PTXInstrInfo:: 328 GetPTXMachineNode(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 336 void 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 343 bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) { 344 const MCInstrDesc &desc = inst.getDesc(); 345 return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch(); 346 } 347 348 bool PTXInstrInfo:: 349 IsAnySuccessorAlsoLayoutSuccessor(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 357 MachineBasicBlock *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