1 //===- NVPTXInstrInfo.cpp - NVPTX 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 NVPTX implementation of the TargetInstrInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "NVPTX.h" 15 #include "NVPTXInstrInfo.h" 16 #include "NVPTXTargetMachine.h" 17 #define GET_INSTRINFO_CTOR 18 #include "NVPTXGenInstrInfo.inc" 19 #include "llvm/Function.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include <cstdio> 25 26 27 using namespace llvm; 28 29 // FIXME: Add the subtarget support on this constructor. 30 NVPTXInstrInfo::NVPTXInstrInfo(NVPTXTargetMachine &tm) 31 : NVPTXGenInstrInfo(), 32 TM(tm), 33 RegInfo(*this, *TM.getSubtargetImpl()) {} 34 35 36 void NVPTXInstrInfo::copyPhysReg (MachineBasicBlock &MBB, 37 MachineBasicBlock::iterator I, DebugLoc DL, 38 unsigned DestReg, unsigned SrcReg, 39 bool KillSrc) const { 40 if (NVPTX::Int32RegsRegClass.contains(DestReg) && 41 NVPTX::Int32RegsRegClass.contains(SrcReg)) 42 BuildMI(MBB, I, DL, get(NVPTX::IMOV32rr), DestReg) 43 .addReg(SrcReg, getKillRegState(KillSrc)); 44 else if (NVPTX::Int8RegsRegClass.contains(DestReg) && 45 NVPTX::Int8RegsRegClass.contains(SrcReg)) 46 BuildMI(MBB, I, DL, get(NVPTX::IMOV8rr), DestReg) 47 .addReg(SrcReg, getKillRegState(KillSrc)); 48 else if (NVPTX::Int1RegsRegClass.contains(DestReg) && 49 NVPTX::Int1RegsRegClass.contains(SrcReg)) 50 BuildMI(MBB, I, DL, get(NVPTX::IMOV1rr), DestReg) 51 .addReg(SrcReg, getKillRegState(KillSrc)); 52 else if (NVPTX::Float32RegsRegClass.contains(DestReg) && 53 NVPTX::Float32RegsRegClass.contains(SrcReg)) 54 BuildMI(MBB, I, DL, get(NVPTX::FMOV32rr), DestReg) 55 .addReg(SrcReg, getKillRegState(KillSrc)); 56 else if (NVPTX::Int16RegsRegClass.contains(DestReg) && 57 NVPTX::Int16RegsRegClass.contains(SrcReg)) 58 BuildMI(MBB, I, DL, get(NVPTX::IMOV16rr), DestReg) 59 .addReg(SrcReg, getKillRegState(KillSrc)); 60 else if (NVPTX::Int64RegsRegClass.contains(DestReg) && 61 NVPTX::Int64RegsRegClass.contains(SrcReg)) 62 BuildMI(MBB, I, DL, get(NVPTX::IMOV64rr), DestReg) 63 .addReg(SrcReg, getKillRegState(KillSrc)); 64 else if (NVPTX::Float64RegsRegClass.contains(DestReg) && 65 NVPTX::Float64RegsRegClass.contains(SrcReg)) 66 BuildMI(MBB, I, DL, get(NVPTX::FMOV64rr), DestReg) 67 .addReg(SrcReg, getKillRegState(KillSrc)); 68 else if (NVPTX::V4F32RegsRegClass.contains(DestReg) && 69 NVPTX::V4F32RegsRegClass.contains(SrcReg)) 70 BuildMI(MBB, I, DL, get(NVPTX::V4f32Mov), DestReg) 71 .addReg(SrcReg, getKillRegState(KillSrc)); 72 else if (NVPTX::V4I32RegsRegClass.contains(DestReg) && 73 NVPTX::V4I32RegsRegClass.contains(SrcReg)) 74 BuildMI(MBB, I, DL, get(NVPTX::V4i32Mov), DestReg) 75 .addReg(SrcReg, getKillRegState(KillSrc)); 76 else if (NVPTX::V2F32RegsRegClass.contains(DestReg) && 77 NVPTX::V2F32RegsRegClass.contains(SrcReg)) 78 BuildMI(MBB, I, DL, get(NVPTX::V2f32Mov), DestReg) 79 .addReg(SrcReg, getKillRegState(KillSrc)); 80 else if (NVPTX::V2I32RegsRegClass.contains(DestReg) && 81 NVPTX::V2I32RegsRegClass.contains(SrcReg)) 82 BuildMI(MBB, I, DL, get(NVPTX::V2i32Mov), DestReg) 83 .addReg(SrcReg, getKillRegState(KillSrc)); 84 else if (NVPTX::V4I8RegsRegClass.contains(DestReg) && 85 NVPTX::V4I8RegsRegClass.contains(SrcReg)) 86 BuildMI(MBB, I, DL, get(NVPTX::V4i8Mov), DestReg) 87 .addReg(SrcReg, getKillRegState(KillSrc)); 88 else if (NVPTX::V2I8RegsRegClass.contains(DestReg) && 89 NVPTX::V2I8RegsRegClass.contains(SrcReg)) 90 BuildMI(MBB, I, DL, get(NVPTX::V2i8Mov), DestReg) 91 .addReg(SrcReg, getKillRegState(KillSrc)); 92 else if (NVPTX::V4I16RegsRegClass.contains(DestReg) && 93 NVPTX::V4I16RegsRegClass.contains(SrcReg)) 94 BuildMI(MBB, I, DL, get(NVPTX::V4i16Mov), DestReg) 95 .addReg(SrcReg, getKillRegState(KillSrc)); 96 else if (NVPTX::V2I16RegsRegClass.contains(DestReg) && 97 NVPTX::V2I16RegsRegClass.contains(SrcReg)) 98 BuildMI(MBB, I, DL, get(NVPTX::V2i16Mov), DestReg) 99 .addReg(SrcReg, getKillRegState(KillSrc)); 100 else if (NVPTX::V2I64RegsRegClass.contains(DestReg) && 101 NVPTX::V2I64RegsRegClass.contains(SrcReg)) 102 BuildMI(MBB, I, DL, get(NVPTX::V2i64Mov), DestReg) 103 .addReg(SrcReg, getKillRegState(KillSrc)); 104 else if (NVPTX::V2F64RegsRegClass.contains(DestReg) && 105 NVPTX::V2F64RegsRegClass.contains(SrcReg)) 106 BuildMI(MBB, I, DL, get(NVPTX::V2f64Mov), DestReg) 107 .addReg(SrcReg, getKillRegState(KillSrc)); 108 else { 109 llvm_unreachable("Don't know how to copy a register"); 110 } 111 } 112 113 bool NVPTXInstrInfo::isMoveInstr(const MachineInstr &MI, 114 unsigned &SrcReg, 115 unsigned &DestReg) const { 116 // Look for the appropriate part of TSFlags 117 bool isMove = false; 118 119 unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::SimpleMoveMask) >> 120 NVPTX::SimpleMoveShift; 121 isMove = (TSFlags == 1); 122 123 if (isMove) { 124 MachineOperand dest = MI.getOperand(0); 125 MachineOperand src = MI.getOperand(1); 126 assert(dest.isReg() && "dest of a movrr is not a reg"); 127 assert(src.isReg() && "src of a movrr is not a reg"); 128 129 SrcReg = src.getReg(); 130 DestReg = dest.getReg(); 131 return true; 132 } 133 134 return false; 135 } 136 137 bool NVPTXInstrInfo::isReadSpecialReg(MachineInstr &MI) const 138 { 139 switch (MI.getOpcode()) { 140 default: return false; 141 case NVPTX::INT_PTX_SREG_NTID_X: 142 case NVPTX::INT_PTX_SREG_NTID_Y: 143 case NVPTX::INT_PTX_SREG_NTID_Z: 144 case NVPTX::INT_PTX_SREG_TID_X: 145 case NVPTX::INT_PTX_SREG_TID_Y: 146 case NVPTX::INT_PTX_SREG_TID_Z: 147 case NVPTX::INT_PTX_SREG_CTAID_X: 148 case NVPTX::INT_PTX_SREG_CTAID_Y: 149 case NVPTX::INT_PTX_SREG_CTAID_Z: 150 case NVPTX::INT_PTX_SREG_NCTAID_X: 151 case NVPTX::INT_PTX_SREG_NCTAID_Y: 152 case NVPTX::INT_PTX_SREG_NCTAID_Z: 153 case NVPTX::INT_PTX_SREG_WARPSIZE: 154 return true; 155 } 156 } 157 158 159 bool NVPTXInstrInfo::isLoadInstr(const MachineInstr &MI, 160 unsigned &AddrSpace) const { 161 bool isLoad = false; 162 unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::isLoadMask) >> 163 NVPTX::isLoadShift; 164 isLoad = (TSFlags == 1); 165 if (isLoad) 166 AddrSpace = getLdStCodeAddrSpace(MI); 167 return isLoad; 168 } 169 170 bool NVPTXInstrInfo::isStoreInstr(const MachineInstr &MI, 171 unsigned &AddrSpace) const { 172 bool isStore = false; 173 unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::isStoreMask) >> 174 NVPTX::isStoreShift; 175 isStore = (TSFlags == 1); 176 if (isStore) 177 AddrSpace = getLdStCodeAddrSpace(MI); 178 return isStore; 179 } 180 181 182 bool NVPTXInstrInfo::CanTailMerge(const MachineInstr *MI) const { 183 unsigned addrspace = 0; 184 if (MI->getOpcode() == NVPTX::INT_CUDA_SYNCTHREADS) 185 return false; 186 if (isLoadInstr(*MI, addrspace)) 187 if (addrspace == NVPTX::PTXLdStInstCode::SHARED) 188 return false; 189 if (isStoreInstr(*MI, addrspace)) 190 if (addrspace == NVPTX::PTXLdStInstCode::SHARED) 191 return false; 192 return true; 193 } 194 195 196 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning 197 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't 198 /// implemented for a target). Upon success, this returns false and returns 199 /// with the following information in various cases: 200 /// 201 /// 1. If this block ends with no branches (it just falls through to its succ) 202 /// just return false, leaving TBB/FBB null. 203 /// 2. If this block ends with only an unconditional branch, it sets TBB to be 204 /// the destination block. 205 /// 3. If this block ends with an conditional branch and it falls through to 206 /// an successor block, it sets TBB to be the branch destination block and a 207 /// list of operands that evaluate the condition. These 208 /// operands can be passed to other TargetInstrInfo methods to create new 209 /// branches. 210 /// 4. If this block ends with an conditional branch and an unconditional 211 /// block, it returns the 'true' destination in TBB, the 'false' destination 212 /// in FBB, and a list of operands that evaluate the condition. These 213 /// operands can be passed to other TargetInstrInfo methods to create new 214 /// branches. 215 /// 216 /// Note that RemoveBranch and InsertBranch must be implemented to support 217 /// cases where this method returns success. 218 /// 219 bool NVPTXInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, 220 MachineBasicBlock *&TBB, 221 MachineBasicBlock *&FBB, 222 SmallVectorImpl<MachineOperand> &Cond, 223 bool AllowModify) const { 224 // If the block has no terminators, it just falls into the block after it. 225 MachineBasicBlock::iterator I = MBB.end(); 226 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) 227 return false; 228 229 // Get the last instruction in the block. 230 MachineInstr *LastInst = I; 231 232 // If there is only one terminator instruction, process it. 233 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 234 if (LastInst->getOpcode() == NVPTX::GOTO) { 235 TBB = LastInst->getOperand(0).getMBB(); 236 return false; 237 } else if (LastInst->getOpcode() == NVPTX::CBranch) { 238 // Block ends with fall-through condbranch. 239 TBB = LastInst->getOperand(1).getMBB(); 240 Cond.push_back(LastInst->getOperand(0)); 241 return false; 242 } 243 // Otherwise, don't know what this is. 244 return true; 245 } 246 247 // Get the instruction before it if it's a terminator. 248 MachineInstr *SecondLastInst = I; 249 250 // If there are three terminators, we don't know what sort of block this is. 251 if (SecondLastInst && I != MBB.begin() && 252 isUnpredicatedTerminator(--I)) 253 return true; 254 255 // If the block ends with NVPTX::GOTO and NVPTX:CBranch, handle it. 256 if (SecondLastInst->getOpcode() == NVPTX::CBranch && 257 LastInst->getOpcode() == NVPTX::GOTO) { 258 TBB = SecondLastInst->getOperand(1).getMBB(); 259 Cond.push_back(SecondLastInst->getOperand(0)); 260 FBB = LastInst->getOperand(0).getMBB(); 261 return false; 262 } 263 264 // If the block ends with two NVPTX:GOTOs, handle it. The second one is not 265 // executed, so remove it. 266 if (SecondLastInst->getOpcode() == NVPTX::GOTO && 267 LastInst->getOpcode() == NVPTX::GOTO) { 268 TBB = SecondLastInst->getOperand(0).getMBB(); 269 I = LastInst; 270 if (AllowModify) 271 I->eraseFromParent(); 272 return false; 273 } 274 275 // Otherwise, can't handle this. 276 return true; 277 } 278 279 unsigned NVPTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 280 MachineBasicBlock::iterator I = MBB.end(); 281 if (I == MBB.begin()) return 0; 282 --I; 283 if (I->getOpcode() != NVPTX::GOTO && I->getOpcode() != NVPTX::CBranch) 284 return 0; 285 286 // Remove the branch. 287 I->eraseFromParent(); 288 289 I = MBB.end(); 290 291 if (I == MBB.begin()) return 1; 292 --I; 293 if (I->getOpcode() != NVPTX::CBranch) 294 return 1; 295 296 // Remove the branch. 297 I->eraseFromParent(); 298 return 2; 299 } 300 301 unsigned 302 NVPTXInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 303 MachineBasicBlock *FBB, 304 const SmallVectorImpl<MachineOperand> &Cond, 305 DebugLoc DL) const { 306 // Shouldn't be a fall through. 307 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 308 assert((Cond.size() == 1 || Cond.size() == 0) && 309 "NVPTX branch conditions have two components!"); 310 311 // One-way branch. 312 if (FBB == 0) { 313 if (Cond.empty()) // Unconditional branch 314 BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(TBB); 315 else // Conditional branch 316 BuildMI(&MBB, DL, get(NVPTX::CBranch)) 317 .addReg(Cond[0].getReg()).addMBB(TBB); 318 return 1; 319 } 320 321 // Two-way Conditional Branch. 322 BuildMI(&MBB, DL, get(NVPTX::CBranch)) 323 .addReg(Cond[0].getReg()).addMBB(TBB); 324 BuildMI(&MBB, DL, get(NVPTX::GOTO)).addMBB(FBB); 325 return 2; 326 } 327