LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - SIMachineFunctionInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 163 164 99.4 %
Date: 2018-10-20 13:21:21 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- SIMachineFunctionInfo.cpp - SI Machine Function Info ---------------===//
       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             : #include "SIMachineFunctionInfo.h"
      11             : #include "AMDGPUArgumentUsageInfo.h"
      12             : #include "AMDGPUSubtarget.h"
      13             : #include "SIRegisterInfo.h"
      14             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      15             : #include "Utils/AMDGPUBaseInfo.h"
      16             : #include "llvm/ADT/Optional.h"
      17             : #include "llvm/CodeGen/MachineBasicBlock.h"
      18             : #include "llvm/CodeGen/MachineFrameInfo.h"
      19             : #include "llvm/CodeGen/MachineFunction.h"
      20             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      21             : #include "llvm/IR/CallingConv.h"
      22             : #include "llvm/IR/Function.h"
      23             : #include <cassert>
      24             : #include <vector>
      25             : 
      26             : #define MAX_LANES 64
      27             : 
      28             : using namespace llvm;
      29             : 
      30       20671 : SIMachineFunctionInfo::SIMachineFunctionInfo(const MachineFunction &MF)
      31             :   : AMDGPUMachineFunction(MF),
      32             :     PrivateSegmentBuffer(false),
      33             :     DispatchPtr(false),
      34             :     QueuePtr(false),
      35             :     KernargSegmentPtr(false),
      36             :     DispatchID(false),
      37             :     FlatScratchInit(false),
      38             :     WorkGroupIDX(false),
      39             :     WorkGroupIDY(false),
      40             :     WorkGroupIDZ(false),
      41             :     WorkGroupInfo(false),
      42             :     PrivateSegmentWaveByteOffset(false),
      43             :     WorkItemIDX(false),
      44             :     WorkItemIDY(false),
      45             :     WorkItemIDZ(false),
      46             :     ImplicitBufferPtr(false),
      47             :     ImplicitArgPtr(false),
      48             :     GITPtrHigh(0xffffffff),
      49       20671 :     HighBitsOf32BitAddress(0) {
      50       20671 :   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
      51       20671 :   const Function &F = MF.getFunction();
      52       20671 :   FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F);
      53       20671 :   WavesPerEU = ST.getWavesPerEU(F);
      54             : 
      55       20671 :   Occupancy = getMaxWavesPerEU();
      56       20671 :   limitOccupancy(MF);
      57             :   CallingConv::ID CC = F.getCallingConv();
      58             : 
      59       20671 :   if (CC == CallingConv::AMDGPU_KERNEL || CC == CallingConv::SPIR_KERNEL) {
      60       16403 :     if (!F.arg_empty())
      61       15259 :       KernargSegmentPtr = true;
      62       16403 :     WorkGroupIDX = true;
      63       16403 :     WorkItemIDX = true;
      64        4268 :   } else if (CC == CallingConv::AMDGPU_PS) {
      65        1444 :     PSInputAddr = AMDGPU::getInitialPSInputAddr(F);
      66             :   }
      67             : 
      68       20671 :   if (!isEntryFunction()) {
      69             :     // Non-entry functions have no special inputs for now, other registers
      70             :     // required for scratch access.
      71        2506 :     ScratchRSrcReg = AMDGPU::SGPR0_SGPR1_SGPR2_SGPR3;
      72        2506 :     ScratchWaveOffsetReg = AMDGPU::SGPR4;
      73        2506 :     FrameOffsetReg = AMDGPU::SGPR5;
      74        2506 :     StackPtrOffsetReg = AMDGPU::SGPR32;
      75             : 
      76        2506 :     ArgInfo.PrivateSegmentBuffer =
      77        5012 :       ArgDescriptor::createRegister(ScratchRSrcReg);
      78        2506 :     ArgInfo.PrivateSegmentWaveByteOffset =
      79        2506 :       ArgDescriptor::createRegister(ScratchWaveOffsetReg);
      80             : 
      81        2506 :     if (F.hasFnAttribute("amdgpu-implicitarg-ptr"))
      82          12 :       ImplicitArgPtr = true;
      83             :   } else {
      84       18165 :     if (F.hasFnAttribute("amdgpu-implicitarg-ptr")) {
      85          42 :       KernargSegmentPtr = true;
      86          50 :       MaxKernArgAlign = std::max(ST.getAlignmentForImplicitArgPtr(),
      87          42 :                                  MaxKernArgAlign);
      88             :     }
      89             :   }
      90             : 
      91       20671 :   if (ST.debuggerEmitPrologue()) {
      92             :     // Enable everything.
      93           4 :     WorkGroupIDX = true;
      94           4 :     WorkGroupIDY = true;
      95           4 :     WorkGroupIDZ = true;
      96           4 :     WorkItemIDX = true;
      97           4 :     WorkItemIDY = true;
      98           4 :     WorkItemIDZ = true;
      99             :   } else {
     100       20667 :     if (F.hasFnAttribute("amdgpu-work-group-id-x"))
     101          34 :       WorkGroupIDX = true;
     102             : 
     103       20667 :     if (F.hasFnAttribute("amdgpu-work-group-id-y"))
     104          40 :       WorkGroupIDY = true;
     105             : 
     106       20667 :     if (F.hasFnAttribute("amdgpu-work-group-id-z"))
     107          40 :       WorkGroupIDZ = true;
     108             : 
     109       20667 :     if (F.hasFnAttribute("amdgpu-work-item-id-x"))
     110          26 :       WorkItemIDX = true;
     111             : 
     112       20667 :     if (F.hasFnAttribute("amdgpu-work-item-id-y"))
     113         134 :       WorkItemIDY = true;
     114             : 
     115       20667 :     if (F.hasFnAttribute("amdgpu-work-item-id-z"))
     116          81 :       WorkItemIDZ = true;
     117             :   }
     118             : 
     119       20671 :   const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
     120       20671 :   bool MaySpill = ST.isVGPRSpillingEnabled(F);
     121             :   bool HasStackObjects = FrameInfo.hasStackObjects();
     122             : 
     123       20671 :   if (isEntryFunction()) {
     124             :     // X, XY, and XYZ are the only supported combinations, so make sure Y is
     125             :     // enabled if Z is.
     126       18165 :     if (WorkItemIDZ)
     127          77 :       WorkItemIDY = true;
     128             : 
     129       18165 :     if (HasStackObjects || MaySpill) {
     130       16453 :       PrivateSegmentWaveByteOffset = true;
     131             : 
     132             :     // HS and GS always have the scratch wave offset in SGPR5 on GFX9.
     133       16453 :     if (ST.getGeneration() >= AMDGPUSubtarget::GFX9 &&
     134        2828 :         (CC == CallingConv::AMDGPU_HS || CC == CallingConv::AMDGPU_GS))
     135             :       ArgInfo.PrivateSegmentWaveByteOffset
     136           5 :         = ArgDescriptor::createRegister(AMDGPU::SGPR5);
     137             :     }
     138             :   }
     139             : 
     140       20671 :   bool isAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
     141       20671 :   if (isAmdHsaOrMesa) {
     142        3130 :     if (HasStackObjects || MaySpill)
     143        3127 :       PrivateSegmentBuffer = true;
     144             : 
     145        3130 :     if (F.hasFnAttribute("amdgpu-dispatch-ptr"))
     146          53 :       DispatchPtr = true;
     147             : 
     148        3130 :     if (F.hasFnAttribute("amdgpu-queue-ptr"))
     149          68 :       QueuePtr = true;
     150             : 
     151        3130 :     if (F.hasFnAttribute("amdgpu-dispatch-id"))
     152          15 :       DispatchID = true;
     153             :   } else if (ST.isMesaGfxShader(F)) {
     154          11 :     if (HasStackObjects || MaySpill)
     155           2 :       ImplicitBufferPtr = true;
     156             :   }
     157             : 
     158       20671 :   if (F.hasFnAttribute("amdgpu-kernarg-segment-ptr"))
     159       14781 :     KernargSegmentPtr = true;
     160             : 
     161       20671 :   if (ST.hasFlatAddressSpace() && isEntryFunction() && isAmdHsaOrMesa) {
     162             :     // TODO: This could be refined a lot. The attribute is a poor way of
     163             :     // detecting calls that may require it before argument lowering.
     164        5026 :     if (HasStackObjects || F.hasFnAttribute("amdgpu-flat-scratch"))
     165         384 :       FlatScratchInit = true;
     166             :   }
     167             : 
     168       20671 :   Attribute A = F.getFnAttribute("amdgpu-git-ptr-high");
     169       20671 :   StringRef S = A.getValueAsString();
     170       20671 :   if (!S.empty())
     171           2 :     S.consumeInteger(0, GITPtrHigh);
     172             : 
     173       20671 :   A = F.getFnAttribute("amdgpu-32bit-address-high-bits");
     174       20671 :   S = A.getValueAsString();
     175       20671 :   if (!S.empty())
     176          16 :     S.consumeInteger(0, HighBitsOf32BitAddress);
     177       20671 : }
     178             : 
     179       40419 : void SIMachineFunctionInfo::limitOccupancy(const MachineFunction &MF) {
     180       40419 :   limitOccupancy(getMaxWavesPerEU());
     181       40419 :   const GCNSubtarget& ST = MF.getSubtarget<GCNSubtarget>();
     182       40419 :   limitOccupancy(ST.getOccupancyWithLocalMemSize(getLDSSize(),
     183             :                  MF.getFunction()));
     184       40419 : }
     185             : 
     186        2602 : unsigned SIMachineFunctionInfo::addPrivateSegmentBuffer(
     187             :   const SIRegisterInfo &TRI) {
     188        2602 :   ArgInfo.PrivateSegmentBuffer =
     189        2602 :     ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     190        2602 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_128RegClass));
     191        2602 :   NumUserSGPRs += 4;
     192        2602 :   return ArgInfo.PrivateSegmentBuffer.getRegister();
     193             : }
     194             : 
     195          42 : unsigned SIMachineFunctionInfo::addDispatchPtr(const SIRegisterInfo &TRI) {
     196          42 :   ArgInfo.DispatchPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     197          42 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
     198          42 :   NumUserSGPRs += 2;
     199          42 :   return ArgInfo.DispatchPtr.getRegister();
     200             : }
     201             : 
     202          57 : unsigned SIMachineFunctionInfo::addQueuePtr(const SIRegisterInfo &TRI) {
     203          57 :   ArgInfo.QueuePtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     204          57 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
     205          57 :   NumUserSGPRs += 2;
     206          57 :   return ArgInfo.QueuePtr.getRegister();
     207             : }
     208             : 
     209       15227 : unsigned SIMachineFunctionInfo::addKernargSegmentPtr(const SIRegisterInfo &TRI) {
     210             :   ArgInfo.KernargSegmentPtr
     211       15227 :     = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     212       15227 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
     213       15227 :   NumUserSGPRs += 2;
     214       15227 :   return ArgInfo.KernargSegmentPtr.getRegister();
     215             : }
     216             : 
     217           5 : unsigned SIMachineFunctionInfo::addDispatchID(const SIRegisterInfo &TRI) {
     218           5 :   ArgInfo.DispatchID = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     219           5 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
     220           5 :   NumUserSGPRs += 2;
     221           5 :   return ArgInfo.DispatchID.getRegister();
     222             : }
     223             : 
     224         381 : unsigned SIMachineFunctionInfo::addFlatScratchInit(const SIRegisterInfo &TRI) {
     225         381 :   ArgInfo.FlatScratchInit = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     226         381 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
     227         381 :   NumUserSGPRs += 2;
     228         381 :   return ArgInfo.FlatScratchInit.getRegister();
     229             : }
     230             : 
     231           2 : unsigned SIMachineFunctionInfo::addImplicitBufferPtr(const SIRegisterInfo &TRI) {
     232           2 :   ArgInfo.ImplicitBufferPtr = ArgDescriptor::createRegister(TRI.getMatchingSuperReg(
     233           2 :     getNextUserSGPR(), AMDGPU::sub0, &AMDGPU::SReg_64RegClass));
     234           2 :   NumUserSGPRs += 2;
     235           2 :   return ArgInfo.ImplicitBufferPtr.getRegister();
     236             : }
     237             : 
     238             : static bool isCalleeSavedReg(const MCPhysReg *CSRegs, MCPhysReg Reg) {
     239        3668 :   for (unsigned I = 0; CSRegs[I]; ++I) {
     240        3656 :     if (CSRegs[I] == Reg)
     241             :       return true;
     242             :   }
     243             : 
     244             :   return false;
     245             : }
     246             : 
     247             : /// Reserve a slice of a VGPR to support spilling for FrameIndex \p FI.
     248        1282 : bool SIMachineFunctionInfo::allocateSGPRSpillToVGPR(MachineFunction &MF,
     249             :                                                     int FI) {
     250        1282 :   std::vector<SpilledReg> &SpillLanes = SGPRToVGPRSpills[FI];
     251             : 
     252             :   // This has already been allocated.
     253        1282 :   if (!SpillLanes.empty())
     254             :     return true;
     255             : 
     256         627 :   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
     257         627 :   const SIRegisterInfo *TRI = ST.getRegisterInfo();
     258         627 :   MachineFrameInfo &FrameInfo = MF.getFrameInfo();
     259         627 :   MachineRegisterInfo &MRI = MF.getRegInfo();
     260         627 :   unsigned WaveSize = ST.getWavefrontSize();
     261             : 
     262         627 :   unsigned Size = FrameInfo.getObjectSize(FI);
     263             :   assert(Size >= 4 && Size <= 64 && "invalid sgpr spill size");
     264             :   assert(TRI->spillSGPRToVGPR() && "not spilling SGPRs to VGPRs");
     265             : 
     266         627 :   int NumLanes = Size / 4;
     267             : 
     268         627 :   const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
     269             : 
     270             :   // Make sure to handle the case where a wide SGPR spill may span between two
     271             :   // VGPRs.
     272        1798 :   for (int I = 0; I < NumLanes; ++I, ++NumVGPRSpillLanes) {
     273             :     unsigned LaneVGPR;
     274        1175 :     unsigned VGPRIndex = (NumVGPRSpillLanes % WaveSize);
     275             : 
     276        1175 :     if (VGPRIndex == 0) {
     277         150 :       LaneVGPR = TRI->findUnusedRegister(MRI, &AMDGPU::VGPR_32RegClass, MF);
     278         150 :       if (LaneVGPR == AMDGPU::NoRegister) {
     279             :         // We have no VGPRs left for spilling SGPRs. Reset because we will not
     280             :         // partially spill the SGPR to VGPRs.
     281           4 :         SGPRToVGPRSpills.erase(FI);
     282           4 :         NumVGPRSpillLanes -= I;
     283             :         return false;
     284             :       }
     285             : 
     286             :       Optional<int> CSRSpillFI;
     287         244 :       if ((FrameInfo.hasCalls() || !isEntryFunction()) && CSRegs &&
     288          98 :           isCalleeSavedReg(CSRegs, LaneVGPR)) {
     289          86 :         CSRSpillFI = FrameInfo.CreateSpillStackObject(4, 4);
     290             :       }
     291             : 
     292         292 :       SpillVGPRs.push_back(SGPRSpillVGPRCSR(LaneVGPR, CSRSpillFI));
     293             : 
     294             :       // Add this register as live-in to all blocks to avoid machine verifer
     295             :       // complaining about use of an undefined physical register.
     296         487 :       for (MachineBasicBlock &BB : MF)
     297         341 :         BB.addLiveIn(LaneVGPR);
     298             :     } else {
     299        1025 :       LaneVGPR = SpillVGPRs.back().VGPR;
     300             :     }
     301             : 
     302        1171 :     SpillLanes.push_back(SpilledReg(LaneVGPR, VGPRIndex));
     303             :   }
     304             : 
     305             :   return true;
     306             : }
     307             : 
     308         142 : void SIMachineFunctionInfo::removeSGPRToVGPRFrameIndices(MachineFrameInfo &MFI) {
     309         765 :   for (auto &R : SGPRToVGPRSpills)
     310         623 :     MFI.RemoveStackObject(R.first);
     311         142 : }
     312             : 
     313             : 
     314             : /// \returns VGPR used for \p Dim' work item ID.
     315          12 : unsigned SIMachineFunctionInfo::getWorkItemIDVGPR(unsigned Dim) const {
     316             :   switch (Dim) {
     317             :   case 0:
     318             :     assert(hasWorkItemIDX());
     319             :     return AMDGPU::VGPR0;
     320             :   case 1:
     321             :     assert(hasWorkItemIDY());
     322             :     return AMDGPU::VGPR1;
     323             :   case 2:
     324             :     assert(hasWorkItemIDZ());
     325             :     return AMDGPU::VGPR2;
     326             :   }
     327           0 :   llvm_unreachable("unexpected dimension");
     328             : }
     329             : 
     330       18316 : MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
     331             :   assert(NumSystemSGPRs == 0 && "System SGPRs must be added after user SGPRs");
     332       18316 :   return AMDGPU::SGPR0 + NumUserSGPRs;
     333             : }
     334             : 
     335       32474 : MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
     336       32474 :   return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
     337             : }

Generated by: LCOV version 1.13