gallium: move sampler_unit field to pstip_fragment_shader since it's per-shader
[mesa.git] / src / gallium / auxiliary / gallivm / instructionssoa.cpp
1 #include "instructionssoa.h"
2
3 #include "storagesoa.h"
4
5 #include "pipe/p_shader_tokens.h"
6
7 #include <llvm/CallingConv.h>
8 #include <llvm/Constants.h>
9 #include <llvm/Module.h>
10 #include <llvm/Function.h>
11 #include <llvm/Instructions.h>
12 #include <llvm/Transforms/Utils/Cloning.h>
13 #include <llvm/ParamAttrsList.h>
14
15 #include <iostream>
16
17
18 /* disable some warnings. this file is autogenerated */
19 #if defined(__GNUC__)
20 #pragma GCC diagnostic ignored "-Wunused-variable"
21 #endif
22 using namespace llvm;
23 #include "gallivmsoabuiltins.cpp"
24 #if defined(__GNUC__)
25 #pragma GCC diagnostic warning "-Wunused-variable"
26 #endif
27
28 InstructionsSoa::InstructionsSoa(llvm::Module *mod, llvm::Function *func,
29 llvm::BasicBlock *block, StorageSoa *storage)
30 : m_builder(block),
31 m_storage(storage),
32 m_idx(0)
33 {
34 createFunctionMap();
35 createBuiltins();
36 }
37
38 const char * InstructionsSoa::name(const char *prefix) const
39 {
40 ++m_idx;
41 snprintf(m_name, 32, "%s%d", prefix, m_idx);
42 return m_name;
43 }
44
45 llvm::Value * InstructionsSoa::vectorFromVals(llvm::Value *x, llvm::Value *y,
46 llvm::Value *z, llvm::Value *w)
47 {
48 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
49 Constant *constVector = Constant::getNullValue(vectorType);
50 Value *res = m_builder.CreateInsertElement(constVector, x,
51 m_storage->constantInt(0),
52 name("vecx"));
53 res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
54 name("vecxy"));
55 res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
56 name("vecxyz"));
57 if (w)
58 res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
59 name("vecxyzw"));
60 return res;
61 }
62
63 std::vector<llvm::Value*> InstructionsSoa::arl(const std::vector<llvm::Value*> in)
64 {
65 std::vector<llvm::Value*> res(4);
66
67 //Extract x's
68 llvm::Value *x1 = m_builder.CreateExtractElement(in[0],
69 m_storage->constantInt(0),
70 name("extractX"));
71 //cast it to an unsigned int
72 x1 = m_builder.CreateFPToUI(x1, IntegerType::get(32), name("x1IntCast"));
73
74 res[0] = x1;//vectorFromVals(x1, x2, x3, x4);
75 //only x is valid. the others shouldn't be necessary
76 /*
77 res[1] = Constant::getNullValue(m_floatVecType);
78 res[2] = Constant::getNullValue(m_floatVecType);
79 res[3] = Constant::getNullValue(m_floatVecType);
80 */
81
82 return res;
83 }
84
85
86 std::vector<llvm::Value*> InstructionsSoa::add(const std::vector<llvm::Value*> in1,
87 const std::vector<llvm::Value*> in2)
88 {
89 std::vector<llvm::Value*> res(4);
90
91 res[0] = m_builder.CreateAdd(in1[0], in2[0], name("addx"));
92 res[1] = m_builder.CreateAdd(in1[1], in2[1], name("addy"));
93 res[2] = m_builder.CreateAdd(in1[2], in2[2], name("addz"));
94 res[3] = m_builder.CreateAdd(in1[3], in2[3], name("addw"));
95
96 return res;
97 }
98
99 std::vector<llvm::Value*> InstructionsSoa::mul(const std::vector<llvm::Value*> in1,
100 const std::vector<llvm::Value*> in2)
101 {
102 std::vector<llvm::Value*> res(4);
103
104 res[0] = m_builder.CreateMul(in1[0], in2[0], name("mulx"));
105 res[1] = m_builder.CreateMul(in1[1], in2[1], name("muly"));
106 res[2] = m_builder.CreateMul(in1[2], in2[2], name("mulz"));
107 res[3] = m_builder.CreateMul(in1[3], in2[3], name("mulw"));
108
109 return res;
110 }
111
112 void InstructionsSoa::end()
113 {
114 m_builder.CreateRetVoid();
115 }
116
117 std::vector<llvm::Value*> InstructionsSoa::madd(const std::vector<llvm::Value*> in1,
118 const std::vector<llvm::Value*> in2,
119 const std::vector<llvm::Value*> in3)
120 {
121 std::vector<llvm::Value*> res = mul(in1, in2);
122 return add(res, in3);
123 }
124
125 std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector)
126 {
127 std::vector<llvm::Value*> res(4);
128 res[0] = m_builder.CreateExtractElement(vector,
129 m_storage->constantInt(0),
130 name("extract1X"));
131 res[1] = m_builder.CreateExtractElement(vector,
132 m_storage->constantInt(1),
133 name("extract2X"));
134 res[2] = m_builder.CreateExtractElement(vector,
135 m_storage->constantInt(2),
136 name("extract3X"));
137 res[3] = m_builder.CreateExtractElement(vector,
138 m_storage->constantInt(3),
139 name("extract4X"));
140
141 return res;
142 }
143
144 void InstructionsSoa::createFunctionMap()
145 {
146 m_functionsMap[TGSI_OPCODE_DP3] = "dp3";
147 m_functionsMap[TGSI_OPCODE_DP4] = "dp4";
148 m_functionsMap[TGSI_OPCODE_POWER] = "pow";
149 }
150
151 void InstructionsSoa::createDependencies()
152 {
153 std::vector<std::string> powDeps(1);
154 powDeps[0] = "powf";
155 m_builtinDependencies["pow"] = powDeps;
156 }
157
158 llvm::Function * InstructionsSoa::function(int op)
159 {
160 if (m_functions.find(op) != m_functions.end())
161 return m_functions[op];
162
163 std::string name = m_functionsMap[op];
164
165 std::vector<std::string> deps = m_builtinDependencies[name];
166 for (unsigned int i = 0; i < deps.size(); ++i) {
167 injectFunction(m_builtins->getFunction(deps[i]));
168 }
169
170 llvm::Function *originalFunc = m_builtins->getFunction(name);
171 injectFunction(originalFunc, op);
172 return m_functions[op];
173 }
174
175 llvm::Module * InstructionsSoa::currentModule() const
176 {
177 BasicBlock *block = m_builder.GetInsertBlock();
178 if (!block || !block->getParent())
179 return 0;
180
181 return block->getParent()->getParent();
182 }
183
184 void InstructionsSoa::createBuiltins()
185 {
186 m_builtins = createSoaBuiltins();
187 createDependencies();
188 }
189
190 std::vector<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1,
191 const std::vector<llvm::Value*> in2)
192 {
193 llvm::Function *func = function(TGSI_OPCODE_DP3);
194 return callBuiltin(func, in1, in2);
195 }
196
197 llvm::Value * InstructionsSoa::allocaTemp()
198 {
199 VectorType *vector = VectorType::get(Type::FloatTy, 4);
200 ArrayType *vecArray = ArrayType::get(vector, 4);
201 AllocaInst *alloca = new AllocaInst(vecArray, name("tmpRes"),
202 m_builder.GetInsertBlock());
203
204 std::vector<Value*> indices;
205 indices.push_back(m_storage->constantInt(0));
206 indices.push_back(m_storage->constantInt(0));
207 GetElementPtrInst *getElem = new GetElementPtrInst(alloca,
208 indices.begin(),
209 indices.end(),
210 name("allocaPtr"),
211 m_builder.GetInsertBlock());
212 return getElem;
213 }
214
215 std::vector<llvm::Value*> InstructionsSoa::allocaToResult(llvm::Value *allocaPtr)
216 {
217 GetElementPtrInst *xElemPtr = new GetElementPtrInst(allocaPtr,
218 m_storage->constantInt(0),
219 name("xPtr"),
220 m_builder.GetInsertBlock());
221 GetElementPtrInst *yElemPtr = new GetElementPtrInst(allocaPtr,
222 m_storage->constantInt(1),
223 name("yPtr"),
224 m_builder.GetInsertBlock());
225 GetElementPtrInst *zElemPtr = new GetElementPtrInst(allocaPtr,
226 m_storage->constantInt(2),
227 name("zPtr"),
228 m_builder.GetInsertBlock());
229 GetElementPtrInst *wElemPtr = new GetElementPtrInst(allocaPtr,
230 m_storage->constantInt(3),
231 name("wPtr"),
232 m_builder.GetInsertBlock());
233
234 std::vector<llvm::Value*> res(4);
235 res[0] = new LoadInst(xElemPtr, name("xRes"), false, m_builder.GetInsertBlock());
236 res[1] = new LoadInst(yElemPtr, name("yRes"), false, m_builder.GetInsertBlock());
237 res[2] = new LoadInst(zElemPtr, name("zRes"), false, m_builder.GetInsertBlock());
238 res[3] = new LoadInst(wElemPtr, name("wRes"), false, m_builder.GetInsertBlock());
239
240 return res;
241 }
242
243 std::vector<llvm::Value*> InstructionsSoa::dp4(const std::vector<llvm::Value*> in1,
244 const std::vector<llvm::Value*> in2)
245 {
246 llvm::Function *func = function(TGSI_OPCODE_DP4);
247 return callBuiltin(func, in1, in2);
248 }
249
250 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1)
251 {
252 std::vector<Value*> params;
253
254 llvm::Value *allocaPtr = allocaTemp();
255 params.push_back(allocaPtr);
256 params.push_back(in1[0]);
257 params.push_back(in1[1]);
258 params.push_back(in1[2]);
259 params.push_back(in1[3]);
260 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
261 call->setCallingConv(CallingConv::C);
262 call->setTailCall(false);
263
264 return allocaToResult(allocaPtr);
265 }
266
267 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
268 const std::vector<llvm::Value*> in2)
269 {
270 std::vector<Value*> params;
271
272 llvm::Value *allocaPtr = allocaTemp();
273 params.push_back(allocaPtr);
274 params.push_back(in1[0]);
275 params.push_back(in1[1]);
276 params.push_back(in1[2]);
277 params.push_back(in1[3]);
278 params.push_back(in2[0]);
279 params.push_back(in2[1]);
280 params.push_back(in2[2]);
281 params.push_back(in2[3]);
282 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
283 call->setCallingConv(CallingConv::C);
284 call->setTailCall(false);
285
286 return allocaToResult(allocaPtr);
287 }
288
289 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
290 const std::vector<llvm::Value*> in2,
291 const std::vector<llvm::Value*> in3)
292 {
293 std::vector<Value*> params;
294
295 llvm::Value *allocaPtr = allocaTemp();
296 params.push_back(allocaPtr);
297 params.push_back(in1[0]);
298 params.push_back(in1[1]);
299 params.push_back(in1[2]);
300 params.push_back(in1[3]);
301 params.push_back(in2[0]);
302 params.push_back(in2[1]);
303 params.push_back(in2[2]);
304 params.push_back(in2[3]);
305 params.push_back(in3[0]);
306 params.push_back(in3[1]);
307 params.push_back(in3[2]);
308 params.push_back(in3[3]);
309 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
310 call->setCallingConv(CallingConv::C);
311 call->setTailCall(false);
312
313 return allocaToResult(allocaPtr);
314 }
315
316 std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> in1,
317 const std::vector<llvm::Value*> in2)
318 {
319 llvm::Function *func = function(TGSI_OPCODE_POWER);
320 return callBuiltin(func, in1, in2);
321 }
322
323 void checkFunction(Function *func)
324 {
325 for (Function::const_iterator BI = func->begin(), BE = func->end();
326 BI != BE; ++BI) {
327 const BasicBlock &BB = *BI;
328 for (BasicBlock::const_iterator II = BB.begin(), IE = BB.end();
329 II != IE; ++II) {
330 const Instruction &I = *II;
331 std::cout<< "Instr = "<<I;
332 for (unsigned op = 0, E = I.getNumOperands(); op != E; ++op) {
333 const Value *Op = I.getOperand(op);
334 std::cout<< "\top = "<<Op<<"("<<op<<")"<<std::endl;
335 //I->setOperand(op, V);
336 }
337 }
338 }
339 }
340
341 void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op)
342 {
343 assert(originalFunc);
344 std::cout << "injecting function originalFunc " <<originalFunc->getName() <<std::endl;
345 if (op != TGSI_OPCODE_LAST) {
346 /* in this case it's possible the function has been already
347 * injected as part of the dependency chain, which gets
348 * injected below */
349 llvm::Function *func = currentModule()->getFunction(originalFunc->getName());
350 if (func) {
351 m_functions[op] = func;
352 return;
353 }
354 }
355 llvm::Function *func = 0;
356 if (originalFunc->isDeclaration()) {
357 std::cout << "function decleration" <<std::endl;
358 func = new Function(originalFunc->getFunctionType(), GlobalValue::ExternalLinkage,
359 originalFunc->getName(), currentModule());
360 func->setCallingConv(CallingConv::C);
361 const ParamAttrsList *pal = 0;
362 func->setParamAttrs(pal);
363 currentModule()->dump();
364 } else {
365 DenseMap<const Value*, Value *> val;
366 val[m_builtins->getFunction("powf")] = currentModule()->getFunction("powf");
367 std::cout <<" replacing "<<m_builtins->getFunction("powf")
368 <<", with " <<currentModule()->getFunction("powf")<<std::endl;
369 func = CloneFunction(originalFunc, val);
370 std::cout<<"1111-------------------------------"<<std::endl;
371 checkFunction(originalFunc);
372 std::cout<<"2222-------------------------------"<<std::endl;
373 checkFunction(func);
374 std::cout <<"XXXX = " <<val[m_builtins->getFunction("powf")]<<std::endl;
375 currentModule()->getFunctionList().push_back(func);
376 std::cout << "Func parent is "<<func->getParent()
377 <<", cur is "<<currentModule() <<std::endl;
378 }
379 if (op != TGSI_OPCODE_LAST) {
380 m_functions[op] = func;
381 }
382 }