do the lit (some artifacts present)
[mesa.git] / src / gallium / auxiliary / gallivm / instructionssoa.cpp
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27 #include "instructionssoa.h"
28
29 #include "storagesoa.h"
30
31 #include "pipe/p_shader_tokens.h"
32 #include "pipe/p_util.h"
33
34 #include <llvm/CallingConv.h>
35 #include <llvm/Constants.h>
36 #include <llvm/Module.h>
37 #include <llvm/Function.h>
38 #include <llvm/Instructions.h>
39 #include <llvm/Transforms/Utils/Cloning.h>
40 #include <llvm/ParameterAttributes.h>
41 #include <llvm/Support/MemoryBuffer.h>
42 #include <llvm/Bitcode/ReaderWriter.h>
43
44
45 #include <iostream>
46
47
48 /* disable some warnings. this file is autogenerated */
49 #if defined(__GNUC__)
50 #pragma GCC diagnostic ignored "-Wunused-variable"
51 #endif
52 using namespace llvm;
53 #include "gallivmsoabuiltins.cpp"
54 #if defined(__GNUC__)
55 #pragma GCC diagnostic warning "-Wunused-variable"
56 #endif
57
58 InstructionsSoa::InstructionsSoa(llvm::Module *mod, llvm::Function *func,
59 llvm::BasicBlock *block, StorageSoa *storage)
60 : m_builder(block),
61 m_storage(storage),
62 m_idx(0)
63 {
64 createFunctionMap();
65 createBuiltins();
66 }
67
68 const char * InstructionsSoa::name(const char *prefix) const
69 {
70 ++m_idx;
71 snprintf(m_name, 32, "%s%d", prefix, m_idx);
72 return m_name;
73 }
74
75 llvm::Value * InstructionsSoa::vectorFromVals(llvm::Value *x, llvm::Value *y,
76 llvm::Value *z, llvm::Value *w)
77 {
78 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
79 Constant *constVector = Constant::getNullValue(vectorType);
80 Value *res = m_builder.CreateInsertElement(constVector, x,
81 m_storage->constantInt(0),
82 name("vecx"));
83 res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
84 name("vecxy"));
85 res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
86 name("vecxyz"));
87 if (w)
88 res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
89 name("vecxyzw"));
90 return res;
91 }
92
93 std::vector<llvm::Value*> InstructionsSoa::arl(const std::vector<llvm::Value*> in)
94 {
95 std::vector<llvm::Value*> res(4);
96
97 //Extract x's
98 llvm::Value *x1 = m_builder.CreateExtractElement(in[0],
99 m_storage->constantInt(0),
100 name("extractX"));
101 //cast it to an unsigned int
102 x1 = m_builder.CreateFPToUI(x1, IntegerType::get(32), name("x1IntCast"));
103
104 res[0] = x1;//vectorFromVals(x1, x2, x3, x4);
105 //only x is valid. the others shouldn't be necessary
106 /*
107 res[1] = Constant::getNullValue(m_floatVecType);
108 res[2] = Constant::getNullValue(m_floatVecType);
109 res[3] = Constant::getNullValue(m_floatVecType);
110 */
111
112 return res;
113 }
114
115
116 std::vector<llvm::Value*> InstructionsSoa::add(const std::vector<llvm::Value*> in1,
117 const std::vector<llvm::Value*> in2)
118 {
119 std::vector<llvm::Value*> res(4);
120
121 res[0] = m_builder.CreateAdd(in1[0], in2[0], name("addx"));
122 res[1] = m_builder.CreateAdd(in1[1], in2[1], name("addy"));
123 res[2] = m_builder.CreateAdd(in1[2], in2[2], name("addz"));
124 res[3] = m_builder.CreateAdd(in1[3], in2[3], name("addw"));
125
126 return res;
127 }
128
129 std::vector<llvm::Value*> InstructionsSoa::mul(const std::vector<llvm::Value*> in1,
130 const std::vector<llvm::Value*> in2)
131 {
132 std::vector<llvm::Value*> res(4);
133
134 res[0] = m_builder.CreateMul(in1[0], in2[0], name("mulx"));
135 res[1] = m_builder.CreateMul(in1[1], in2[1], name("muly"));
136 res[2] = m_builder.CreateMul(in1[2], in2[2], name("mulz"));
137 res[3] = m_builder.CreateMul(in1[3], in2[3], name("mulw"));
138
139 return res;
140 }
141
142 void InstructionsSoa::end()
143 {
144 m_builder.CreateRetVoid();
145 }
146
147 std::vector<llvm::Value*> InstructionsSoa::madd(const std::vector<llvm::Value*> in1,
148 const std::vector<llvm::Value*> in2,
149 const std::vector<llvm::Value*> in3)
150 {
151 std::vector<llvm::Value*> res = mul(in1, in2);
152 return add(res, in3);
153 }
154
155 std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector)
156 {
157 std::vector<llvm::Value*> res(4);
158 res[0] = m_builder.CreateExtractElement(vector,
159 m_storage->constantInt(0),
160 name("extract1X"));
161 res[1] = m_builder.CreateExtractElement(vector,
162 m_storage->constantInt(1),
163 name("extract2X"));
164 res[2] = m_builder.CreateExtractElement(vector,
165 m_storage->constantInt(2),
166 name("extract3X"));
167 res[3] = m_builder.CreateExtractElement(vector,
168 m_storage->constantInt(3),
169 name("extract4X"));
170
171 return res;
172 }
173
174 void InstructionsSoa::createFunctionMap()
175 {
176 m_functionsMap[TGSI_OPCODE_ABS] = "abs";
177 m_functionsMap[TGSI_OPCODE_DP3] = "dp3";
178 m_functionsMap[TGSI_OPCODE_DP4] = "dp4";
179 m_functionsMap[TGSI_OPCODE_MIN] = "min";
180 m_functionsMap[TGSI_OPCODE_MAX] = "max";
181 m_functionsMap[TGSI_OPCODE_POWER] = "pow";
182 m_functionsMap[TGSI_OPCODE_LIT] = "lit";
183 }
184
185 void InstructionsSoa::createDependencies()
186 {
187 {
188 std::vector<std::string> powDeps(2);
189 powDeps[0] = "powf";
190 powDeps[1] = "powvec";
191 m_builtinDependencies["pow"] = powDeps;
192 }
193 {
194 std::vector<std::string> absDeps(1);
195 absDeps[0] = "fabsf";
196 m_builtinDependencies["abs"] = absDeps;
197 }
198 {
199 std::vector<std::string> maxDeps(1);
200 maxDeps[0] = "maxvec";
201 m_builtinDependencies["max"] = maxDeps;
202 }
203 {
204 std::vector<std::string> minDeps(1);
205 minDeps[0] = "minvec";
206 m_builtinDependencies["min"] = minDeps;
207 }
208 {
209 std::vector<std::string> litDeps(4);
210 litDeps[0] = "minvec";
211 litDeps[1] = "maxvec";
212 litDeps[2] = "powf";
213 litDeps[3] = "powvec";
214 m_builtinDependencies["lit"] = litDeps;
215 }
216 }
217
218 llvm::Function * InstructionsSoa::function(int op)
219 {
220 if (m_functions.find(op) != m_functions.end())
221 return m_functions[op];
222
223 std::string name = m_functionsMap[op];
224
225 std::cout <<"For op = "<<op<<", func is '"<<name<<"'"<<std::endl;
226
227 std::vector<std::string> deps = m_builtinDependencies[name];
228 for (unsigned int i = 0; i < deps.size(); ++i) {
229 llvm::Function *func = m_builtins->getFunction(deps[i]);
230 std::cout <<"\tinjecting dep = '"<<func->getName()<<"'"<<std::endl;
231 injectFunction(func);
232 }
233
234 llvm::Function *originalFunc = m_builtins->getFunction(name);
235 injectFunction(originalFunc, op);
236 return m_functions[op];
237 }
238
239 llvm::Module * InstructionsSoa::currentModule() const
240 {
241 BasicBlock *block = m_builder.GetInsertBlock();
242 if (!block || !block->getParent())
243 return 0;
244
245 return block->getParent()->getParent();
246 }
247
248 void InstructionsSoa::createBuiltins()
249 {
250 MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
251 (const char*)&soabuiltins_data[0],
252 (const char*)&soabuiltins_data[Elements(soabuiltins_data)]);
253 m_builtins = ParseBitcodeFile(buffer);
254 std::cout<<"Builtins created at "<<m_builtins<<std::endl;
255 assert(m_builtins);
256 createDependencies();
257 }
258
259
260 std::vector<llvm::Value*> InstructionsSoa::abs(const std::vector<llvm::Value*> in1)
261 {
262 llvm::Function *func = function(TGSI_OPCODE_ABS);
263 return callBuiltin(func, in1);
264 }
265
266 std::vector<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1,
267 const std::vector<llvm::Value*> in2)
268 {
269 llvm::Function *func = function(TGSI_OPCODE_DP3);
270 return callBuiltin(func, in1, in2);
271 }
272
273 llvm::Value * InstructionsSoa::allocaTemp()
274 {
275 VectorType *vector = VectorType::get(Type::FloatTy, 4);
276 ArrayType *vecArray = ArrayType::get(vector, 4);
277 AllocaInst *alloca = new AllocaInst(vecArray, name("tmpRes"),
278 m_builder.GetInsertBlock());
279
280 std::vector<Value*> indices;
281 indices.push_back(m_storage->constantInt(0));
282 indices.push_back(m_storage->constantInt(0));
283 GetElementPtrInst *getElem = GetElementPtrInst::Create(alloca,
284 indices.begin(),
285 indices.end(),
286 name("allocaPtr"),
287 m_builder.GetInsertBlock());
288 return getElem;
289 }
290
291 std::vector<llvm::Value*> InstructionsSoa::allocaToResult(llvm::Value *allocaPtr)
292 {
293 GetElementPtrInst *xElemPtr = GetElementPtrInst::Create(allocaPtr,
294 m_storage->constantInt(0),
295 name("xPtr"),
296 m_builder.GetInsertBlock());
297 GetElementPtrInst *yElemPtr = GetElementPtrInst::Create(allocaPtr,
298 m_storage->constantInt(1),
299 name("yPtr"),
300 m_builder.GetInsertBlock());
301 GetElementPtrInst *zElemPtr = GetElementPtrInst::Create(allocaPtr,
302 m_storage->constantInt(2),
303 name("zPtr"),
304 m_builder.GetInsertBlock());
305 GetElementPtrInst *wElemPtr = GetElementPtrInst::Create(allocaPtr,
306 m_storage->constantInt(3),
307 name("wPtr"),
308 m_builder.GetInsertBlock());
309
310 std::vector<llvm::Value*> res(4);
311 res[0] = new LoadInst(xElemPtr, name("xRes"), false, m_builder.GetInsertBlock());
312 res[1] = new LoadInst(yElemPtr, name("yRes"), false, m_builder.GetInsertBlock());
313 res[2] = new LoadInst(zElemPtr, name("zRes"), false, m_builder.GetInsertBlock());
314 res[3] = new LoadInst(wElemPtr, name("wRes"), false, m_builder.GetInsertBlock());
315
316 return res;
317 }
318
319 std::vector<llvm::Value*> InstructionsSoa::dp4(const std::vector<llvm::Value*> in1,
320 const std::vector<llvm::Value*> in2)
321 {
322 llvm::Function *func = function(TGSI_OPCODE_DP4);
323 return callBuiltin(func, in1, in2);
324 }
325
326 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1)
327 {
328 std::vector<Value*> params;
329
330 llvm::Value *allocaPtr = allocaTemp();
331 params.push_back(allocaPtr);
332 params.push_back(in1[0]);
333 params.push_back(in1[1]);
334 params.push_back(in1[2]);
335 params.push_back(in1[3]);
336 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
337 call->setCallingConv(CallingConv::C);
338 call->setTailCall(false);
339
340 return allocaToResult(allocaPtr);
341 }
342
343 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
344 const std::vector<llvm::Value*> in2)
345 {
346 std::vector<Value*> params;
347
348 llvm::Value *allocaPtr = allocaTemp();
349 params.push_back(allocaPtr);
350 params.push_back(in1[0]);
351 params.push_back(in1[1]);
352 params.push_back(in1[2]);
353 params.push_back(in1[3]);
354 params.push_back(in2[0]);
355 params.push_back(in2[1]);
356 params.push_back(in2[2]);
357 params.push_back(in2[3]);
358 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
359 call->setCallingConv(CallingConv::C);
360 call->setTailCall(false);
361
362 return allocaToResult(allocaPtr);
363 }
364
365 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
366 const std::vector<llvm::Value*> in2,
367 const std::vector<llvm::Value*> in3)
368 {
369 std::vector<Value*> params;
370
371 llvm::Value *allocaPtr = allocaTemp();
372 params.push_back(allocaPtr);
373 params.push_back(in1[0]);
374 params.push_back(in1[1]);
375 params.push_back(in1[2]);
376 params.push_back(in1[3]);
377 params.push_back(in2[0]);
378 params.push_back(in2[1]);
379 params.push_back(in2[2]);
380 params.push_back(in2[3]);
381 params.push_back(in3[0]);
382 params.push_back(in3[1]);
383 params.push_back(in3[2]);
384 params.push_back(in3[3]);
385 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
386 call->setCallingConv(CallingConv::C);
387 call->setTailCall(false);
388
389 return allocaToResult(allocaPtr);
390 }
391
392 std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> in1,
393 const std::vector<llvm::Value*> in2)
394 {
395 llvm::Function *func = function(TGSI_OPCODE_POWER);
396 return callBuiltin(func, in1, in2);
397 }
398
399 std::vector<llvm::Value*> InstructionsSoa::min(const std::vector<llvm::Value*> in1,
400 const std::vector<llvm::Value*> in2)
401 {
402 llvm::Function *func = function(TGSI_OPCODE_MIN);
403 return callBuiltin(func, in1, in2);
404 }
405
406
407 std::vector<llvm::Value*> InstructionsSoa::max(const std::vector<llvm::Value*> in1,
408 const std::vector<llvm::Value*> in2)
409 {
410 llvm::Function *func = function(TGSI_OPCODE_MAX);
411 return callBuiltin(func, in1, in2);
412 }
413
414 void checkFunction(Function *func)
415 {
416 for (Function::const_iterator BI = func->begin(), BE = func->end();
417 BI != BE; ++BI) {
418 const BasicBlock &BB = *BI;
419 for (BasicBlock::const_iterator II = BB.begin(), IE = BB.end();
420 II != IE; ++II) {
421 const Instruction &I = *II;
422 std::cout<< "Instr = "<<I;
423 for (unsigned op = 0, E = I.getNumOperands(); op != E; ++op) {
424 const Value *Op = I.getOperand(op);
425 std::cout<< "\top = "<<Op<<"("<<op<<")"<<std::endl;
426 //I->setOperand(op, V);
427 }
428 }
429 }
430 }
431
432 void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op)
433 {
434 assert(originalFunc);
435 std::cout << "injecting function originalFunc " <<originalFunc->getName() <<std::endl;
436 if (op != TGSI_OPCODE_LAST) {
437 /* in this case it's possible the function has been already
438 * injected as part of the dependency chain, which gets
439 * injected below */
440 llvm::Function *func = currentModule()->getFunction(originalFunc->getName());
441 if (func) {
442 m_functions[op] = func;
443 return;
444 }
445 }
446 llvm::Function *func = 0;
447 if (originalFunc->isDeclaration()) {
448 func = Function::Create(originalFunc->getFunctionType(), GlobalValue::ExternalLinkage,
449 originalFunc->getName(), currentModule());
450 func->setCallingConv(CallingConv::C);
451 const PAListPtr pal;
452 func->setParamAttrs(pal);
453 currentModule()->dump();
454 } else {
455 DenseMap<const Value*, Value *> val;
456 val[m_builtins->getFunction("powf")] = currentModule()->getFunction("powf");
457 func = CloneFunction(originalFunc, val);
458 #if 0
459 std::cout <<" replacing "<<m_builtins->getFunction("powf")
460 <<", with " <<currentModule()->getFunction("powf")<<std::endl;
461 std::cout<<"1111-------------------------------"<<std::endl;
462 checkFunction(originalFunc);
463 std::cout<<"2222-------------------------------"<<std::endl;
464 checkFunction(func);
465 std::cout <<"XXXX = " <<val[m_builtins->getFunction("powf")]<<std::endl;
466 #endif
467 currentModule()->getFunctionList().push_back(func);
468 }
469 if (op != TGSI_OPCODE_LAST) {
470 m_functions[op] = func;
471 }
472 }
473
474 std::vector<llvm::Value*> InstructionsSoa::sub(const std::vector<llvm::Value*> in1,
475 const std::vector<llvm::Value*> in2)
476 {
477 std::vector<llvm::Value*> res(4);
478
479 res[0] = m_builder.CreateSub(in1[0], in2[0], name("subx"));
480 res[1] = m_builder.CreateSub(in1[1], in2[1], name("suby"));
481 res[2] = m_builder.CreateSub(in1[2], in2[2], name("subz"));
482 res[3] = m_builder.CreateSub(in1[3], in2[3], name("subw"));
483
484 return res;
485 }
486
487 std::vector<llvm::Value*> InstructionsSoa::lit(const std::vector<llvm::Value*> in)
488 {
489 llvm::Function *func = function(TGSI_OPCODE_LIT);
490 return callBuiltin(func, in);
491 }
492