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 23263509Sdim#define GET_INSTRINFO_CTOR_DTOR 24263509Sdim#define GET_INSTRINFO_NAMED_OPS 25249259Sdim#define GET_INSTRMAP_INFO 26249259Sdim#include "AMDGPUGenInstrInfo.inc" 27249259Sdim 28249259Sdimusing namespace llvm; 29249259Sdim 30263509Sdim 31263509Sdim// Pin the vtable to this file. 32263509Sdimvoid AMDGPUInstrInfo::anchor() {} 33263509Sdim 34249259SdimAMDGPUInstrInfo::AMDGPUInstrInfo(TargetMachine &tm) 35263509Sdim : 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 125263509Sdimbool AMDGPUInstrInfo::expandPostRAPseudo (MachineBasicBlock::iterator MI) const { 126263509Sdim MachineBasicBlock *MBB = MI->getParent(); 127263509Sdim int OffsetOpIdx = 128263509Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::addr); 129263509Sdim // addr is a custom operand with multiple MI operands, and only the 130263509Sdim // first MI operand is given a name. 131263509Sdim int RegOpIdx = OffsetOpIdx + 1; 132263509Sdim int ChanOpIdx = 133263509Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::chan); 134263509Sdim 135263509Sdim if (isRegisterLoad(*MI)) { 136263509Sdim int DstOpIdx = 137263509Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst); 138263509Sdim unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); 139263509Sdim unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); 140263509Sdim unsigned Address = calculateIndirectAddress(RegIndex, Channel); 141263509Sdim unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); 142263509Sdim if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { 143263509Sdim buildMovInstr(MBB, MI, MI->getOperand(DstOpIdx).getReg(), 144263509Sdim getIndirectAddrRegClass()->getRegister(Address)); 145263509Sdim } else { 146263509Sdim buildIndirectRead(MBB, MI, MI->getOperand(DstOpIdx).getReg(), 147263509Sdim Address, OffsetReg); 148263509Sdim } 149263509Sdim } else if (isRegisterStore(*MI)) { 150263509Sdim int ValOpIdx = 151263509Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::val); 152263509Sdim AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::dst); 153263509Sdim unsigned RegIndex = MI->getOperand(RegOpIdx).getImm(); 154263509Sdim unsigned Channel = MI->getOperand(ChanOpIdx).getImm(); 155263509Sdim unsigned Address = calculateIndirectAddress(RegIndex, Channel); 156263509Sdim unsigned OffsetReg = MI->getOperand(OffsetOpIdx).getReg(); 157263509Sdim if (OffsetReg == AMDGPU::INDIRECT_BASE_ADDR) { 158263509Sdim buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address), 159263509Sdim MI->getOperand(ValOpIdx).getReg()); 160263509Sdim } else { 161263509Sdim buildIndirectWrite(MBB, MI, MI->getOperand(ValOpIdx).getReg(), 162263509Sdim calculateIndirectAddress(RegIndex, Channel), 163263509Sdim OffsetReg); 164263509Sdim } 165263509Sdim } else { 166263509Sdim return false; 167263509Sdim } 168263509Sdim 169263509Sdim MBB->erase(MI); 170263509Sdim return true; 171263509Sdim} 172263509Sdim 173263509Sdim 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 279263509Sdimint AMDGPUInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const { 280263509Sdim const MachineRegisterInfo &MRI = MF.getRegInfo(); 281263509Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 282263509Sdim int Offset = -1; 283249259Sdim 284263509Sdim if (MFI->getNumObjects() == 0) { 285263509Sdim return -1; 286263509Sdim } 287263509Sdim 288263509Sdim if (MRI.livein_empty()) { 289263509Sdim return 0; 290263509Sdim } 291263509Sdim 292263509Sdim const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass(); 293263509Sdim for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(), 294263509Sdim LE = MRI.livein_end(); 295263509Sdim LI != LE; ++LI) { 296263509Sdim unsigned Reg = LI->first; 297263509Sdim if (TargetRegisterInfo::isVirtualRegister(Reg) || 298263509Sdim !IndirectRC->contains(Reg)) 299263509Sdim continue; 300263509Sdim 301263509Sdim unsigned RegIndex; 302263509Sdim unsigned RegEnd; 303263509Sdim for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd; 304263509Sdim ++RegIndex) { 305263509Sdim if (IndirectRC->getRegister(RegIndex) == Reg) 306263509Sdim break; 307263509Sdim } 308263509Sdim Offset = std::max(Offset, (int)RegIndex); 309263509Sdim } 310263509Sdim 311263509Sdim return Offset + 1; 312263509Sdim} 313263509Sdim 314263509Sdimint AMDGPUInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const { 315263509Sdim int Offset = 0; 316263509Sdim const MachineFrameInfo *MFI = MF.getFrameInfo(); 317263509Sdim 318263509Sdim // Variable sized objects are not supported 319263509Sdim assert(!MFI->hasVarSizedObjects()); 320263509Sdim 321263509Sdim if (MFI->getNumObjects() == 0) { 322263509Sdim return -1; 323263509Sdim } 324263509Sdim 325263509Sdim Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1); 326263509Sdim 327263509Sdim return getIndirectIndexBegin(MF) + Offset; 328263509Sdim} 329263509Sdim 330263509Sdim 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} 351263509Sdim 352263509Sdimint AMDGPUInstrInfo::getMaskedMIMGOp(uint16_t Opcode, unsigned Channels) const { 353263509Sdim switch (Channels) { 354263509Sdim default: return Opcode; 355263509Sdim case 1: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_1); 356263509Sdim case 2: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_2); 357263509Sdim case 3: return AMDGPU::getMaskedMIMGOp(Opcode, AMDGPU::Channels_3); 358263509Sdim } 359263509Sdim} 360