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