1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
27 #include "instructionssoa.h"
29 #include "storagesoa.h"
31 #include "pipe/p_shader_tokens.h"
32 #include "pipe/p_util.h"
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>
49 /* disable some warnings. this file is autogenerated */
51 #pragma GCC diagnostic ignored "-Wunused-variable"
54 #include "gallivmsoabuiltins.cpp"
56 #pragma GCC diagnostic warning "-Wunused-variable"
59 InstructionsSoa::InstructionsSoa(llvm::Module
*mod
, llvm::Function
*func
,
60 llvm::BasicBlock
*block
, StorageSoa
*storage
)
69 const char * InstructionsSoa::name(const char *prefix
) const
72 snprintf(m_name
, 32, "%s%d", prefix
, m_idx
);
76 llvm::Value
* InstructionsSoa::vectorFromVals(llvm::Value
*x
, llvm::Value
*y
,
77 llvm::Value
*z
, llvm::Value
*w
)
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),
84 res
= m_builder
.CreateInsertElement(res
, y
, m_storage
->constantInt(1),
86 res
= m_builder
.CreateInsertElement(res
, z
, m_storage
->constantInt(2),
89 res
= m_builder
.CreateInsertElement(res
, w
, m_storage
->constantInt(3),
94 std::vector
<llvm::Value
*> InstructionsSoa::arl(const std::vector
<llvm::Value
*> in
)
96 std::vector
<llvm::Value
*> res(4);
99 llvm::Value
*x1
= m_builder
.CreateExtractElement(in
[0],
100 m_storage
->constantInt(0),
102 //cast it to an unsigned int
103 x1
= m_builder
.CreateFPToUI(x1
, IntegerType::get(32), name("x1IntCast"));
105 res
[0] = x1
;//vectorFromVals(x1, x2, x3, x4);
106 //only x is valid. the others shouldn't be necessary
108 res[1] = Constant::getNullValue(m_floatVecType);
109 res[2] = Constant::getNullValue(m_floatVecType);
110 res[3] = Constant::getNullValue(m_floatVecType);
117 std::vector
<llvm::Value
*> InstructionsSoa::add(const std::vector
<llvm::Value
*> in1
,
118 const std::vector
<llvm::Value
*> in2
)
120 std::vector
<llvm::Value
*> res(4);
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"));
130 std::vector
<llvm::Value
*> InstructionsSoa::mul(const std::vector
<llvm::Value
*> in1
,
131 const std::vector
<llvm::Value
*> in2
)
133 std::vector
<llvm::Value
*> res(4);
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"));
143 void InstructionsSoa::end()
145 m_builder
.CreateRetVoid();
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
)
152 std::vector
<llvm::Value
*> res
= mul(in1
, in2
);
153 return add(res
, in3
);
156 std::vector
<llvm::Value
*> InstructionsSoa::extractVector(llvm::Value
*vector
)
158 std::vector
<llvm::Value
*> res(4);
159 res
[0] = m_builder
.CreateExtractElement(vector
,
160 m_storage
->constantInt(0),
162 res
[1] = m_builder
.CreateExtractElement(vector
,
163 m_storage
->constantInt(1),
165 res
[2] = m_builder
.CreateExtractElement(vector
,
166 m_storage
->constantInt(2),
168 res
[3] = m_builder
.CreateExtractElement(vector
,
169 m_storage
->constantInt(3),
175 void InstructionsSoa::createFunctionMap()
177 m_functionsMap
[TGSI_OPCODE_DP3
] = "dp3";
178 m_functionsMap
[TGSI_OPCODE_DP4
] = "dp4";
179 m_functionsMap
[TGSI_OPCODE_POWER
] = "pow";
182 void InstructionsSoa::createDependencies()
184 std::vector
<std::string
> powDeps(1);
186 m_builtinDependencies
["pow"] = powDeps
;
189 llvm::Function
* InstructionsSoa::function(int op
)
191 if (m_functions
.find(op
) != m_functions
.end())
192 return m_functions
[op
];
194 std::string name
= m_functionsMap
[op
];
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
]));
201 llvm::Function
*originalFunc
= m_builtins
->getFunction(name
);
202 injectFunction(originalFunc
, op
);
203 return m_functions
[op
];
206 llvm::Module
* InstructionsSoa::currentModule() const
208 BasicBlock
*block
= m_builder
.GetInsertBlock();
209 if (!block
|| !block
->getParent())
212 return block
->getParent()->getParent();
215 void InstructionsSoa::createBuiltins()
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();
224 std::vector
<llvm::Value
*> InstructionsSoa::dp3(const std::vector
<llvm::Value
*> in1
,
225 const std::vector
<llvm::Value
*> in2
)
227 llvm::Function
*func
= function(TGSI_OPCODE_DP3
);
228 return callBuiltin(func
, in1
, in2
);
231 llvm::Value
* InstructionsSoa::allocaTemp()
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());
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
,
245 m_builder
.GetInsertBlock());
249 std::vector
<llvm::Value
*> InstructionsSoa::allocaToResult(llvm::Value
*allocaPtr
)
251 GetElementPtrInst
*xElemPtr
= GetElementPtrInst::Create(allocaPtr
,
252 m_storage
->constantInt(0),
254 m_builder
.GetInsertBlock());
255 GetElementPtrInst
*yElemPtr
= GetElementPtrInst::Create(allocaPtr
,
256 m_storage
->constantInt(1),
258 m_builder
.GetInsertBlock());
259 GetElementPtrInst
*zElemPtr
= GetElementPtrInst::Create(allocaPtr
,
260 m_storage
->constantInt(2),
262 m_builder
.GetInsertBlock());
263 GetElementPtrInst
*wElemPtr
= GetElementPtrInst::Create(allocaPtr
,
264 m_storage
->constantInt(3),
266 m_builder
.GetInsertBlock());
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());
277 std::vector
<llvm::Value
*> InstructionsSoa::dp4(const std::vector
<llvm::Value
*> in1
,
278 const std::vector
<llvm::Value
*> in2
)
280 llvm::Function
*func
= function(TGSI_OPCODE_DP4
);
281 return callBuiltin(func
, in1
, in2
);
284 std::vector
<Value
*> InstructionsSoa::callBuiltin(llvm::Function
*func
, const std::vector
<llvm::Value
*> in1
)
286 std::vector
<Value
*> params
;
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);
298 return allocaToResult(allocaPtr
);
301 std::vector
<Value
*> InstructionsSoa::callBuiltin(llvm::Function
*func
, const std::vector
<llvm::Value
*> in1
,
302 const std::vector
<llvm::Value
*> in2
)
304 std::vector
<Value
*> params
;
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);
320 return allocaToResult(allocaPtr
);
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
)
327 std::vector
<Value
*> params
;
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);
347 return allocaToResult(allocaPtr
);
350 std::vector
<llvm::Value
*> InstructionsSoa::pow(const std::vector
<llvm::Value
*> in1
,
351 const std::vector
<llvm::Value
*> in2
)
353 llvm::Function
*func
= function(TGSI_OPCODE_POWER
);
354 return callBuiltin(func
, in1
, in2
);
357 void checkFunction(Function
*func
)
359 for (Function::const_iterator BI
= func
->begin(), BE
= func
->end();
361 const BasicBlock
&BB
= *BI
;
362 for (BasicBlock::const_iterator II
= BB
.begin(), IE
= BB
.end();
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);
375 void InstructionsSoa::injectFunction(llvm::Function
*originalFunc
, int op
)
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
383 llvm::Function
*func
= currentModule()->getFunction(originalFunc
->getName());
385 m_functions
[op
] = func
;
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
);
396 func
->setParamAttrs(pal
);
397 currentModule()->dump();
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
;
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
;
413 if (op
!= TGSI_OPCODE_LAST
) {
414 m_functions
[op
] = func
;