Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AMDGPU/SIAddIMGInit.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- SIAddIMGInit.cpp - Add any required IMG inits ---------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
/// \file
10
/// Any MIMG instructions that use tfe or lwe require an initialization of the
11
/// result register that will be written in the case of a memory access failure
12
/// The required code is also added to tie this init code to the result of the
13
/// img instruction
14
///
15
//===----------------------------------------------------------------------===//
16
//
17
18
#include "AMDGPU.h"
19
#include "AMDGPUSubtarget.h"
20
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
21
#include "SIInstrInfo.h"
22
#include "llvm/CodeGen/MachineFunctionPass.h"
23
#include "llvm/CodeGen/MachineInstrBuilder.h"
24
#include "llvm/CodeGen/MachineRegisterInfo.h"
25
#include "llvm/IR/Function.h"
26
#include "llvm/Support/Debug.h"
27
#include "llvm/Target/TargetMachine.h"
28
29
#define DEBUG_TYPE "si-img-init"
30
31
using namespace llvm;
32
33
namespace {
34
35
class SIAddIMGInit : public MachineFunctionPass {
36
public:
37
  static char ID;
38
39
public:
40
2.40k
  SIAddIMGInit() : MachineFunctionPass(ID) {
41
2.40k
    initializeSIAddIMGInitPass(*PassRegistry::getPassRegistry());
42
2.40k
  }
43
44
  bool runOnMachineFunction(MachineFunction &MF) override;
45
46
2.38k
  void getAnalysisUsage(AnalysisUsage &AU) const override {
47
2.38k
    AU.setPreservesCFG();
48
2.38k
    MachineFunctionPass::getAnalysisUsage(AU);
49
2.38k
  }
50
};
51
52
} // End anonymous namespace.
53
54
INITIALIZE_PASS(SIAddIMGInit, DEBUG_TYPE, "SI Add IMG Init", false, false)
55
56
char SIAddIMGInit::ID = 0;
57
58
char &llvm::SIAddIMGInitID = SIAddIMGInit::ID;
59
60
2.40k
FunctionPass *llvm::createSIAddIMGInitPass() { return new SIAddIMGInit(); }
61
62
25.1k
bool SIAddIMGInit::runOnMachineFunction(MachineFunction &MF) {
63
25.1k
  MachineRegisterInfo &MRI = MF.getRegInfo();
64
25.1k
  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
65
25.1k
  const SIInstrInfo *TII = ST.getInstrInfo();
66
25.1k
  const SIRegisterInfo *RI = ST.getRegisterInfo();
67
25.1k
  bool Changed = false;
68
25.1k
69
53.6k
  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE;
70
28.4k
       ++BI) {
71
28.4k
    MachineBasicBlock &MBB = *BI;
72
28.4k
    MachineBasicBlock::iterator I, Next;
73
781k
    for (I = MBB.begin(); I != MBB.end(); 
I = Next753k
) {
74
753k
      Next = std::next(I);
75
753k
      MachineInstr &MI = *I;
76
753k
77
753k
      auto Opcode = MI.getOpcode();
78
753k
      if (TII->isMIMG(Opcode) && 
!MI.mayStore()1.26k
) {
79
1.01k
        MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
80
1.01k
        MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
81
1.01k
        MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16);
82
1.01k
83
1.01k
        // Check for instructions that don't have tfe or lwe fields
84
1.01k
        // There shouldn't be any at this point.
85
1.01k
        assert( (TFE && LWE) && "Expected tfe and lwe operands in instruction");
86
1.01k
87
1.01k
        unsigned TFEVal = TFE->getImm();
88
1.01k
        unsigned LWEVal = LWE->getImm();
89
1.01k
        unsigned D16Val = D16 ? 
D16->getImm()954
:
057
;
90
1.01k
91
1.01k
        if (TFEVal || 
LWEVal884
) {
92
150
          // At least one of TFE or LWE are non-zero
93
150
          // We have to insert a suitable initialization of the result value and
94
150
          // tie this to the dest of the image instruction.
95
150
96
150
          const DebugLoc &DL = MI.getDebugLoc();
97
150
98
150
          int DstIdx =
99
150
              AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
100
150
101
150
          // Calculate which dword we have to initialize to 0.
102
150
          MachineOperand *MO_Dmask =
103
150
              TII->getNamedOperand(MI, AMDGPU::OpName::dmask);
104
150
105
150
          // check that dmask operand is found.
106
150
          assert(MO_Dmask && "Expected dmask operand in instruction");
107
150
108
150
          unsigned dmask = MO_Dmask->getImm();
109
150
          // Determine the number of active lanes taking into account the
110
150
          // Gather4 special case
111
150
          unsigned ActiveLanes =
112
150
              TII->isGather4(Opcode) ? 
40
: countPopulation(dmask);
113
150
114
150
          // Subreg indices are counted from 1
115
150
          // When D16 then we want next whole VGPR after write data.
116
150
          static_assert(AMDGPU::sub0 == 1 && AMDGPU::sub4 == 5, "Subreg indices different from expected");
117
150
118
150
          bool Packed = !ST.hasUnpackedD16VMem();
119
150
120
150
          unsigned InitIdx =
121
150
              D16Val && 
Packed12
?
((ActiveLanes + 1) >> 1) + 19
:
ActiveLanes + 1141
;
122
150
123
150
          // Abandon attempt if the dst size isn't large enough
124
150
          // - this is in fact an error but this is picked up elsewhere and
125
150
          // reported correctly.
126
150
          uint32_t DstSize =
127
150
              RI->getRegSizeInBits(*TII->getOpRegClass(MI, DstIdx)) / 32;
128
150
          if (DstSize < InitIdx)
129
0
            continue;
130
150
131
150
          // Create a register for the intialization value.
132
150
          unsigned PrevDst =
133
150
              MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
134
150
          unsigned NewDst = 0; // Final initialized value will be in here
135
150
136
150
          // If PRTStrictNull feature is enabled (the default) then initialize
137
150
          // all the result registers to 0, otherwise just the error indication
138
150
          // register (VGPRn+1)
139
150
          unsigned SizeLeft = ST.usePRTStrictNull() ? 
InitIdx129
:
121
;
140
150
          unsigned CurrIdx = ST.usePRTStrictNull() ? 
1129
:
InitIdx21
;
141
150
142
150
          if (DstSize == 1) {
143
0
            // In this case we can just initialize the result directly
144
0
            BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), PrevDst)
145
0
                .addImm(0);
146
0
            NewDst = PrevDst;
147
150
          } else {
148
150
            BuildMI(MBB, MI, DL, TII->get(AMDGPU::IMPLICIT_DEF), PrevDst);
149
613
            for (; SizeLeft; 
SizeLeft--, CurrIdx++463
) {
150
463
              NewDst =
151
463
                  MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx));
152
463
              // Initialize dword
153
463
              unsigned SubReg =
154
463
                  MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
155
463
              BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_MOV_B32_e32), SubReg)
156
463
                  .addImm(0);
157
463
              // Insert into the super-reg
158
463
              BuildMI(MBB, I, DL, TII->get(TargetOpcode::INSERT_SUBREG), NewDst)
159
463
                  .addReg(PrevDst)
160
463
                  .addReg(SubReg)
161
463
                  .addImm(CurrIdx);
162
463
163
463
              PrevDst = NewDst;
164
463
            }
165
150
          }
166
150
167
150
          // Add as an implicit operand
168
150
          MachineInstrBuilder(MF, MI).addReg(NewDst, RegState::Implicit);
169
150
170
150
          // Tie the just added implicit operand to the dst
171
150
          MI.tieOperands(DstIdx, MI.getNumOperands() - 1);
172
150
173
150
          Changed = true;
174
150
        }
175
1.01k
      }
176
753k
    }
177
28.4k
  }
178
25.1k
179
25.1k
  return Changed;
180
25.1k
}