Home | History | Annotate | Download | only in R600
      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