LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - AMDGPUInstructionSelector.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 197 230 85.7 %
Date: 2017-09-14 15:23:50 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AMDGPUInstructionSelector.cpp ----------------------------*- C++ -*-==//
       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             : /// \file
      10             : /// This file implements the targeting of the InstructionSelector class for
      11             : /// AMDGPU.
      12             : /// \todo This should be generated by TableGen.
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "AMDGPUInstructionSelector.h"
      16             : #include "AMDGPUInstrInfo.h"
      17             : #include "AMDGPURegisterBankInfo.h"
      18             : #include "AMDGPURegisterInfo.h"
      19             : #include "AMDGPUSubtarget.h"
      20             : #include "llvm/CodeGen/MachineBasicBlock.h"
      21             : #include "llvm/CodeGen/MachineFunction.h"
      22             : #include "llvm/CodeGen/MachineInstr.h"
      23             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      24             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      25             : #include "llvm/IR/Type.h"
      26             : #include "llvm/Support/Debug.h"
      27             : #include "llvm/Support/raw_ostream.h"
      28             : 
      29             : #define DEBUG_TYPE "amdgpu-isel"
      30             : 
      31             : using namespace llvm;
      32             : 
      33        1796 : AMDGPUInstructionSelector::AMDGPUInstructionSelector(
      34        1796 :     const SISubtarget &STI, const AMDGPURegisterBankInfo &RBI)
      35        1796 :     : InstructionSelector(), TII(*STI.getInstrInfo()),
      36        7184 :       TRI(*STI.getRegisterInfo()), RBI(RBI), AMDGPUASI(STI.getAMDGPUAS()) {}
      37             : 
      38             : MachineOperand
      39          36 : AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO,
      40             :                                            unsigned SubIdx) const {
      41             : 
      42          36 :   MachineInstr *MI = MO.getParent();
      43          36 :   MachineBasicBlock *BB = MO.getParent()->getParent();
      44          36 :   MachineFunction *MF = BB->getParent();
      45          36 :   MachineRegisterInfo &MRI = MF->getRegInfo();
      46          36 :   unsigned DstReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
      47             : 
      48          36 :   if (MO.isReg()) {
      49         108 :     unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx);
      50          36 :     unsigned Reg = MO.getReg();
      51         180 :     BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
      52          36 :             .addReg(Reg, 0, ComposedSubIdx);
      53             : 
      54          72 :     return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(),
      55         108 :                                      MO.isKill(), MO.isDead(), MO.isUndef(),
      56          72 :                                      MO.isEarlyClobber(), 0, MO.isDebug(),
      57         288 :                                      MO.isInternalRead());
      58             :   }
      59             : 
      60             :   assert(MO.isImm());
      61             : 
      62           0 :   APInt Imm(64, MO.getImm());
      63             : 
      64           0 :   switch (SubIdx) {
      65           0 :   default:
      66           0 :     llvm_unreachable("do not know to split immediate with this sub index.");
      67           0 :   case AMDGPU::sub0:
      68           0 :     return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue());
      69           0 :   case AMDGPU::sub1:
      70           0 :     return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue());
      71             :   }
      72             : }
      73             : 
      74           9 : bool AMDGPUInstructionSelector::selectG_ADD(MachineInstr &I) const {
      75           9 :   MachineBasicBlock *BB = I.getParent();
      76           9 :   MachineFunction *MF = BB->getParent();
      77           9 :   MachineRegisterInfo &MRI = MF->getRegInfo();
      78           9 :   unsigned Size = RBI.getSizeInBits(I.getOperand(0).getReg(), MRI, TRI);
      79           9 :   unsigned DstLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
      80           9 :   unsigned DstHi = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
      81             : 
      82           9 :   if (Size != 64)
      83             :     return false;
      84             : 
      85          18 :   DebugLoc DL = I.getDebugLoc();
      86             : 
      87          18 :   MachineOperand Lo1(getSubOperand64(I.getOperand(1), AMDGPU::sub0));
      88          18 :   MachineOperand Lo2(getSubOperand64(I.getOperand(2), AMDGPU::sub0));
      89             : 
      90          27 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
      91           9 :           .add(Lo1)
      92           9 :           .add(Lo2);
      93             : 
      94          18 :   MachineOperand Hi1(getSubOperand64(I.getOperand(1), AMDGPU::sub1));
      95          18 :   MachineOperand Hi2(getSubOperand64(I.getOperand(2), AMDGPU::sub1));
      96             : 
      97          27 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
      98           9 :           .add(Hi1)
      99           9 :           .add(Hi2);
     100             : 
     101          36 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), I.getOperand(0).getReg())
     102           9 :           .addReg(DstLo)
     103           9 :           .addImm(AMDGPU::sub0)
     104           9 :           .addReg(DstHi)
     105           9 :           .addImm(AMDGPU::sub1);
     106             : 
     107          36 :   for (MachineOperand &MO : I.explicit_operands()) {
     108          54 :     if (!MO.isReg() || TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
     109           0 :       continue;
     110          27 :     RBI.constrainGenericRegister(MO.getReg(), AMDGPU::SReg_64RegClass, MRI);
     111             :   }
     112             : 
     113           9 :   I.eraseFromParent();
     114           9 :   return true;
     115             : }
     116             : 
     117           9 : bool AMDGPUInstructionSelector::selectG_GEP(MachineInstr &I) const {
     118           9 :   return selectG_ADD(I);
     119             : }
     120             : 
     121          14 : bool AMDGPUInstructionSelector::selectG_STORE(MachineInstr &I) const {
     122          14 :   MachineBasicBlock *BB = I.getParent();
     123          42 :   DebugLoc DL = I.getDebugLoc();
     124             : 
     125             :   // FIXME: Select store instruction based on address space
     126          42 :   MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(AMDGPU::FLAT_STORE_DWORD))
     127          42 :           .add(I.getOperand(1))
     128          28 :           .add(I.getOperand(0))
     129          14 :           .addImm(0)  // offset
     130          14 :           .addImm(0)  // glc
     131          14 :           .addImm(0); // slc
     132             : 
     133             : 
     134             :   // Now that we selected an opcode, we need to constrain the register
     135             :   // operands to use appropriate classes.
     136          14 :   bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
     137             : 
     138          14 :   I.eraseFromParent();
     139          28 :   return Ret;
     140             : }
     141             : 
     142           9 : bool AMDGPUInstructionSelector::selectG_CONSTANT(MachineInstr &I) const {
     143           9 :   MachineBasicBlock *BB = I.getParent();
     144           9 :   MachineFunction *MF = BB->getParent();
     145           9 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     146           9 :   unsigned DstReg = I.getOperand(0).getReg();
     147           9 :   unsigned Size = RBI.getSizeInBits(DstReg, MRI, TRI);
     148             : 
     149           9 :   if (Size == 32) {
     150           0 :     I.setDesc(TII.get(AMDGPU::S_MOV_B32));
     151           0 :     return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
     152             :   }
     153             : 
     154             :   assert(Size == 64);
     155             : 
     156          18 :   DebugLoc DL = I.getDebugLoc();
     157           9 :   unsigned LoReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
     158           9 :   unsigned HiReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
     159          18 :   const APInt &Imm = I.getOperand(1).getCImm()->getValue();
     160             : 
     161          27 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), LoReg)
     162          36 :           .addImm(Imm.trunc(32).getZExtValue());
     163             : 
     164          27 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), HiReg)
     165          36 :           .addImm(Imm.ashr(32).getZExtValue());
     166             : 
     167          36 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
     168           9 :           .addReg(LoReg)
     169           9 :           .addImm(AMDGPU::sub0)
     170           9 :           .addReg(HiReg)
     171           9 :           .addImm(AMDGPU::sub1);
     172             :   // We can't call constrainSelectedInstRegOperands here, because it doesn't
     173             :   // work for target independent opcodes
     174           9 :   I.eraseFromParent();
     175           9 :   return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, MRI);
     176             : }
     177             : 
     178             : static bool isConstant(const MachineInstr &MI) {
     179         126 :   return MI.getOpcode() == TargetOpcode::G_CONSTANT;
     180             : }
     181             : 
     182         128 : void AMDGPUInstructionSelector::getAddrModeInfo(const MachineInstr &Load,
     183             :     const MachineRegisterInfo &MRI, SmallVectorImpl<GEPInfo> &AddrInfo) const {
     184             : 
     185         128 :   const MachineInstr *PtrMI = MRI.getUniqueVRegDef(Load.getOperand(1).getReg());
     186             : 
     187             :   assert(PtrMI);
     188             : 
     189         256 :   if (PtrMI->getOpcode() != TargetOpcode::G_GEP)
     190          65 :     return;
     191             : 
     192         126 :   GEPInfo GEPInfo(*PtrMI);
     193             : 
     194         189 :   for (unsigned i = 1, e = 3; i < e; ++i) {
     195         252 :     const MachineOperand &GEPOp = PtrMI->getOperand(i);
     196         126 :     const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.getReg());
     197             :     assert(OpDef);
     198         189 :     if (isConstant(*OpDef)) {
     199             :       // FIXME: Is it possible to have multiple Imm parts?  Maybe if we
     200             :       // are lacking other optimizations.
     201             :       assert(GEPInfo.Imm == 0);
     202         126 :       GEPInfo.Imm = OpDef->getOperand(1).getCImm()->getSExtValue();
     203          63 :       continue;
     204             :     }
     205          63 :     const RegisterBank *OpBank = RBI.getRegBank(GEPOp.getReg(), MRI, TRI);
     206          63 :     if (OpBank->getID() == AMDGPU::SGPRRegBankID)
     207          63 :       GEPInfo.SgprParts.push_back(GEPOp.getReg());
     208             :     else
     209           0 :       GEPInfo.VgprParts.push_back(GEPOp.getReg());
     210             :   }
     211             : 
     212          63 :   AddrInfo.push_back(GEPInfo);
     213          63 :   getAddrModeInfo(*PtrMI, MRI, AddrInfo);
     214             : }
     215             : 
     216          63 : static bool isInstrUniform(const MachineInstr &MI) {
     217          63 :   if (!MI.hasOneMemOperand())
     218             :     return false;
     219             : 
     220          63 :   const MachineMemOperand *MMO = *MI.memoperands_begin();
     221          63 :   const Value *Ptr = MMO->getValue();
     222             : 
     223             :   // UndefValue means this is a load of a kernel input.  These are uniform.
     224             :   // Sometimes LDS instructions have constant pointers.
     225             :   // If Ptr is null, then that means this mem operand contains a
     226             :   // PseudoSourceValue like GOT.
     227         165 :   if (!Ptr || isa<UndefValue>(Ptr) || isa<Argument>(Ptr) ||
     228          87 :       isa<Constant>(Ptr) || isa<GlobalValue>(Ptr))
     229             :     return true;
     230             : 
     231          24 :   const Instruction *I = dyn_cast<Instruction>(Ptr);
     232          24 :   return I && I->getMetadata("amdgpu.uniform");
     233             : }
     234             : 
     235             : static unsigned getSmrdOpcode(unsigned BaseOpcode, unsigned LoadSize) {
     236             : 
     237          63 :   if (LoadSize == 32)
     238             :     return BaseOpcode;
     239             : 
     240             :   switch (BaseOpcode) {
     241          24 :   case AMDGPU::S_LOAD_DWORD_IMM:
     242          24 :     switch (LoadSize) {
     243             :     case 64:
     244             :       return AMDGPU::S_LOAD_DWORDX2_IMM;
     245           0 :     case 128:
     246             :       return AMDGPU::S_LOAD_DWORDX4_IMM;
     247           0 :     case 256:
     248             :       return AMDGPU::S_LOAD_DWORDX8_IMM;
     249           0 :     case 512:
     250             :       return AMDGPU::S_LOAD_DWORDX16_IMM;
     251             :     }
     252             :     break;
     253           0 :   case AMDGPU::S_LOAD_DWORD_IMM_ci:
     254           0 :     switch (LoadSize) {
     255             :     case 64:
     256             :       return AMDGPU::S_LOAD_DWORDX2_IMM_ci;
     257           0 :     case 128:
     258             :       return AMDGPU::S_LOAD_DWORDX4_IMM_ci;
     259           0 :     case 256:
     260             :       return AMDGPU::S_LOAD_DWORDX8_IMM_ci;
     261           0 :     case 512:
     262             :       return AMDGPU::S_LOAD_DWORDX16_IMM_ci;
     263             :     }
     264             :     break;
     265           0 :   case AMDGPU::S_LOAD_DWORD_SGPR:
     266           0 :     switch (LoadSize) {
     267             :     case 64:
     268             :       return AMDGPU::S_LOAD_DWORDX2_SGPR;
     269           0 :     case 128:
     270             :       return AMDGPU::S_LOAD_DWORDX4_SGPR;
     271           0 :     case 256:
     272             :       return AMDGPU::S_LOAD_DWORDX8_SGPR;
     273           0 :     case 512:
     274             :       return AMDGPU::S_LOAD_DWORDX16_SGPR;
     275             :     }
     276             :     break;
     277             :   }
     278           0 :   llvm_unreachable("Invalid base smrd opcode or size");
     279             : }
     280             : 
     281          63 : bool AMDGPUInstructionSelector::hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const {
     282         189 :   for (const GEPInfo &GEPInfo : AddrInfo) {
     283          63 :     if (!GEPInfo.VgprParts.empty())
     284             :       return true;
     285             :   }
     286             :   return false;
     287             : }
     288             : 
     289          65 : bool AMDGPUInstructionSelector::selectSMRD(MachineInstr &I,
     290             :                                            ArrayRef<GEPInfo> AddrInfo) const {
     291             : 
     292          65 :   if (!I.hasOneMemOperand())
     293             :     return false;
     294             : 
     295         130 :   if ((*I.memoperands_begin())->getAddrSpace() != AMDGPUASI.CONSTANT_ADDRESS)
     296             :     return false;
     297             : 
     298          63 :   if (!isInstrUniform(I))
     299             :     return false;
     300             : 
     301          63 :   if (hasVgprParts(AddrInfo))
     302             :     return false;
     303             : 
     304          63 :   MachineBasicBlock *BB = I.getParent();
     305          63 :   MachineFunction *MF = BB->getParent();
     306          63 :   const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>();
     307          63 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     308          63 :   unsigned DstReg = I.getOperand(0).getReg();
     309          63 :   const DebugLoc &DL = I.getDebugLoc();
     310             :   unsigned Opcode;
     311          63 :   unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
     312             : 
     313         126 :   if (!AddrInfo.empty() && AddrInfo[0].SgprParts.size() == 1) {
     314             : 
     315          63 :     const GEPInfo &GEPInfo = AddrInfo[0];
     316             : 
     317         126 :     unsigned PtrReg = GEPInfo.SgprParts[0];
     318          63 :     int64_t EncodedImm = AMDGPU::getSMRDEncodedOffset(Subtarget, GEPInfo.Imm);
     319          63 :     if (AMDGPU::isLegalSMRDImmOffset(Subtarget, GEPInfo.Imm)) {
     320          38 :       Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
     321             : 
     322         152 :       MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     323          38 :                                  .addReg(PtrReg)
     324          38 :                                  .addImm(EncodedImm)
     325          38 :                                  .addImm(0); // glc
     326          38 :       return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     327             :     }
     328             : 
     329          36 :     if (Subtarget.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS &&
     330          11 :         isUInt<32>(EncodedImm)) {
     331           9 :       Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM_ci, LoadSize);
     332          36 :       MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     333           9 :                                    .addReg(PtrReg)
     334           9 :                                    .addImm(EncodedImm)
     335           9 :                                    .addImm(0); // glc
     336           9 :       return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     337             :     }
     338             : 
     339          16 :     if (isUInt<32>(GEPInfo.Imm)) {
     340           7 :       Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_SGPR, LoadSize);
     341           7 :       unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
     342          21 :       BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), OffsetReg)
     343          14 :               .addImm(GEPInfo.Imm);
     344             : 
     345          28 :       MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     346           7 :                                    .addReg(PtrReg)
     347           7 :                                    .addReg(OffsetReg)
     348           7 :                                    .addImm(0); // glc
     349           7 :       return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     350             :     }
     351             :   }
     352             : 
     353           9 :   unsigned PtrReg = I.getOperand(1).getReg();
     354           9 :   Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
     355          36 :   MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     356           9 :                                .addReg(PtrReg)
     357           9 :                                .addImm(0)
     358           9 :                                .addImm(0); // glc
     359           9 :   return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     360             : }
     361             : 
     362             : 
     363          65 : bool AMDGPUInstructionSelector::selectG_LOAD(MachineInstr &I) const {
     364          65 :   MachineBasicBlock *BB = I.getParent();
     365          65 :   MachineFunction *MF = BB->getParent();
     366          65 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     367         195 :   DebugLoc DL = I.getDebugLoc();
     368          65 :   unsigned DstReg = I.getOperand(0).getReg();
     369          65 :   unsigned PtrReg = I.getOperand(1).getReg();
     370          65 :   unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
     371             :   unsigned Opcode;
     372             : 
     373         130 :   SmallVector<GEPInfo, 4> AddrInfo;
     374             : 
     375          65 :   getAddrModeInfo(I, MRI, AddrInfo);
     376             : 
     377          65 :   if (selectSMRD(I, AddrInfo)) {
     378          63 :     I.eraseFromParent();
     379          63 :     return true;
     380             :   }
     381             : 
     382           2 :   switch (LoadSize) {
     383           0 :   default:
     384           0 :     llvm_unreachable("Load size not supported\n");
     385             :   case 32:
     386             :     Opcode = AMDGPU::FLAT_LOAD_DWORD;
     387             :     break;
     388           0 :   case 64:
     389           0 :     Opcode = AMDGPU::FLAT_LOAD_DWORDX2;
     390           0 :     break;
     391             :   }
     392             : 
     393           8 :   MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode))
     394           4 :                                .add(I.getOperand(0))
     395           2 :                                .addReg(PtrReg)
     396           2 :                                .addImm(0)  // offset
     397           2 :                                .addImm(0)  // glc
     398           2 :                                .addImm(0); // slc
     399             : 
     400           2 :   bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
     401           2 :   I.eraseFromParent();
     402           2 :   return Ret;
     403             : }
     404             : 
     405         184 : bool AMDGPUInstructionSelector::select(MachineInstr &I) const {
     406             : 
     407         552 :   if (!isPreISelGenericOpcode(I.getOpcode()))
     408             :     return true;
     409             : 
     410          97 :   switch (I.getOpcode()) {
     411             :   default:
     412             :     break;
     413           0 :   case TargetOpcode::G_ADD:
     414           0 :     return selectG_ADD(I);
     415           9 :   case TargetOpcode::G_CONSTANT:
     416           9 :     return selectG_CONSTANT(I);
     417           9 :   case TargetOpcode::G_GEP:
     418           9 :     return selectG_GEP(I);
     419          65 :   case TargetOpcode::G_LOAD:
     420          65 :     return selectG_LOAD(I);
     421          14 :   case TargetOpcode::G_STORE:
     422          14 :     return selectG_STORE(I);
     423             :   }
     424             :   return false;
     425             : }

Generated by: LCOV version 1.13