1249259Sdim//===-- AMDGPUInstrInfo.cpp - Base class for AMD GPU InstrInfo ------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim/// \file 11249259Sdim/// \brief Implementation of the TargetInstrInfo class that is common to all 12249259Sdim/// AMD GPUs. 13249259Sdim// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#include "AMDGPUInstrInfo.h" 17249259Sdim#include "AMDGPURegisterInfo.h" 18249259Sdim#include "AMDGPUTargetMachine.h" 19249259Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 20249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 21249259Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 22249259Sdim 23263508Sdim#define GET_INSTRINFO_CTOR_DTOR 24263508Sdim#define GET_INSTRINFO_NAMED_OPS 25249259Sdim#define GET_INSTRMAP_INFO 26249259Sdim#include "AMDGPUGenInstrInfo.inc" 27249259Sdim 28249259Sdimusing namespace llvm; 29249259Sdim 30263508Sdim 31263508Sdim// Pin the vtable to this file. 32263508Sdimvoid AMDGPUInstrInfo::anchor() {} 33263508Sdim 34249259SdimAMDGPUInstrInfo::AMDGPUInstrInfo(TargetMachine &tm) 35263508Sdim : AMDGPUGenInstrInfo(-1,-1), RI(tm), TM(tm) { } 36249259Sdim 37249259Sdimconst AMDGPURegisterInfo &AMDGPUInstrInfo::getRegisterInfo() const { 38249259Sdim return RI; 39249259Sdim} 40249259Sdim 41249259Sdimbool AMDGPUInstrInfo::isCoalescableExtInstr(const MachineInstr &MI, 42249259Sdim unsigned &SrcReg, unsigned &DstReg, 43249259Sdim unsigned &SubIdx) const { 44249259Sdim// TODO: Implement this function 45249259Sdim return false; 46249259Sdim} 47249259Sdim 48249259Sdimunsigned AMDGPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 49249259Sdim int &FrameIndex) const { 50249259Sdim// TODO: Implement this function 51249259Sdim return 0; 52249259Sdim} 53249259Sdim 54249259Sdimunsigned AMDGPUInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI, 55249259Sdim int &FrameIndex) const { 56249259Sdim// TODO: Implement this function 57249259Sdim return 0; 58249259Sdim} 59249259Sdim 60249259Sdimbool AMDGPUInstrInfo::hasLoadFromStackSlot(const MachineInstr *MI, 61249259Sdim const MachineMemOperand *&MMO, 62249259Sdim int &FrameIndex) const { 63249259Sdim// TODO: Implement this function 64249259Sdim return false; 65249259Sdim} 66249259Sdimunsigned AMDGPUInstrInfo::isStoreFromStackSlot(const MachineInstr *MI, 67249259Sdim int &FrameIndex) const { 68249259Sdim// TODO: Implement this function 69249259Sdim return 0; 70249259Sdim} 71249259Sdimunsigned AMDGPUInstrInfo::isStoreFromStackSlotPostFE(const MachineInstr *MI, 72249259Sdim int &FrameIndex) const { 73249259Sdim// TODO: Implement this function 74249259Sdim return 0; 75249259Sdim} 76249259Sdimbool AMDGPUInstrInfo::hasStoreFromStackSlot(const MachineInstr *MI, 77249259Sdim const MachineMemOperand *&MMO, 78249259Sdim int &FrameIndex) const { 79249259Sdim// TODO: Implement this function 80249259Sdim return false; 81249259Sdim} 82249259Sdim 83249259SdimMachineInstr * 84249259SdimAMDGPUInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, 85249259Sdim MachineBasicBlock::iterator &MBBI, 86249259Sdim LiveVariables *LV) const { 87249259Sdim// TODO: Implement this function 88249259Sdim return NULL; 89249259Sdim} 90249259Sdimbool AMDGPUInstrInfo::getNextBranchInstr(MachineBasicBlock::iterator &iter, 91249259Sdim MachineBasicBlock &MBB) const { 92249259Sdim while (iter != MBB.end()) { 93249259Sdim switch (iter->getOpcode()) { 94249259Sdim default: 95249259Sdim break; 96249259Sdim case AMDGPU::BRANCH_COND_i32: 97249259Sdim case AMDGPU::BRANCH_COND_f32: 98249259Sdim case AMDGPU::BRANCH: 99249259Sdim return true; 100249259Sdim }; 101249259Sdim ++iter; 102249259Sdim } 103249259Sdim return false; 104249259Sdim} 105249259Sdim 106249259Sdimvoid 107249259SdimAMDGPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 108249259Sdim MachineBasicBlock::iterator MI, 109249259Sdim unsigned SrcReg, bool isKill, 110249259Sdim int FrameIndex, 111249259Sdim const TargetRegisterClass *RC, 112249259Sdim const TargetRegisterInfo *TRI) const { 113249259Sdim assert(!"Not Implemented"); 114249259Sdim} 115249259Sdim 116249259Sdimvoid 117249259SdimAMDGPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 118249259Sdim MachineBasicBlock::iterator MI, 119249259Sdim unsigned DestReg, int FrameIndex, 120249259Sdim const TargetRegisterClass *RC, 121249259Sdim const TargetRegisterInfo *TRI) const { 122249259Sdim assert(!"Not Implemented"); 123249259Sdim} 124249259Sdim 125263508Sdimbool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const { 126263508Sdim MachineBasicBlock *MBB = MI->getParent(); 127263508Sdim int OffsetOpIdx = 128263508Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::addr); 129263508Sdim // addr is a custom operand with multiple MI operands, and only the 130263508Sdim // first MI operand is given a name. 131263508Sdim int RegOpIdx = OffsetOpIdx + 1; 132263508Sdim int ChanOpIdx = 133263508Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::chan); 134263508Sdim 135263508Sdim if (isRegisterLoad(*MI)) { 136263508Sdim int DstOpIdx = 137263508Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst); 138263508Sdim unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); 139263508Sdim unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); 140263508Sdim unsigned Address = calculateIndirectAddress(RegIndex, Channel); 141263508Sdim unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); 142263508Sdim if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { 143263508Sdim buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(), 144263508Sdim getIndirectAddrRegClass()->getRegister(Address)); 145263508Sdim } else { 146263508Sdim buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(), 147263508Sdim Address, OffsetReg); 148263508Sdim } 149263508Sdim } else if (isRegisterStore(*MI)) { 150263508Sdim int ValOpIdx = 151263508Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::val); 152263508Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst); 153263508Sdim unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); 154263508Sdim unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); 155263508Sdim unsigned Address = calculateIndirectAddress(RegIndex, Channel); 156263508Sdim unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); 157263508Sdim if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { 158263508Sdim buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address), 159263508Sdim MI->getOperand(ValOpIdx).getReg()); 160263508Sdim } else { 161263508Sdim buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(), 162263508Sdim calculateIndirectAddress(RegIndex, Channel), 163263508Sdim OffsetReg); 164263508Sdim } 165263508Sdim } else { 166263508Sdim return false; 167263508Sdim } 168263508Sdim 169263508Sdim MBB->erase(MI); 170263508Sdim return true; 171263508Sdim} 172263508Sdim 173263508Sdim 174249259SdimMachineInstr * 175249259SdimAMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 176249259Sdim MachineInstr *MI, 177249259Sdim const SmallVectorImpl<unsigned> &Ops, 178249259Sdim int FrameIndex) const { 179249259Sdim// TODO: Implement this function 180249259Sdim return 0; 181249259Sdim} 182249259SdimMachineInstr* 183249259SdimAMDGPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 184249259Sdim MachineInstr *MI, 185249259Sdim const SmallVectorImpl<unsigned> &Ops, 186249259Sdim MachineInstr *LoadMI) const { 187249259Sdim // TODO: Implement this function 188249259Sdim return 0; 189249259Sdim} 190249259Sdimbool 191249259SdimAMDGPUInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, 192249259Sdim const SmallVectorImpl<unsigned> &Ops) const { 193249259Sdim // TODO: Implement this function 194249259Sdim return false; 195249259Sdim} 196249259Sdimbool 197249259SdimAMDGPUInstrInfo::unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, 198249259Sdim unsigned Reg, bool UnfoldLoad, 199249259Sdim bool UnfoldStore, 200249259Sdim SmallVectorImpl<MachineInstr*> &NewMIs) const { 201249259Sdim // TODO: Implement this function 202249259Sdim return false; 203249259Sdim} 204249259Sdim 205249259Sdimbool 206249259SdimAMDGPUInstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, 207249259Sdim SmallVectorImpl<SDNode*> &NewNodes) const { 208249259Sdim // TODO: Implement this function 209249259Sdim return false; 210249259Sdim} 211249259Sdim 212249259Sdimunsigned 213249259SdimAMDGPUInstrInfo::getOpcodeAfterMemoryUnfold(unsigned Opc, 214249259Sdim bool UnfoldLoad, bool UnfoldStore, 215249259Sdim unsigned *LoadRegIndex) const { 216249259Sdim // TODO: Implement this function 217249259Sdim return 0; 218249259Sdim} 219249259Sdim 220249259Sdimbool AMDGPUInstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, 221249259Sdim int64_t Offset1, int64_t Offset2, 222249259Sdim unsigned NumLoads) const { 223249259Sdim assert(Offset2 > Offset1 224249259Sdim && "Second offset should be larger than first offset!"); 225249259Sdim // If we have less than 16 loads in a row, and the offsets are within 16, 226249259Sdim // then schedule together. 227249259Sdim // TODO: Make the loads schedule near if it fits in a cacheline 228249259Sdim return (NumLoads < 16 && (Offset2 - Offset1) < 16); 229249259Sdim} 230249259Sdim 231249259Sdimbool 232249259SdimAMDGPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) 233249259Sdim const { 234249259Sdim // TODO: Implement this function 235249259Sdim return true; 236249259Sdim} 237249259Sdimvoid AMDGPUInstrInfo::insertNoop(MachineBasicBlock &MBB, 238249259Sdim MachineBasicBlock::iterator MI) const { 239249259Sdim // TODO: Implement this function 240249259Sdim} 241249259Sdim 242249259Sdimbool AMDGPUInstrInfo::isPredicated(const MachineInstr *MI) const { 243249259Sdim // TODO: Implement this function 244249259Sdim return false; 245249259Sdim} 246249259Sdimbool 247249259SdimAMDGPUInstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, 248249259Sdim const SmallVectorImpl<MachineOperand> &Pred2) 249249259Sdim const { 250249259Sdim // TODO: Implement this function 251249259Sdim return false; 252249259Sdim} 253249259Sdim 254249259Sdimbool AMDGPUInstrInfo::DefinesPredicate(MachineInstr *MI, 255249259Sdim std::vector<MachineOperand> &Pred) const { 256249259Sdim // TODO: Implement this function 257249259Sdim return false; 258249259Sdim} 259249259Sdim 260249259Sdimbool AMDGPUInstrInfo::isPredicable(MachineInstr *MI) const { 261249259Sdim // TODO: Implement this function 262249259Sdim return MI->getDesc().isPredicable(); 263249259Sdim} 264249259Sdim 265249259Sdimbool 266249259SdimAMDGPUInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { 267249259Sdim // TODO: Implement this function 268249259Sdim return true; 269249259Sdim} 270249259Sdim 271249259Sdimbool AMDGPUInstrInfo::isRegisterStore(const MachineInstr &MI) const { 272249259Sdim return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_STORE; 273249259Sdim} 274249259Sdim 275249259Sdimbool AMDGPUInstrInfo::isRegisterLoad(const MachineInstr &MI) const { 276249259Sdim return get(MI.getOpcode()).TSFlags & AMDGPU_FLAG_REGISTER_LOAD; 277249259Sdim} 278249259Sdim 279263508Sdimint AMDGPUInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const { 280263508Sdim const MachineRegisterInfo &MRI = MF.getRegInfo(); 281263508Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 282263508Sdim int Offset = -1; 283249259Sdim 284263508Sdim if (MFI->getNumObjects() == 0) { 285263508Sdim return -1; 286263508Sdim } 287263508Sdim 288263508Sdim if (MRI.livein_empty()) { 289263508Sdim return 0; 290263508Sdim } 291263508Sdim 292263508Sdim const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass(); 293263508Sdim for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(), 294263508Sdim LE = MRI.livein_end(); 295263508Sdim LI != LE; ++LI) { 296263508Sdim unsigned Reg = LI->first; 297263508Sdim if (TargetRegisterInfo::isVirtualRegister(Reg) || 298263508Sdim !IndirectRC->contains(Reg)) 299263508Sdim continue; 300263508Sdim 301263508Sdim unsigned RegIndex; 302263508Sdim unsigned RegEnd; 303263508Sdim for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd; 304263508Sdim ++RegIndex) { 305263508Sdim if (IndirectRC->getRegister(RegIndex) == Reg) 306263508Sdim break; 307263508Sdim } 308263508Sdim Offset = std::max(Offset, (int)RegIndex); 309263508Sdim } 310263508Sdim 311263508Sdim return Offset + 1; 312263508Sdim} 313263508Sdim 314263508Sdimint AMDGPUInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const { 315263508Sdim int Offset = 0; 316263508Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 317263508Sdim 318263508Sdim // Variable sized objects are not supported 319263508Sdim assert(!MFI->hasVarSizedObjects()); 320263508Sdim 321263508Sdim if (MFI->getNumObjects() == 0) { 322263508Sdim return -1; 323263508Sdim } 324263508Sdim 325263508Sdim Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1); 326263508Sdim 327263508Sdim return getIndirectIndexBegin(MF) + Offset; 328263508Sdim} 329263508Sdim 330263508Sdim 331249259Sdimvoid AMDGPUInstrInfo::convertToISA(MachineInstr & MI, MachineFunction &MF, 332249259Sdim DebugLoc DL) const { 333249259Sdim MachineRegisterInfo &MRI = MF.getRegInfo(); 334249259Sdim const AMDGPURegisterInfo & RI = getRegisterInfo(); 335249259Sdim 336249259Sdim for (unsigned i = 0; i < MI.getNumOperands(); i++) { 337249259Sdim MachineOperand &MO = MI.getOperand(i); 338249259Sdim // Convert dst regclass to one that is supported by the ISA 339249259Sdim if (MO.isReg() && MO.isDef()) { 340249259Sdim if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) { 341249259Sdim const TargetRegisterClass * oldRegClass = MRI.getRegClass(MO.getReg()); 342249259Sdim const TargetRegisterClass * newRegClass = RI.getISARegClass(oldRegClass); 343249259Sdim 344249259Sdim assert(newRegClass); 345249259Sdim 346249259Sdim MRI.setRegClass(MO.getReg(), newRegClass); 347249259Sdim } 348249259Sdim } 349249259Sdim } 350249259Sdim} 351263508Sdim 352263508Sdimint AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const { 353263508Sdim switch (Channels) { 354263508Sdim default: return Opcode; 355263508Sdim case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1); 356263508Sdim case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2); 357263508Sdim case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3); 358263508Sdim } 359263508Sdim} 360