1 //===-- AMDGPUInstrInfo.cpp - Base class for AMD GPU InstrInfo ------------===// 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 /// \file 11 /// \brief Implementation of the TargetInstrInfo class that is common to all 12 /// AMD GPUs. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "AMDGPUInstrInfo.h" 17 #include "AMDGPURegisterInfo.h" 18 #include "AMDGPUTargetMachine.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/MachineRegisterInfo.h" 22 23 using namespace llvm; 24 25 #define GET_INSTRINFO_CTOR_DTOR 26 #define GET_INSTRINFO_NAMED_OPS 27 #define GET_INSTRMAP_INFO 28 #include "AMDGPUGenInstrInfo.inc" 29 30 // Pin the vtable to this file. 31 void AMDGPUInstrInfo::anchor() {} 32 33 AMDGPUInstrInfo::AMDGPUInstrInfo(const AMDGPUSubtarget &st) 34 : AMDGPUGenInstrInfo(-1,-1), RI(st), ST(st) { } 35 36 const AMDGPURegisterInfo &AMDGPUInstrInfo::getRegisterInfo() const { 37 return RI; 38 } 39 40 bool AMDGPUInstrInfo::isCoalescableExtInstr(const MachineInstr &MI, 41 unsigned &SrcReg, unsigned &DstReg, 42 unsigned &SubIdx) const { 43 // TODO: Implement this function 44 return false; 45 } 46 47 unsigned AMDGPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 48 int &FrameIndex) const { 49 // TODO: Implement this function 50 return 0; 51 } 52 53 unsigned AMDGPUInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI, 54 int &FrameIndex) const { 55 // TODO: Implement this function 56 return 0; 57 } 58 59 bool AMDGPUInstrInfo::hasLoadFromStackSlot(const MachineInstr *MI, 60 const MachineMemOperand *&MMO, 61 int &FrameIndex) const { 62 // TODO: Implement this function 63 return false; 64 } 65 unsigned AMDGPUInstrInfo::isStoreFromStackSlot(const MachineInstr *MI, 66 int &FrameIndex) const { 67 // TODO: Implement this function 68 return 0; 69 } 70 unsigned AMDGPUInstrInfo::isStoreFromStackSlotPostFE(const MachineInstr *MI, 71 int &FrameIndex) const { 72 // TODO: Implement this function 73 return 0; 74 } 75 bool AMDGPUInstrInfo::hasStoreFromStackSlot(const MachineInstr *MI, 76 const MachineMemOperand *&MMO, 77 int &FrameIndex) const { 78 // TODO: Implement this function 79 return false; 80 } 81 82 MachineInstr * 83 AMDGPUInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, 84 MachineBasicBlock::iterator &MBBI, 85 LiveVariables *LV) const { 86 // TODO: Implement this function 87 return nullptr; 88 } 89 bool AMDGPUInstrInfo::getNextBranchInstr(MachineBasicBlock::iterator &iter, 90 MachineBasicBlock &MBB) const { 91 while (iter != MBB.end()) { 92 switch (iter->getOpcode()) { 93 default: 94 break; 95 case AMDGPU::BRANCH_COND_i32: 96 case AMDGPU::BRANCH_COND_f32: 97 case AMDGPU::BRANCH: 98 return true; 99 }; 100 ++iter; 101 } 102 return false; 103 } 104 105 void 106 AMDGPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 107 MachineBasicBlock::iterator MI, 108 unsigned SrcReg, bool isKill, 109 int FrameIndex, 110 const TargetRegisterClass *RC, 111 const TargetRegisterInfo *TRI) const { 112 llvm_unreachable("Not Implemented"); 113 } 114 115 void 116 AMDGPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 117 MachineBasicBlock::iterator MI, 118 unsigned DestReg, int FrameIndex, 119 const TargetRegisterClass *RC, 120 const TargetRegisterInfo *TRI) const { 121 llvm_unreachable("Not Implemented"); 122 } 123 124 bool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const { 125 MachineBasicBlock *MBB = MI->getParent(); 126 int OffsetOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), 127 AMDGPU::OpName::addr); 128 // addr is a custom operand with multiple MI operands, and only the 129 // first MI operand is given a name. 130 int RegOpIdx = OffsetOpIdx + 1; 131 int ChanOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), 132 AMDGPU::OpName::chan); 133 if (isRegisterLoad(*MI)) { 134 int DstOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), 135 AMDGPU::OpName::dst); 136 unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); 137 unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); 138 unsigned Address = calculateIndirectAddress(RegIndex, Channel); 139 unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); 140 if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { 141 buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(), 142 getIndirectAddrRegClass()->getRegister(Address)); 143 } else { 144 buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(), 145 Address, OffsetReg); 146 } 147 } else if (isRegisterStore(*MI)) { 148 int ValOpIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), 149 AMDGPU::OpName::val); 150 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst); 151 unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); 152 unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); 153 unsigned Address = calculateIndirectAddress(RegIndex, Channel); 154 unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); 155 if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { 156 buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address), 157 MI->getOperand(ValOpIdx).getReg()); 158 } else { 159 buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(), 160 calculateIndirectAddress(RegIndex, Channel), 161 OffsetReg); 162 } 163 } else { 164 return false; 165 } 166 167 MBB->erase(MI); 168 return true; 169 } 170 171 172 MachineInstr * 173 AMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 174 MachineInstr *MI, 175 const SmallVectorImpl<unsigned> &Ops, 176 int FrameIndex) const { 177 // TODO: Implement this function 178 return nullptr; 179 } 180 MachineInstr* 181 AMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 182 MachineInstr *MI, 183 const SmallVectorImpl<unsigned> &Ops, 184 MachineInstr *LoadMI) const { 185 // TODO: Implement this function 186 return nullptr; 187 } 188 bool 189 AMDGPUInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, 190 const SmallVectorImpl<unsigned> &Ops) const { 191 // TODO: Implement this function 192 return false; 193 } 194 bool 195 AMDGPUInstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, 196 unsigned Reg, bool UnfoldLoad, 197 bool UnfoldStore, 198 SmallVectorImpl<MachineInstr*> &NewMIs) const { 199 // TODO: Implement this function 200 return false; 201 } 202 203 bool 204 AMDGPUInstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, 205 SmallVectorImpl<SDNode*> &NewNodes) const { 206 // TODO: Implement this function 207 return false; 208 } 209 210 unsigned 211 AMDGPUInstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc, 212 bool UnfoldLoad, bool UnfoldStore, 213 unsigned *LoadRegIndex) const { 214 // TODO: Implement this function 215 return 0; 216 } 217 218 bool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, 219 int64_t Offset1, int64_t Offset2, 220 unsigned NumLoads) const { 221 assert(Offset2 > Offset1 222 && "Second offset should be larger than first offset!"); 223 // If we have less than 16 loads in a row, and the offsets are within 16, 224 // then schedule together. 225 // TODO: Make the loads schedule near if it fits in a cacheline 226 return (NumLoads < 16 && (Offset2 - Offset1) < 16); 227 } 228 229 bool 230 AMDGPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) 231 const { 232 // TODO: Implement this function 233 return true; 234 } 235 void AMDGPUInstrInfo::insertNoop(MachineBasicBlock &MBB, 236 MachineBasicBlock::iterator MI) const { 237 // TODO: Implement this function 238 } 239 240 bool AMDGPUInstrInfo::isPredicated(const MachineInstr *MI) const { 241 // TODO: Implement this function 242 return false; 243 } 244 bool 245 AMDGPUInstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, 246 const SmallVectorImpl<MachineOperand> &Pred2) 247 const { 248 // TODO: Implement this function 249 return false; 250 } 251 252 bool AMDGPUInstrInfo::DefinesPredicate(MachineInstr *MI, 253 std::vector<MachineOperand> &Pred) const { 254 // TODO: Implement this function 255 return false; 256 } 257 258 bool AMDGPUInstrInfo::isPredicable(MachineInstr *MI) const { 259 // TODO: Implement this function 260 return MI->getDesc().isPredicable(); 261 } 262 263 bool 264 AMDGPUInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { 265 // TODO: Implement this function 266 return true; 267 } 268 269 bool AMDGPUInstrInfo::isRegisterStore(const MachineInstr &MI) const { 270 return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_STORE; 271 } 272 273 bool AMDGPUInstrInfo::isRegisterLoad(const MachineInstr &MI) const { 274 return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_LOAD; 275 } 276 277 int AMDGPUInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const { 278 const MachineRegisterInfo &MRI = MF.getRegInfo(); 279 const MachineFrameInfo *MFI = MF.getFrameInfo(); 280 int Offset = -1; 281 282 if (MFI->getNumObjects() == 0) { 283 return -1; 284 } 285 286 if (MRI.livein_empty()) { 287 return 0; 288 } 289 290 const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass(); 291 for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(), 292 LE = MRI.livein_end(); 293 LI != LE; ++LI) { 294 unsigned Reg = LI->first; 295 if (TargetRegisterInfo::isVirtualRegister(Reg) || 296 !IndirectRC->contains(Reg)) 297 continue; 298 299 unsigned RegIndex; 300 unsigned RegEnd; 301 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd; 302 ++RegIndex) { 303 if (IndirectRC->getRegister(RegIndex) == Reg) 304 break; 305 } 306 Offset = std::max(Offset, (int)RegIndex); 307 } 308 309 return Offset + 1; 310 } 311 312 int AMDGPUInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const { 313 int Offset = 0; 314 const MachineFrameInfo *MFI = MF.getFrameInfo(); 315 316 // Variable sized objects are not supported 317 assert(!MFI->hasVarSizedObjects()); 318 319 if (MFI->getNumObjects() == 0) { 320 return -1; 321 } 322 323 Offset = MF.getTarget().getFrameLowering()->getFrameIndexOffset(MF, -1); 324 325 return getIndirectIndexBegin(MF) + Offset; 326 } 327 328 int AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const { 329 switch (Channels) { 330 default: return Opcode; 331 case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1); 332 case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2); 333 case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3); 334 } 335 } 336 337 // Wrapper for Tablegen'd function. enum Subtarget is not defined in any 338 // header files, so we need to wrap it in a function that takes unsigned 339 // instead. 340 namespace llvm { 341 namespace AMDGPU { 342 int getMCOpcode(uint16_t Opcode, unsigned Gen) { 343 return getMCOpcode(Opcode); 344 } 345 } 346 } 347