Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/NVPTX/NVPTXReplaceImageHandles.cpp @ 77:54457678186b LLVM3.6
LLVM 3.6
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 08 Sep 2014 22:06:00 +0900 |
parents | |
children | 60c9769439b8 |
comparison
equal
deleted
inserted
replaced
34:e874dbf0ad9d | 77:54457678186b |
---|---|
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) override; | |
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 } |