Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/NVPTX/NVPTXReplaceImageHandles.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- NVPTXReplaceImageHandles.cpp - Replace image handles for Fermi ----===//
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
// On Fermi, image handles are not supported. To work around this, we traverse
10
// the machine code and replace image handles with concrete symbols. For this
11
// to work reliably, inlining of all function call must be performed.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "NVPTX.h"
16
#include "NVPTXMachineFunctionInfo.h"
17
#include "NVPTXSubtarget.h"
18
#include "NVPTXTargetMachine.h"
19
#include "MCTargetDesc/NVPTXBaseInfo.h"
20
#include "llvm/ADT/DenseSet.h"
21
#include "llvm/CodeGen/MachineFunction.h"
22
#include "llvm/CodeGen/MachineFunctionPass.h"
23
#include "llvm/CodeGen/MachineRegisterInfo.h"
24
#include "llvm/Support/raw_ostream.h"
25
26
using namespace llvm;
27
28
namespace {
29
class NVPTXReplaceImageHandles : public MachineFunctionPass {
30
private:
31
  static char ID;
32
  DenseSet<MachineInstr *> InstrsToRemove;
33
34
public:
35
  NVPTXReplaceImageHandles();
36
37
  bool runOnMachineFunction(MachineFunction &MF) override;
38
39
1.01k
  StringRef getPassName() const override {
40
1.01k
    return "NVPTX Replace Image Handles";
41
1.01k
  }
42
private:
43
  bool processInstr(MachineInstr &MI);
44
  void replaceImageHandle(MachineOperand &Op, MachineFunction &MF);
45
  bool findIndexForHandle(MachineOperand &Op, MachineFunction &MF,
46
                          unsigned &Idx);
47
};
48
}
49
50
char NVPTXReplaceImageHandles::ID = 0;
51
52
NVPTXReplaceImageHandles::NVPTXReplaceImageHandles()
53
199
  : MachineFunctionPass(ID) {}
54
55
1.01k
bool NVPTXReplaceImageHandles::runOnMachineFunction(MachineFunction &MF) {
56
1.01k
  bool Changed = false;
57
1.01k
  InstrsToRemove.clear();
58
1.01k
59
2.09k
  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE;
60
1.08k
       ++BI) {
61
1.08k
    for (MachineBasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
62
7.74k
         I != E; 
++I6.66k
) {
63
6.66k
      MachineInstr &MI = *I;
64
6.66k
      Changed |= processInstr(MI);
65
6.66k
    }
66
1.08k
  }
67
1.01k
68
1.01k
  // Now clean up any handle-access instructions
69
1.01k
  // This is needed in debug mode when code cleanup passes are not executed,
70
1.01k
  // but we need the handle access to be eliminated because they are not
71
1.01k
  // valid instructions when image handles are disabled.
72
1.01k
  for (DenseSet<MachineInstr *>::iterator I = InstrsToRemove.begin(),
73
1.02k
       E = InstrsToRemove.end(); I != E; 
++I11
) {
74
11
    (*I)->eraseFromParent();
75
11
  }
76
1.01k
  return Changed;
