LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - AMDGPUInstructionSelector.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 297 326 91.1 %
Date: 2018-10-20 13:21:21 Functions: 22 23 95.7 %
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 "AMDGPUTargetMachine.h"
      21             : #include "SIMachineFunctionInfo.h"
      22             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      23             : #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
      24             : #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
      25             : #include "llvm/CodeGen/GlobalISel/Utils.h"
      26             : #include "llvm/CodeGen/MachineBasicBlock.h"
      27             : #include "llvm/CodeGen/MachineFunction.h"
      28             : #include "llvm/CodeGen/MachineInstr.h"
      29             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      30             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      31             : #include "llvm/IR/Type.h"
      32             : #include "llvm/Support/Debug.h"
      33             : #include "llvm/Support/raw_ostream.h"
      34             : 
      35             : #define DEBUG_TYPE "amdgpu-isel"
      36             : 
      37             : using namespace llvm;
      38             : 
      39             : #define GET_GLOBALISEL_IMPL
      40             : #define AMDGPUSubtarget GCNSubtarget
      41             : #include "AMDGPUGenGlobalISel.inc"
      42             : #undef GET_GLOBALISEL_IMPL
      43             : #undef AMDGPUSubtarget
      44             : 
      45        2492 : AMDGPUInstructionSelector::AMDGPUInstructionSelector(
      46             :     const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI,
      47        2492 :     const AMDGPUTargetMachine &TM)
      48        2492 :     : InstructionSelector(), TII(*STI.getInstrInfo()),
      49        2492 :       TRI(*STI.getRegisterInfo()), RBI(RBI), TM(TM),
      50             :       STI(STI),
      51             :       EnableLateStructurizeCFG(AMDGPUTargetMachine::EnableLateStructurizeCFG),
      52             : #define GET_GLOBALISEL_PREDICATES_INIT
      53             : #include "AMDGPUGenGlobalISel.inc"
      54             : #undef GET_GLOBALISEL_PREDICATES_INIT
      55             : #define GET_GLOBALISEL_TEMPORARIES_INIT
      56             : #include "AMDGPUGenGlobalISel.inc"
      57             : #undef GET_GLOBALISEL_TEMPORARIES_INIT
      58             : {
      59        2492 : }
      60             : 
      61           0 : const char *AMDGPUInstructionSelector::getName() { return DEBUG_TYPE; }
      62             : 
      63         151 : bool AMDGPUInstructionSelector::selectCOPY(MachineInstr &I) const {
      64         151 :   MachineBasicBlock *BB = I.getParent();
      65         151 :   MachineFunction *MF = BB->getParent();
      66         151 :   MachineRegisterInfo &MRI = MF->getRegInfo();
      67         151 :   I.setDesc(TII.get(TargetOpcode::COPY));
      68         453 :   for (const MachineOperand &MO : I.operands()) {
      69         604 :     if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
      70             :       continue;
      71             : 
      72             :     const TargetRegisterClass *RC =
      73         188 :             TRI.getConstrainedRegClassForOperand(MO, MRI);
      74         188 :     if (!RC)
      75             :       continue;
      76          78 :     RBI.constrainGenericRegister(MO.getReg(), *RC, MRI);
      77             :   }
      78         151 :   return true;
      79             : }
      80             : 
      81             : MachineOperand
      82          36 : AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO,
      83             :                                            unsigned SubIdx) const {
      84             : 
      85          36 :   MachineInstr *MI = MO.getParent();
      86          36 :   MachineBasicBlock *BB = MO.getParent()->getParent();
      87          36 :   MachineFunction *MF = BB->getParent();
      88          36 :   MachineRegisterInfo &MRI = MF->getRegInfo();
      89          36 :   unsigned DstReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
      90             : 
      91          36 :   if (MO.isReg()) {
      92          36 :     unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx);
      93          36 :     unsigned Reg = MO.getReg();
      94          72 :     BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
      95          36 :             .addReg(Reg, 0, ComposedSubIdx);
      96             : 
      97             :     return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(),
      98             :                                      MO.isKill(), MO.isDead(), MO.isUndef(),
      99             :                                      MO.isEarlyClobber(), 0, MO.isDebug(),
     100             :                                      MO.isInternalRead());
     101             :   }
     102             : 
     103             :   assert(MO.isImm());
     104             : 
     105           0 :   APInt Imm(64, MO.getImm());
     106             : 
     107           0 :   switch (SubIdx) {
     108           0 :   default:
     109           0 :     llvm_unreachable("do not know to split immediate with this sub index.");
     110           0 :   case AMDGPU::sub0:
     111           0 :     return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue());
     112           0 :   case AMDGPU::sub1:
     113           0 :     return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue());
     114             :   }
     115             : }
     116             : 
     117             : static int64_t getConstant(const MachineInstr *MI) {
     118          16 :   return MI->getOperand(1).getCImm()->getSExtValue();
     119             : }
     120             : 
     121           9 : bool AMDGPUInstructionSelector::selectG_ADD(MachineInstr &I) const {
     122           9 :   MachineBasicBlock *BB = I.getParent();
     123           9 :   MachineFunction *MF = BB->getParent();
     124           9 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     125           9 :   unsigned Size = RBI.getSizeInBits(I.getOperand(0).getReg(), MRI, TRI);
     126           9 :   unsigned DstLo = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
     127           9 :   unsigned DstHi = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
     128             : 
     129           9 :   if (Size != 64)
     130             :     return false;
     131             : 
     132             :   DebugLoc DL = I.getDebugLoc();
     133             : 
     134          18 :   MachineOperand Lo1(getSubOperand64(I.getOperand(1), AMDGPU::sub0));
     135          18 :   MachineOperand Lo2(getSubOperand64(I.getOperand(2), AMDGPU::sub0));
     136             : 
     137           9 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
     138             :           .add(Lo1)
     139             :           .add(Lo2);
     140             : 
     141          18 :   MachineOperand Hi1(getSubOperand64(I.getOperand(1), AMDGPU::sub1));
     142          18 :   MachineOperand Hi2(getSubOperand64(I.getOperand(2), AMDGPU::sub1));
     143             : 
     144           9 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
     145             :           .add(Hi1)
     146             :           .add(Hi2);
     147             : 
     148          18 :   BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), I.getOperand(0).getReg())
     149           9 :           .addReg(DstLo)
     150             :           .addImm(AMDGPU::sub0)
     151           9 :           .addReg(DstHi)
     152             :           .addImm(AMDGPU::sub1);
     153             : 
     154          36 :   for (MachineOperand &MO : I.explicit_operands()) {
     155          27 :     if (!MO.isReg() || TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
     156             :       continue;
     157          27 :     RBI.constrainGenericRegister(MO.getReg(), AMDGPU::SReg_64RegClass, MRI);
     158             :   }
     159             : 
     160           9 :   I.eraseFromParent();
     161             :   return true;
     162             : }
     163             : 
     164           9 : bool AMDGPUInstructionSelector::selectG_GEP(MachineInstr &I) const {
     165           9 :   return selectG_ADD(I);
     166             : }
     167             : 
     168          20 : bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(MachineInstr &I) const {
     169          20 :   MachineBasicBlock *BB = I.getParent();
     170          20 :   MachineFunction *MF = BB->getParent();
     171          20 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     172          20 :   const MachineOperand &MO = I.getOperand(0);
     173             :   const TargetRegisterClass *RC =
     174          20 :       TRI.getConstrainedRegClassForOperand(MO, MRI);
     175          20 :   if (RC)
     176           0 :     RBI.constrainGenericRegister(MO.getReg(), *RC, MRI);
     177          20 :   I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
     178          20 :   return true;
     179             : }
     180             : 
     181          31 : bool AMDGPUInstructionSelector::selectG_INTRINSIC(MachineInstr &I,
     182             :                                           CodeGenCoverage &CoverageInfo) const {
     183          31 :   unsigned IntrinsicID =  I.getOperand(1).getIntrinsicID();
     184             : 
     185          31 :   switch (IntrinsicID) {
     186             :   default:
     187             :     break;
     188          18 :   case Intrinsic::maxnum:
     189             :   case Intrinsic::minnum:
     190             :   case Intrinsic::amdgcn_cvt_pkrtz:
     191          18 :     return selectImpl(I, CoverageInfo);
     192             : 
     193          13 :   case Intrinsic::amdgcn_kernarg_segment_ptr: {
     194          13 :     MachineFunction *MF = I.getParent()->getParent();
     195          13 :     MachineRegisterInfo &MRI = MF->getRegInfo();
     196          13 :     const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
     197             :     const ArgDescriptor *InputPtrReg;
     198             :     const TargetRegisterClass *RC;
     199             :     const DebugLoc &DL = I.getDebugLoc();
     200             : 
     201             :     std::tie(InputPtrReg, RC)
     202             :       = MFI->getPreloadedValue(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR);
     203          13 :     if (!InputPtrReg)
     204           1 :       report_fatal_error("missing kernarg segment ptr");
     205             : 
     206          24 :     BuildMI(*I.getParent(), &I, DL, TII.get(AMDGPU::COPY))
     207          12 :       .add(I.getOperand(0))
     208          12 :       .addReg(MRI.getLiveInVirtReg(InputPtrReg->getRegister()));
     209          12 :     I.eraseFromParent();
     210             :     return true;
     211             :   }
     212             :   }
     213             :   return false;
     214             : }
     215             : 
     216             : static MachineInstr *
     217           4 : buildEXP(const TargetInstrInfo &TII, MachineInstr *Insert, unsigned Tgt,
     218             :          unsigned Reg0, unsigned Reg1, unsigned Reg2, unsigned Reg3,
     219             :          unsigned VM, bool Compr, unsigned Enabled, bool Done) {
     220             :   const DebugLoc &DL = Insert->getDebugLoc();
     221           4 :   MachineBasicBlock &BB = *Insert->getParent();
     222           4 :   unsigned Opcode = Done ? AMDGPU::EXP_DONE : AMDGPU::EXP;
     223           4 :   return BuildMI(BB, Insert, DL, TII.get(Opcode))
     224           4 :           .addImm(Tgt)
     225           4 :           .addReg(Reg0)
     226           4 :           .addReg(Reg1)
     227           4 :           .addReg(Reg2)
     228           4 :           .addReg(Reg3)
     229           4 :           .addImm(VM)
     230           4 :           .addImm(Compr)
     231           4 :           .addImm(Enabled);
     232             : }
     233             : 
     234           4 : bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
     235             :                                                  MachineInstr &I,
     236             :                                                  CodeGenCoverage &CoverageInfo) const {
     237           4 :   MachineBasicBlock *BB = I.getParent();
     238           4 :   MachineFunction *MF = BB->getParent();
     239           4 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     240             : 
     241           4 :   unsigned IntrinsicID = I.getOperand(0).getIntrinsicID();
     242           4 :   switch (IntrinsicID) {
     243           2 :   case Intrinsic::amdgcn_exp: {
     244           2 :     int64_t Tgt = getConstant(MRI.getVRegDef(I.getOperand(1).getReg()));
     245           2 :     int64_t Enabled = getConstant(MRI.getVRegDef(I.getOperand(2).getReg()));
     246           2 :     int64_t Done = getConstant(MRI.getVRegDef(I.getOperand(7).getReg()));
     247           2 :     int64_t VM = getConstant(MRI.getVRegDef(I.getOperand(8).getReg()));
     248             : 
     249           4 :     MachineInstr *Exp = buildEXP(TII, &I, Tgt, I.getOperand(3).getReg(),
     250             :                                  I.getOperand(4).getReg(),
     251             :                                  I.getOperand(5).getReg(),
     252           2 :                                  I.getOperand(6).getReg(),
     253             :                                  VM, false, Enabled, Done);
     254             : 
     255           2 :     I.eraseFromParent();
     256           2 :     return constrainSelectedInstRegOperands(*Exp, TII, TRI, RBI);
     257             :   }
     258             :   case Intrinsic::amdgcn_exp_compr: {
     259             :     const DebugLoc &DL = I.getDebugLoc();
     260           2 :     int64_t Tgt = getConstant(MRI.getVRegDef(I.getOperand(1).getReg()));
     261           2 :     int64_t Enabled = getConstant(MRI.getVRegDef(I.getOperand(2).getReg()));
     262           2 :     unsigned Reg0 = I.getOperand(3).getReg();
     263           2 :     unsigned Reg1 = I.getOperand(4).getReg();
     264           2 :     unsigned Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
     265           2 :     int64_t Done = getConstant(MRI.getVRegDef(I.getOperand(5).getReg()));
     266           2 :     int64_t VM = getConstant(MRI.getVRegDef(I.getOperand(6).getReg()));
     267             : 
     268           2 :     BuildMI(*BB, &I, DL, TII.get(AMDGPU::IMPLICIT_DEF), Undef);
     269           2 :     MachineInstr *Exp = buildEXP(TII, &I, Tgt, Reg0, Reg1, Undef, Undef, VM,
     270             :                                  true,  Enabled, Done);
     271             : 
     272           2 :     I.eraseFromParent();
     273           2 :     return constrainSelectedInstRegOperands(*Exp, TII, TRI, RBI);
     274             :   }
     275             :   }
     276             :   return false;
     277             : }
     278             : 
     279          69 : bool AMDGPUInstructionSelector::selectG_STORE(MachineInstr &I) const {
     280          69 :   MachineBasicBlock *BB = I.getParent();
     281          69 :   MachineFunction *MF = BB->getParent();
     282          69 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     283             :   DebugLoc DL = I.getDebugLoc();
     284          69 :   unsigned StoreSize = RBI.getSizeInBits(I.getOperand(0).getReg(), MRI, TRI);
     285             :   unsigned Opcode;
     286             : 
     287             :   // FIXME: Select store instruction based on address space
     288          69 :   switch (StoreSize) {
     289             :   default:
     290             :     return false;
     291             :   case 32:
     292             :     Opcode = AMDGPU::FLAT_STORE_DWORD;
     293             :     break;
     294          13 :   case 64:
     295             :     Opcode = AMDGPU::FLAT_STORE_DWORDX2;
     296          13 :     break;
     297           2 :   case 96:
     298             :     Opcode = AMDGPU::FLAT_STORE_DWORDX3;
     299           2 :     break;
     300           2 :   case 128:
     301             :     Opcode = AMDGPU::FLAT_STORE_DWORDX4;
     302           2 :     break;
     303             :   }
     304             : 
     305          69 :   MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode))
     306          69 :           .add(I.getOperand(1))
     307          69 :           .add(I.getOperand(0))
     308             :           .addImm(0)  // offset
     309             :           .addImm(0)  // glc
     310             :           .addImm(0); // slc
     311             : 
     312             : 
     313             :   // Now that we selected an opcode, we need to constrain the register
     314             :   // operands to use appropriate classes.
     315          69 :   bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
     316             : 
     317          69 :   I.eraseFromParent();
     318          69 :   return Ret;
     319             : }
     320             : 
     321          25 : bool AMDGPUInstructionSelector::selectG_CONSTANT(MachineInstr &I) const {
     322          25 :   MachineBasicBlock *BB = I.getParent();
     323          25 :   MachineFunction *MF = BB->getParent();
     324          25 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     325          25 :   MachineOperand &ImmOp = I.getOperand(1);
     326             : 
     327             :   // The AMDGPU backend only supports Imm operands and not CImm or FPImm.
     328          25 :   if (ImmOp.isFPImm()) {
     329           8 :     const APInt &Imm = ImmOp.getFPImm()->getValueAPF().bitcastToAPInt();
     330           4 :     ImmOp.ChangeToImmediate(Imm.getZExtValue());
     331          21 :   } else if (ImmOp.isCImm()) {
     332          34 :     ImmOp.ChangeToImmediate(ImmOp.getCImm()->getZExtValue());
     333             :   }
     334             : 
     335          25 :   unsigned DstReg = I.getOperand(0).getReg();
     336             :   unsigned Size;
     337             :   bool IsSgpr;
     338             :   const RegisterBank *RB = MRI.getRegBankOrNull(I.getOperand(0).getReg());
     339           3 :   if (RB) {
     340           3 :     IsSgpr = RB->getID() == AMDGPU::SGPRRegBankID;
     341           3 :     Size = MRI.getType(DstReg).getSizeInBits();
     342             :   } else {
     343          22 :     const TargetRegisterClass *RC = TRI.getRegClassForReg(MRI, DstReg);
     344          22 :     IsSgpr = TRI.isSGPRClass(RC);
     345          22 :     Size = TRI.getRegSizeInBits(*RC);
     346             :   }
     347             : 
     348          25 :   if (Size != 32 && Size != 64)
     349             :     return false;
     350             : 
     351          25 :   unsigned Opcode = IsSgpr ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
     352          25 :   if (Size == 32) {
     353          12 :     I.setDesc(TII.get(Opcode));
     354          12 :     I.addImplicitDefUseOperands(*MF);
     355          12 :     return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
     356             :   }
     357             : 
     358             :   DebugLoc DL = I.getDebugLoc();
     359          13 :   const TargetRegisterClass *RC = IsSgpr ? &AMDGPU::SReg_32_XM0RegClass :
     360             :                                            &AMDGPU::VGPR_32RegClass;
     361          13 :   unsigned LoReg = MRI.createVirtualRegister(RC);
     362          13 :   unsigned HiReg = MRI.createVirtualRegister(RC);
     363          13 :   const APInt &Imm = APInt(Size, I.getOperand(1).getImm());
     364             : 
     365          13 :   BuildMI(*BB, &I, DL, TII.get(Opcode), LoReg)
     366          26 :           .addImm(Imm.trunc(32).getZExtValue());
     367             : 
     368          13 :   BuildMI(*BB, &I, DL, TII.get(Opcode), HiReg)
     369          26 :           .addImm(Imm.ashr(32).getZExtValue());
     370             : 
     371             :   const MachineInstr *RS =
     372          13 :       BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
     373          13 :               .addReg(LoReg)
     374             :               .addImm(AMDGPU::sub0)
     375          13 :               .addReg(HiReg)
     376          13 :               .addImm(AMDGPU::sub1);
     377             : 
     378             :   // We can't call constrainSelectedInstRegOperands here, because it doesn't
     379             :   // work for target independent opcodes
     380          13 :   I.eraseFromParent();
     381             :   const TargetRegisterClass *DstRC =
     382          13 :       TRI.getConstrainedRegClassForOperand(RS->getOperand(0), MRI);
     383          13 :   if (!DstRC)
     384             :     return true;
     385           2 :   return RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
     386             : }
     387             : 
     388             : static bool isConstant(const MachineInstr &MI) {
     389         102 :   return MI.getOpcode() == TargetOpcode::G_CONSTANT;
     390             : }
     391             : 
     392         106 : void AMDGPUInstructionSelector::getAddrModeInfo(const MachineInstr &Load,
     393             :     const MachineRegisterInfo &MRI, SmallVectorImpl<GEPInfo> &AddrInfo) const {
     394             : 
     395         106 :   const MachineInstr *PtrMI = MRI.getUniqueVRegDef(Load.getOperand(1).getReg());
     396             : 
     397             :   assert(PtrMI);
     398             : 
     399         212 :   if (PtrMI->getOpcode() != TargetOpcode::G_GEP)
     400          55 :     return;
     401             : 
     402          51 :   GEPInfo GEPInfo(*PtrMI);
     403             : 
     404         153 :   for (unsigned i = 1, e = 3; i < e; ++i) {
     405         102 :     const MachineOperand &GEPOp = PtrMI->getOperand(i);
     406         102 :     const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.getReg());
     407             :     assert(OpDef);
     408         102 :     if (isConstant(*OpDef)) {
     409             :       // FIXME: Is it possible to have multiple Imm parts?  Maybe if we
     410             :       // are lacking other optimizations.
     411             :       assert(GEPInfo.Imm == 0);
     412          51 :       GEPInfo.Imm = OpDef->getOperand(1).getCImm()->getSExtValue();
     413          51 :       continue;
     414             :     }
     415          51 :     const RegisterBank *OpBank = RBI.getRegBank(GEPOp.getReg(), MRI, TRI);
     416          51 :     if (OpBank->getID() == AMDGPU::SGPRRegBankID)
     417          51 :       GEPInfo.SgprParts.push_back(GEPOp.getReg());
     418             :     else
     419           0 :       GEPInfo.VgprParts.push_back(GEPOp.getReg());
     420             :   }
     421             : 
     422          51 :   AddrInfo.push_back(GEPInfo);
     423          51 :   getAddrModeInfo(*PtrMI, MRI, AddrInfo);
     424             : }
     425             : 
     426          52 : static bool isInstrUniform(const MachineInstr &MI) {
     427          52 :   if (!MI.hasOneMemOperand())
     428             :     return false;
     429             : 
     430          52 :   const MachineMemOperand *MMO = *MI.memoperands_begin();
     431             :   const Value *Ptr = MMO->getValue();
     432             : 
     433             :   // UndefValue means this is a load of a kernel input.  These are uniform.
     434             :   // Sometimes LDS instructions have constant pointers.
     435             :   // If Ptr is null, then that means this mem operand contains a
     436             :   // PseudoSourceValue like GOT.
     437          52 :   if (!Ptr || isa<UndefValue>(Ptr) || isa<Argument>(Ptr) ||
     438          52 :       isa<Constant>(Ptr) || isa<GlobalValue>(Ptr))
     439             :     return true;
     440             : 
     441          24 :   if (MMO->getAddrSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
     442             :     return true;
     443             : 
     444             :   const Instruction *I = dyn_cast<Instruction>(Ptr);
     445          24 :   return I && I->getMetadata("amdgpu.uniform");
     446             : }
     447             : 
     448             : static unsigned getSmrdOpcode(unsigned BaseOpcode, unsigned LoadSize) {
     449             : 
     450          42 :   if (LoadSize == 32)
     451             :     return BaseOpcode;
     452             : 
     453             :   switch (BaseOpcode) {
     454          12 :   case AMDGPU::S_LOAD_DWORD_IMM:
     455             :     switch (LoadSize) {
     456             :     case 64:
     457             :       return AMDGPU::S_LOAD_DWORDX2_IMM;
     458           0 :     case 128:
     459             :       return AMDGPU::S_LOAD_DWORDX4_IMM;
     460           0 :     case 256:
     461             :       return AMDGPU::S_LOAD_DWORDX8_IMM;
     462           0 :     case 512:
     463             :       return AMDGPU::S_LOAD_DWORDX16_IMM;
     464             :     }
     465             :     break;
     466           0 :   case AMDGPU::S_LOAD_DWORD_IMM_ci:
     467             :     switch (LoadSize) {
     468             :     case 64:
     469             :       return AMDGPU::S_LOAD_DWORDX2_IMM_ci;
     470           0 :     case 128:
     471             :       return AMDGPU::S_LOAD_DWORDX4_IMM_ci;
     472           0 :     case 256:
     473             :       return AMDGPU::S_LOAD_DWORDX8_IMM_ci;
     474           0 :     case 512:
     475             :       return AMDGPU::S_LOAD_DWORDX16_IMM_ci;
     476             :     }
     477             :     break;
     478           0 :   case AMDGPU::S_LOAD_DWORD_SGPR:
     479             :     switch (LoadSize) {
     480             :     case 64:
     481             :       return AMDGPU::S_LOAD_DWORDX2_SGPR;
     482           0 :     case 128:
     483             :       return AMDGPU::S_LOAD_DWORDX4_SGPR;
     484           0 :     case 256:
     485             :       return AMDGPU::S_LOAD_DWORDX8_SGPR;
     486           0 :     case 512:
     487             :       return AMDGPU::S_LOAD_DWORDX16_SGPR;
     488             :     }
     489             :     break;
     490             :   }
     491           0 :   llvm_unreachable("Invalid base smrd opcode or size");
     492             : }
     493             : 
     494          52 : bool AMDGPUInstructionSelector::hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const {
     495         103 :   for (const GEPInfo &GEPInfo : AddrInfo) {
     496          51 :     if (!GEPInfo.VgprParts.empty())
     497             :       return true;
     498             :   }
     499             :   return false;
     500             : }
     501             : 
     502          55 : bool AMDGPUInstructionSelector::selectSMRD(MachineInstr &I,
     503             :                                            ArrayRef<GEPInfo> AddrInfo) const {
     504             : 
     505          55 :   if (!I.hasOneMemOperand())
     506             :     return false;
     507             : 
     508          58 :   if ((*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS &&
     509           3 :       (*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS_32BIT)
     510             :     return false;
     511             : 
     512          52 :   if (!isInstrUniform(I))
     513             :     return false;
     514             : 
     515          52 :   if (hasVgprParts(AddrInfo))
     516             :     return false;
     517             : 
     518          52 :   MachineBasicBlock *BB = I.getParent();
     519          52 :   MachineFunction *MF = BB->getParent();
     520          52 :   const GCNSubtarget &Subtarget = MF->getSubtarget<GCNSubtarget>();
     521          52 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     522          52 :   unsigned DstReg = I.getOperand(0).getReg();
     523             :   const DebugLoc &DL = I.getDebugLoc();
     524             :   unsigned Opcode;
     525          52 :   unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
     526             : 
     527          52 :   if (!AddrInfo.empty() && AddrInfo[0].SgprParts.size() == 1) {
     528             : 
     529             :     const GEPInfo &GEPInfo = AddrInfo[0];
     530             : 
     531          51 :     unsigned PtrReg = GEPInfo.SgprParts[0];
     532          51 :     int64_t EncodedImm = AMDGPU::getSMRDEncodedOffset(Subtarget, GEPInfo.Imm);
     533          51 :     if (AMDGPU::isLegalSMRDImmOffset(Subtarget, GEPInfo.Imm)) {
     534             :       Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
     535             : 
     536          26 :       MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     537          26 :                                  .addReg(PtrReg)
     538             :                                  .addImm(EncodedImm)
     539          26 :                                  .addImm(0); // glc
     540          26 :       return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     541             :     }
     542             : 
     543          25 :     if (Subtarget.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS &&
     544          11 :         isUInt<32>(EncodedImm)) {
     545             :       Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM_ci, LoadSize);
     546           9 :       MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     547           9 :                                    .addReg(PtrReg)
     548             :                                    .addImm(EncodedImm)
     549           9 :                                    .addImm(0); // glc
     550           9 :       return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     551             :     }
     552             : 
     553          16 :     if (isUInt<32>(GEPInfo.Imm)) {
     554             :       Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_SGPR, LoadSize);
     555           7 :       unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
     556           7 :       BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), OffsetReg)
     557           7 :               .addImm(GEPInfo.Imm);
     558             : 
     559           7 :       MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     560           7 :                                    .addReg(PtrReg)
     561           7 :                                    .addReg(OffsetReg)
     562           7 :                                    .addImm(0); // glc
     563           7 :       return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     564             :     }
     565             :   }
     566             : 
     567          10 :   unsigned PtrReg = I.getOperand(1).getReg();
     568             :   Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
     569          10 :   MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
     570          10 :                                .addReg(PtrReg)
     571             :                                .addImm(0)
     572          10 :                                .addImm(0); // glc
     573          10 :   return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
     574             : }
     575             : 
     576             : 
     577          55 : bool AMDGPUInstructionSelector::selectG_LOAD(MachineInstr &I) const {
     578          55 :   MachineBasicBlock *BB = I.getParent();
     579          55 :   MachineFunction *MF = BB->getParent();
     580          55 :   MachineRegisterInfo &MRI = MF->getRegInfo();
     581             :   DebugLoc DL = I.getDebugLoc();
     582          55 :   unsigned DstReg = I.getOperand(0).getReg();
     583          55 :   unsigned PtrReg = I.getOperand(1).getReg();
     584          55 :   unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
     585             :   unsigned Opcode;
     586             : 
     587          55 :   SmallVector<GEPInfo, 4> AddrInfo;
     588             : 
     589          55 :   getAddrModeInfo(I, MRI, AddrInfo);
     590             : 
     591          55 :   if (selectSMRD(I, AddrInfo)) {
     592          52 :     I.eraseFromParent();
     593          52 :     return true;
     594             :   }
     595             : 
     596           3 :   switch (LoadSize) {
     597           0 :   default:
     598           0 :     llvm_unreachable("Load size not supported\n");
     599             :   case 32:
     600             :     Opcode = AMDGPU::FLAT_LOAD_DWORD;
     601             :     break;
     602           0 :   case 64:
     603             :     Opcode = AMDGPU::FLAT_LOAD_DWORDX2;
     604           0 :     break;
     605             :   }
     606             : 
     607           3 :   MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode))
     608           3 :                                .add(I.getOperand(0))
     609           3 :                                .addReg(PtrReg)
     610             :                                .addImm(0)  // offset
     611             :                                .addImm(0)  // glc
     612           3 :                                .addImm(0); // slc
     613             : 
     614           3 :   bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
     615           3 :   I.eraseFromParent();
     616           3 :   return Ret;
     617             : }
     618             : 
     619         415 : bool AMDGPUInstructionSelector::select(MachineInstr &I,
     620             :                                        CodeGenCoverage &CoverageInfo) const {
     621             : 
     622         830 :   if (!isPreISelGenericOpcode(I.getOpcode())) {
     623         153 :     if (I.isCopy())
     624         140 :       return selectCOPY(I);
     625             :     return true;
     626             :   }
     627             : 
     628         262 :   switch (I.getOpcode()) {
     629          38 :   default:
     630          38 :     return selectImpl(I, CoverageInfo);
     631           0 :   case TargetOpcode::G_ADD:
     632           0 :     return selectG_ADD(I);
     633          11 :   case TargetOpcode::G_INTTOPTR:
     634             :   case TargetOpcode::G_BITCAST:
     635          11 :     return selectCOPY(I);
     636          25 :   case TargetOpcode::G_CONSTANT:
     637             :   case TargetOpcode::G_FCONSTANT:
     638          25 :     return selectG_CONSTANT(I);
     639           9 :   case TargetOpcode::G_GEP:
     640           9 :     return selectG_GEP(I);
     641          20 :   case TargetOpcode::G_IMPLICIT_DEF:
     642          20 :     return selectG_IMPLICIT_DEF(I);
     643          31 :   case TargetOpcode::G_INTRINSIC:
     644          31 :     return selectG_INTRINSIC(I, CoverageInfo);
     645           4 :   case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
     646           4 :     return selectG_INTRINSIC_W_SIDE_EFFECTS(I, CoverageInfo);
     647          55 :   case TargetOpcode::G_LOAD:
     648          55 :     return selectG_LOAD(I);
     649          69 :   case TargetOpcode::G_STORE:
     650          69 :     return selectG_STORE(I);
     651             :   }
     652             :   return false;
     653             : }
     654             : 
     655             : InstructionSelector::ComplexRendererFns
     656           6 : AMDGPUInstructionSelector::selectVCSRC(MachineOperand &Root) const {
     657             :   return {{
     658           6 :       [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
     659          18 :   }};
     660             : 
     661             : }
     662             : 
     663             : ///
     664             : /// This will select either an SGPR or VGPR operand and will save us from
     665             : /// having to write an extra tablegen pattern.
     666             : InstructionSelector::ComplexRendererFns
     667          20 : AMDGPUInstructionSelector::selectVSRC0(MachineOperand &Root) const {
     668             :   return {{
     669          20 :       [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
     670          60 :   }};
     671             : }
     672             : 
     673             : InstructionSelector::ComplexRendererFns
     674          20 : AMDGPUInstructionSelector::selectVOP3Mods0(MachineOperand &Root) const {
     675             :   return {{
     676          20 :       [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
     677             :       [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // src0_mods
     678             :       [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
     679             :       [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }  // omod
     680         120 :   }};
     681             : }
     682             : InstructionSelector::ComplexRendererFns
     683           2 : AMDGPUInstructionSelector::selectVOP3OMods(MachineOperand &Root) const {
     684             :   return {{
     685           2 :       [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
     686             :       [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
     687             :       [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }  // omod
     688          10 :   }};
     689             : }
     690             : 
     691             : InstructionSelector::ComplexRendererFns
     692          18 : AMDGPUInstructionSelector::selectVOP3Mods(MachineOperand &Root) const {
     693             :   return {{
     694          18 :       [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
     695             :       [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }  // src_mods
     696          72 :   }};
     697             : }

Generated by: LCOV version 1.13