/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 | } |