1 #include "instructionssoa.h"
3 #include "storagesoa.h"
5 #include "pipe/p_shader_tokens.h"
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>
18 /* disable some warnings. this file is autogenerated */
20 #pragma GCC diagnostic ignored "-Wunused-variable"
23 #include "gallivmsoabuiltins.cpp"
25 #pragma GCC diagnostic warning "-Wunused-variable"
28 InstructionsSoa::InstructionsSoa(llvm::Module
*mod
, llvm::Function
*func
,
29 llvm::BasicBlock
*block
, StorageSoa
*storage
)
38 const char * InstructionsSoa::name(const char *prefix
) const
41 snprintf(m_name
, 32, "%s%d", prefix
, m_idx
);
45 llvm::Value
* InstructionsSoa::vectorFromVals(llvm::Value
*x
, llvm::Value
*y
,
46 llvm::Value
*z
, llvm::Value
*w
)
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),
53 res
= m_builder
.CreateInsertElement(res
, y
, m_storage
->constantInt(1),
55 res
= m_builder
.CreateInsertElement(res
, z
, m_storage
->constantInt(2),
58 res
= m_builder
.CreateInsertElement(res
, w
, m_storage
->constantInt(3),
63 std::vector
<llvm::Value
*> InstructionsSoa::arl(const std::vector
<llvm::Value
*> in
)
65 std::vector
<llvm::Value
*> res(4);
68 llvm::Value
*x1
= m_builder
.CreateExtractElement(in
[0],
69 m_storage
->constantInt(0),
71 //cast it to an unsigned int
72 x1
= m_builder
.CreateFPToUI(x1
, IntegerType::get(32), name("x1IntCast"));
74 res
[0] = x1
;//vectorFromVals(x1, x2, x3, x4);
75 //only x is valid. the others shouldn't be necessary
77 res[1] = Constant::getNullValue(m_floatVecType);
78 res[2] = Constant::getNullValue(m_floatVecType);
79 res[3] = Constant::getNullValue(m_floatVecType);
86 std::vector
<llvm::Value
*> InstructionsSoa::add(const std::vector
<llvm::Value
*> in1
,
87 const std::vector
<llvm::Value
*> in2
)
89 std::vector
<llvm::Value
*> res(4);
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"));
99 std::vector
<llvm::Value
*> InstructionsSoa::mul(const std::vector
<llvm::Value
*> in1
,
100 const std::vector
<llvm::Value
*> in2
)
102 std::vector
<llvm::Value
*> res(4);
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"));
112 void InstructionsSoa::end()
114 m_builder
.CreateRetVoid();
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
)
121 std::vector
<llvm::Value
*> res
= mul(in1
, in2
);
122 return add(res
, in3
);
125 std::vector
<llvm::Value
*> InstructionsSoa::extractVector(llvm::Value
*vector
)
127 std::vector
<llvm::Value
*> res(4);
128 res
[0] = m_builder
.CreateExtractElement(vector
,
129 m_storage
->constantInt(0),
131 res
[1] = m_builder
.CreateExtractElement(vector
,
132 m_storage
->constantInt(1),
134 res
[2] = m_builder
.CreateExtractElement(vector
,
135 m_storage
->constantInt(2),
137 res
[3] = m_builder
.CreateExtractElement(vector
,
138 m_storage
->constantInt(3),
144 void InstructionsSoa::createFunctionMap()
146 m_functionsMap
[TGSI_OPCODE_DP3
] = "dp3";
147 m_functionsMap
[TGSI_OPCODE_DP4
] = "dp4";
148 m_functionsMap
[TGSI_OPCODE_POWER
] = "pow";
151 void InstructionsSoa::createDependencies()
153 std::vector
<std::string
> powDeps(1);
155 m_builtinDependencies
["pow"] = powDeps
;
158 llvm::Function
* InstructionsSoa::function(int op
)
160 if (m_functions
.find(op
) != m_functions
.end())
161 return m_functions
[op
];
163 std::string name
= m_functionsMap
[op
];
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
]));
170 llvm::Function
*originalFunc
= m_builtins
->getFunction(name
);
171 injectFunction(originalFunc
, op
);
172 return m_functions
[op
];
175 llvm::Module
* InstructionsSoa::currentModule() const
177 BasicBlock
*block
= m_builder
.GetInsertBlock();
178 if (!block
|| !block
->getParent())
181 return block
->getParent()->getParent();
184 void InstructionsSoa::createBuiltins()
186 m_builtins
= createSoaBuiltins();
187 createDependencies();
190 std::vector
<llvm::Value
*> InstructionsSoa::dp3(const std::vector
<llvm::Value
*> in1
,
191 const std::vector
<llvm::Value
*> in2
)
193 llvm::Function
*func
= function(TGSI_OPCODE_DP3
);
194 return callBuiltin(func
, in1
, in2
);
197 llvm::Value
* InstructionsSoa::allocaTemp()
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());
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
,
211 m_builder
.GetInsertBlock());
215 std::vector
<llvm::Value
*> InstructionsSoa::allocaToResult(llvm::Value
*allocaPtr
)
217 GetElementPtrInst
*xElemPtr
= new GetElementPtrInst(allocaPtr
,
218 m_storage
->constantInt(0),
220 m_builder
.GetInsertBlock());
221 GetElementPtrInst
*yElemPtr
= new GetElementPtrInst(allocaPtr
,
222 m_storage
->constantInt(1),
224 m_builder
.GetInsertBlock());
225 GetElementPtrInst
*zElemPtr
= new GetElementPtrInst(allocaPtr
,
226 m_storage
->constantInt(2),
228 m_builder
.GetInsertBlock());
229 GetElementPtrInst
*wElemPtr
= new GetElementPtrInst(allocaPtr
,
230 m_storage
->constantInt(3),
232 m_builder
.GetInsertBlock());
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());
243 std::vector
<llvm::Value
*> InstructionsSoa::dp4(const std::vector
<llvm::Value
*> in1
,
244 const std::vector
<llvm::Value
*> in2
)
246 llvm::Function
*func
= function(TGSI_OPCODE_DP4
);
247 return callBuiltin(func
, in1
, in2
);
250 std::vector
<Value
*> InstructionsSoa::callBuiltin(llvm::Function
*func
, const std::vector
<llvm::Value
*> in1
)
252 std::vector
<Value
*> params
;
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);
264 return allocaToResult(allocaPtr
);
267 std::vector
<Value
*> InstructionsSoa::callBuiltin(llvm::Function
*func
, const std::vector
<llvm::Value
*> in1
,
268 const std::vector
<llvm::Value
*> in2
)
270 std::vector
<Value
*> params
;
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);
286 return allocaToResult(allocaPtr
);
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
)
293 std::vector
<Value
*> params
;
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);
313 return allocaToResult(allocaPtr
);
316 std::vector
<llvm::Value
*> InstructionsSoa::pow(const std::vector
<llvm::Value
*> in1
,
317 const std::vector
<llvm::Value
*> in2
)
319 llvm::Function
*func
= function(TGSI_OPCODE_POWER
);
320 return callBuiltin(func
, in1
, in2
);
323 void checkFunction(Function
*func
)
325 for (Function::const_iterator BI
= func
->begin(), BE
= func
->end();
327 const BasicBlock
&BB
= *BI
;
328 for (BasicBlock::const_iterator II
= BB
.begin(), IE
= BB
.end();
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);
341 void InstructionsSoa::injectFunction(llvm::Function
*originalFunc
, int op
)
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
349 llvm::Function
*func
= currentModule()->getFunction(originalFunc
->getName());
351 m_functions
[op
] = func
;
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();
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
;
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
;
379 if (op
!= TGSI_OPCODE_LAST
) {
380 m_functions
[op
] = func
;