77
1.01k
}
78
79
6.66k
bool NVPTXReplaceImageHandles::processInstr(MachineInstr &MI) {
80
6.66k
  MachineFunction &MF = *MI.getParent()->getParent();
81
6.66k
  const MCInstrDesc &MCID = MI.getDesc();
82
6.66k
83
6.66k
  if (MCID.TSFlags & NVPTXII::IsTexFlag) {
84
3
    // This is a texture fetch, so operand 4 is a texref and operand 5 is
85
3
    // a samplerref
86
3
    MachineOperand &TexHandle = MI.getOperand(4);
87
3
    replaceImageHandle(TexHandle, MF);
88
3
89
3
    if (!(MCID.TSFlags & NVPTXII::IsTexModeUnifiedFlag)) {
90
1
      MachineOperand &SampHandle = MI.getOperand(5);
91
1
      replaceImageHandle(SampHandle, MF);
92
1
    }
93
3
94
3
    return true;
95
6.65k
  } else if (MCID.TSFlags & NVPTXII::IsSuldMask) {
96
3
    unsigned VecSize =
97
3
      1 << (((MCID.TSFlags & NVPTXII::IsSuldMask) >> NVPTXII::IsSuldShift) - 1);
98
3
99
3
    // For a surface load of vector size N, the Nth operand will be the surfref
100
3
    MachineOperand &SurfHandle = MI.getOperand(VecSize);
101
3
102
3
    replaceImageHandle(SurfHandle, MF);
103
3
104
3
    return true;
105
6.65k
  } else if (MCID.TSFlags & NVPTXII::IsSustFlag) {
106
3
    // This is a surface store, so operand 0 is a surfref
107
3
    MachineOperand &SurfHandle = MI.getOperand(0);
108
3
109
3
    replaceImageHandle(SurfHandle, MF);
110
3
111
3
    return true;
112
6.65k
  } else if (MCID.TSFlags & NVPTXII::IsSurfTexQueryFlag) {
113
8
    // This is a query, so operand 1 is a surfref/texref
114
8
    MachineOperand &Handle = MI.getOperand(1);
115
8
116
8
    replaceImageHandle(Handle, MF);
117
8
118
8
    return true;
119
8
  }
120
6.64k
121
6.64k
  return false;
122
6.64k
}
123
124
void NVPTXReplaceImageHandles::
125
18
replaceImageHandle(MachineOperand &Op, MachineFunction &MF) {
126
18
  unsigned Idx;
127
18
  if (findIndexForHandle(Op, MF, Idx)) {
128
11
    Op.ChangeToImmediate(Idx);
129
11
  }
130
18
}
131
132
bool NVPTXReplaceImageHandles::
133
18
findIndexForHandle(MachineOperand &Op, MachineFunction &MF, unsigned &Idx) {
134
18
  const MachineRegisterInfo &MRI = MF.getRegInfo();
135
18
  NVPTXMachineFunctionInfo *MFI = MF.getInfo<NVPTXMachineFunctionInfo>();
136
18
137
18
  assert(Op.isReg() && "Handle is not in a reg?");
138
18
139
18
  // Which instruction defines the handle?
140
18
  MachineInstr &TexHandleDef = *MRI.getVRegDef(Op.getReg());
141
18
142
18
  switch (TexHandleDef.getOpcode()) {
143
18
  case NVPTX::LD_i64_avar: {
144
11
    // The handle is a parameter value being loaded, replace with the
145
11
    // parameter symbol
146
11
    const NVPTXTargetMachine &TM =
147
11
        static_cast<const NVPTXTargetMachine &>(MF.getTarget());
148
11
    if (TM.getDrvInterface() == NVPTX::CUDA) {
149
7
      // For CUDA, we preserve the param loads coming from function arguments
150
7
      return false;
151
7
    }
152
4
153
4
    assert(TexHandleDef.getOperand(6).isSymbol() && "Load is not a symbol!");
154
4
    StringRef Sym = TexHandleDef.getOperand(6).getSymbolName();
155
4
    std::string ParamBaseName = MF.getName();
156
4
    ParamBaseName += "_param_";
157
4
    assert(Sym.startswith(ParamBaseName) && "Invalid symbol reference");
158
4
    unsigned Param = atoi(Sym.data()+ParamBaseName.size());
159
4
    std::string NewSym;
160
4
    raw_string_ostream NewSymStr(NewSym);
161
4
    NewSymStr << MF.getName() << "_param_" << Param;
162
4
163
4
    InstrsToRemove.insert(&TexHandleDef);
164
4
    Idx = MFI->getImageHandleSymbolIndex(NewSymStr.str().c_str());
165
4
    return true;
166
4
  }
167
7
  case NVPTX::texsurf_handles: {
168
7
    // The handle is a global variable, replace with the global variable name
169
7
    assert(TexHandleDef.getOperand(1).isGlobal() && "Load is not a global!");
170
7
    const GlobalValue *GV = TexHandleDef.getOperand(1).getGlobal();
171
7
    assert(GV->hasName() && "Global sampler must be named!");
172
7
    InstrsToRemove.insert(&TexHandleDef);
173
7
    Idx = MFI->getImageHandleSymbolIndex(GV->getName().data());
174
7
    return true;
175
4
  }
176
4
  case NVPTX::nvvm_move_i64:
177
0
  case TargetOpcode::COPY: {
178
0
    bool Res = findIndexForHandle(TexHandleDef.getOperand(1), MF, Idx);
179
0
    if (Res) {
180
0
      InstrsToRemove.insert(&TexHandleDef);
181
0
    }
182
0
    return Res;
183
0
  }
184
0
  default:
185
0
    llvm_unreachable("Unknown instruction operating on handle");
186
18
  }
187
18
}
188
189
199
MachineFunctionPass *llvm::createNVPTXReplaceImageHandlesPass() {
190
199
  return new NVPTXReplaceImageHandles();
191
199
}