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