00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "instructionssoa.h"
00028
00029 #include "storagesoa.h"
00030
00031 #include "pipe/p_shader_tokens.h"
00032 #include "util/u_memory.h"
00033
00034 #include <llvm/CallingConv.h>
00035 #include <llvm/Constants.h>
00036 #include <llvm/Module.h>
00037 #include <llvm/Function.h>
00038 #include <llvm/Instructions.h>
00039 #include <llvm/Transforms/Utils/Cloning.h>
00040 #include <llvm/ParameterAttributes.h>
00041 #include <llvm/Support/MemoryBuffer.h>
00042 #include <llvm/Bitcode/ReaderWriter.h>
00043
00044
00045 #include <iostream>
00046
00047
00048
00049 #if defined(__GNUC__)
00050 #pragma GCC diagnostic ignored "-Wunused-variable"
00051 #endif
00052 using namespace llvm;
00053 #include "gallivmsoabuiltins.cpp"
00054 #if defined(__GNUC__)
00055 #pragma GCC diagnostic warning "-Wunused-variable"
00056 #endif
00057
00058 InstructionsSoa::InstructionsSoa(llvm::Module *mod, llvm::Function *func,
00059 llvm::BasicBlock *block, StorageSoa *storage)
00060 : m_builder(block),
00061 m_storage(storage),
00062 m_idx(0)
00063 {
00064 createFunctionMap();
00065 createBuiltins();
00066 }
00067
00068 const char * InstructionsSoa::name(const char *prefix) const
00069 {
00070 ++m_idx;
00071 snprintf(m_name, 32, "%s%d", prefix, m_idx);
00072 return m_name;
00073 }
00074
00075 llvm::Value * InstructionsSoa::vectorFromVals(llvm::Value *x, llvm::Value *y,
00076 llvm::Value *z, llvm::Value *w)
00077 {
00078 VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
00079 Constant *constVector = Constant::getNullValue(vectorType);
00080 Value *res = m_builder.CreateInsertElement(constVector, x,
00081 m_storage->constantInt(0),
00082 name("vecx"));
00083 res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
00084 name("vecxy"));
00085 res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
00086 name("vecxyz"));
00087 if (w)
00088 res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
00089 name("vecxyzw"));
00090 return res;
00091 }
00092
00093 std::vector<llvm::Value*> InstructionsSoa::arl(const std::vector<llvm::Value*> in)
00094 {
00095 std::vector<llvm::Value*> res(4);
00096
00097
00098 llvm::Value *x1 = m_builder.CreateExtractElement(in[0],
00099 m_storage->constantInt(0),
00100 name("extractX"));
00101
00102 x1 = m_builder.CreateFPToUI(x1, IntegerType::get(32), name("x1IntCast"));
00103
00104 res[0] = x1;
00105
00106
00107
00108
00109
00110
00111
00112 return res;
00113 }
00114
00115
00116 std::vector<llvm::Value*> InstructionsSoa::add(const std::vector<llvm::Value*> in1,
00117 const std::vector<llvm::Value*> in2)
00118 {
00119 std::vector<llvm::Value*> res(4);
00120
00121 res[0] = m_builder.CreateAdd(in1[0], in2[0], name("addx"));
00122 res[1] = m_builder.CreateAdd(in1[1], in2[1], name("addy"));
00123 res[2] = m_builder.CreateAdd(in1[2], in2[2], name("addz"));
00124 res[3] = m_builder.CreateAdd(in1[3], in2[3], name("addw"));
00125
00126 return res;
00127 }
00128
00129 std::vector<llvm::Value*> InstructionsSoa::mul(const std::vector<llvm::Value*> in1,
00130 const std::vector<llvm::Value*> in2)
00131 {
00132 std::vector<llvm::Value*> res(4);
00133
00134 res[0] = m_builder.CreateMul(in1[0], in2[0], name("mulx"));
00135 res[1] = m_builder.CreateMul(in1[1], in2[1], name("muly"));
00136 res[2] = m_builder.CreateMul(in1[2], in2[2], name("mulz"));
00137 res[3] = m_builder.CreateMul(in1[3], in2[3], name("mulw"));
00138
00139 return res;
00140 }
00141
00142 void InstructionsSoa::end()
00143 {
00144 m_builder.CreateRetVoid();
00145 }
00146
00147 std::vector<llvm::Value*> InstructionsSoa::madd(const std::vector<llvm::Value*> in1,
00148 const std::vector<llvm::Value*> in2,
00149 const std::vector<llvm::Value*> in3)
00150 {
00151 std::vector<llvm::Value*> res = mul(in1, in2);
00152 return add(res, in3);
00153 }
00154
00155 std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector)
00156 {
00157 std::vector<llvm::Value*> res(4);
00158 res[0] = m_builder.CreateExtractElement(vector,
00159 m_storage->constantInt(0),
00160 name("extract1X"));
00161 res[1] = m_builder.CreateExtractElement(vector,
00162 m_storage->constantInt(1),
00163 name("extract2X"));
00164 res[2] = m_builder.CreateExtractElement(vector,
00165 m_storage->constantInt(2),
00166 name("extract3X"));
00167 res[3] = m_builder.CreateExtractElement(vector,
00168 m_storage->constantInt(3),
00169 name("extract4X"));
00170
00171 return res;
00172 }
00173
00174 void InstructionsSoa::createFunctionMap()
00175 {
00176 m_functionsMap[TGSI_OPCODE_ABS] = "abs";
00177 m_functionsMap[TGSI_OPCODE_DP3] = "dp3";
00178 m_functionsMap[TGSI_OPCODE_DP4] = "dp4";
00179 m_functionsMap[TGSI_OPCODE_MIN] = "min";
00180 m_functionsMap[TGSI_OPCODE_MAX] = "max";
00181 m_functionsMap[TGSI_OPCODE_POWER] = "pow";
00182 m_functionsMap[TGSI_OPCODE_LIT] = "lit";
00183 m_functionsMap[TGSI_OPCODE_RSQ] = "rsq";
00184 m_functionsMap[TGSI_OPCODE_SLT] = "slt";
00185 }
00186
00187 void InstructionsSoa::createDependencies()
00188 {
00189 {
00190 std::vector<std::string> powDeps(2);
00191 powDeps[0] = "powf";
00192 powDeps[1] = "powvec";
00193 m_builtinDependencies["pow"] = powDeps;
00194 }
00195 {
00196 std::vector<std::string> absDeps(2);
00197 absDeps[0] = "fabsf";
00198 absDeps[1] = "absvec";
00199 m_builtinDependencies["abs"] = absDeps;
00200 }
00201 {
00202 std::vector<std::string> maxDeps(1);
00203 maxDeps[0] = "maxvec";
00204 m_builtinDependencies["max"] = maxDeps;
00205 }
00206 {
00207 std::vector<std::string> minDeps(1);
00208 minDeps[0] = "minvec";
00209 m_builtinDependencies["min"] = minDeps;
00210 }
00211 {
00212 std::vector<std::string> litDeps(4);
00213 litDeps[0] = "minvec";
00214 litDeps[1] = "maxvec";
00215 litDeps[2] = "powf";
00216 litDeps[3] = "powvec";
00217 m_builtinDependencies["lit"] = litDeps;
00218 }
00219 {
00220 std::vector<std::string> rsqDeps(4);
00221 rsqDeps[0] = "sqrtf";
00222 rsqDeps[1] = "sqrtvec";
00223 rsqDeps[2] = "fabsf";
00224 rsqDeps[3] = "absvec";
00225 m_builtinDependencies["rsq"] = rsqDeps;
00226 }
00227 }
00228
00229 llvm::Function * InstructionsSoa::function(int op)
00230 {
00231 if (m_functions.find(op) != m_functions.end())
00232 return m_functions[op];
00233
00234 std::string name = m_functionsMap[op];
00235
00236 std::cout <<"For op = "<<op<<", func is '"<<name<<"'"<<std::endl;
00237
00238 std::vector<std::string> deps = m_builtinDependencies[name];
00239 for (unsigned int i = 0; i < deps.size(); ++i) {
00240 llvm::Function *func = m_builtins->getFunction(deps[i]);
00241 std::cout <<"\tinjecting dep = '"<<func->getName()<<"'"<<std::endl;
00242 injectFunction(func);
00243 }
00244
00245 llvm::Function *originalFunc = m_builtins->getFunction(name);
00246 injectFunction(originalFunc, op);
00247 return m_functions[op];
00248 }
00249
00250 llvm::Module * InstructionsSoa::currentModule() const
00251 {
00252 BasicBlock *block = m_builder.GetInsertBlock();
00253 if (!block || !block->getParent())
00254 return 0;
00255
00256 return block->getParent()->getParent();
00257 }
00258
00259 void InstructionsSoa::createBuiltins()
00260 {
00261 MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
00262 (const char*)&soabuiltins_data[0],
00263 (const char*)&soabuiltins_data[Elements(soabuiltins_data)]);
00264 m_builtins = ParseBitcodeFile(buffer);
00265 std::cout<<"Builtins created at "<<m_builtins<<std::endl;
00266 assert(m_builtins);
00267 createDependencies();
00268 }
00269
00270
00271 std::vector<llvm::Value*> InstructionsSoa::abs(const std::vector<llvm::Value*> in1)
00272 {
00273 llvm::Function *func = function(TGSI_OPCODE_ABS);
00274 return callBuiltin(func, in1);
00275 }
00276
00277 std::vector<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1,
00278 const std::vector<llvm::Value*> in2)
00279 {
00280 llvm::Function *func = function(TGSI_OPCODE_DP3);
00281 return callBuiltin(func, in1, in2);
00282 }
00283
00284
00285 std::vector<llvm::Value*> InstructionsSoa::slt(const std::vector<llvm::Value*> in1,
00286 const std::vector<llvm::Value*> in2)
00287 {
00288 llvm::Function *func = function(TGSI_OPCODE_SLT);
00289 return callBuiltin(func, in1, in2);
00290 }
00291
00292 llvm::Value * InstructionsSoa::allocaTemp()
00293 {
00294 VectorType *vector = VectorType::get(Type::FloatTy, 4);
00295 ArrayType *vecArray = ArrayType::get(vector, 4);
00296 AllocaInst *alloca = new AllocaInst(vecArray, name("tmpRes"),
00297 m_builder.GetInsertBlock());
00298
00299 std::vector<Value*> indices;
00300 indices.push_back(m_storage->constantInt(0));
00301 indices.push_back(m_storage->constantInt(0));
00302 GetElementPtrInst *getElem = GetElementPtrInst::Create(alloca,
00303 indices.begin(),
00304 indices.end(),
00305 name("allocaPtr"),
00306 m_builder.GetInsertBlock());
00307 return getElem;
00308 }
00309
00310 std::vector<llvm::Value*> InstructionsSoa::allocaToResult(llvm::Value *allocaPtr)
00311 {
00312 GetElementPtrInst *xElemPtr = GetElementPtrInst::Create(allocaPtr,
00313 m_storage->constantInt(0),
00314 name("xPtr"),
00315 m_builder.GetInsertBlock());
00316 GetElementPtrInst *yElemPtr = GetElementPtrInst::Create(allocaPtr,
00317 m_storage->constantInt(1),
00318 name("yPtr"),
00319 m_builder.GetInsertBlock());
00320 GetElementPtrInst *zElemPtr = GetElementPtrInst::Create(allocaPtr,
00321 m_storage->constantInt(2),
00322 name("zPtr"),
00323 m_builder.GetInsertBlock());
00324 GetElementPtrInst *wElemPtr = GetElementPtrInst::Create(allocaPtr,
00325 m_storage->constantInt(3),
00326 name("wPtr"),
00327 m_builder.GetInsertBlock());
00328
00329 std::vector<llvm::Value*> res(4);
00330 res[0] = new LoadInst(xElemPtr, name("xRes"), false, m_builder.GetInsertBlock());
00331 res[1] = new LoadInst(yElemPtr, name("yRes"), false, m_builder.GetInsertBlock());
00332 res[2] = new LoadInst(zElemPtr, name("zRes"), false, m_builder.GetInsertBlock());
00333 res[3] = new LoadInst(wElemPtr, name("wRes"), false, m_builder.GetInsertBlock());
00334
00335 return res;
00336 }
00337
00338 std::vector<llvm::Value*> InstructionsSoa::dp4(const std::vector<llvm::Value*> in1,
00339 const std::vector<llvm::Value*> in2)
00340 {
00341 llvm::Function *func = function(TGSI_OPCODE_DP4);
00342 return callBuiltin(func, in1, in2);
00343 }
00344
00345 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1)
00346 {
00347 std::vector<Value*> params;
00348
00349 llvm::Value *allocaPtr = allocaTemp();
00350 params.push_back(allocaPtr);
00351 params.push_back(in1[0]);
00352 params.push_back(in1[1]);
00353 params.push_back(in1[2]);
00354 params.push_back(in1[3]);
00355 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
00356 call->setCallingConv(CallingConv::C);
00357 call->setTailCall(false);
00358
00359 return allocaToResult(allocaPtr);
00360 }
00361
00362 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
00363 const std::vector<llvm::Value*> in2)
00364 {
00365 std::vector<Value*> params;
00366
00367 llvm::Value *allocaPtr = allocaTemp();
00368 params.push_back(allocaPtr);
00369 params.push_back(in1[0]);
00370 params.push_back(in1[1]);
00371 params.push_back(in1[2]);
00372 params.push_back(in1[3]);
00373 params.push_back(in2[0]);
00374 params.push_back(in2[1]);
00375 params.push_back(in2[2]);
00376 params.push_back(in2[3]);
00377 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
00378 call->setCallingConv(CallingConv::C);
00379 call->setTailCall(false);
00380
00381 return allocaToResult(allocaPtr);
00382 }
00383
00384 std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector<llvm::Value*> in1,
00385 const std::vector<llvm::Value*> in2,
00386 const std::vector<llvm::Value*> in3)
00387 {
00388 std::vector<Value*> params;
00389
00390 llvm::Value *allocaPtr = allocaTemp();
00391 params.push_back(allocaPtr);
00392 params.push_back(in1[0]);
00393 params.push_back(in1[1]);
00394 params.push_back(in1[2]);
00395 params.push_back(in1[3]);
00396 params.push_back(in2[0]);
00397 params.push_back(in2[1]);
00398 params.push_back(in2[2]);
00399 params.push_back(in2[3]);
00400 params.push_back(in3[0]);
00401 params.push_back(in3[1]);
00402 params.push_back(in3[2]);
00403 params.push_back(in3[3]);
00404 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end());
00405 call->setCallingConv(CallingConv::C);
00406 call->setTailCall(false);
00407
00408 return allocaToResult(allocaPtr);
00409 }
00410
00411 std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> in1,
00412 const std::vector<llvm::Value*> in2)
00413 {
00414 llvm::Function *func = function(TGSI_OPCODE_POWER);
00415 return callBuiltin(func, in1, in2);
00416 }
00417
00418 std::vector<llvm::Value*> InstructionsSoa::min(const std::vector<llvm::Value*> in1,
00419 const std::vector<llvm::Value*> in2)
00420 {
00421 llvm::Function *func = function(TGSI_OPCODE_MIN);
00422 return callBuiltin(func, in1, in2);
00423 }
00424
00425
00426 std::vector<llvm::Value*> InstructionsSoa::max(const std::vector<llvm::Value*> in1,
00427 const std::vector<llvm::Value*> in2)
00428 {
00429 llvm::Function *func = function(TGSI_OPCODE_MAX);
00430 return callBuiltin(func, in1, in2);
00431 }
00432
00433 void checkFunction(Function *func)
00434 {
00435 for (Function::const_iterator BI = func->begin(), BE = func->end();
00436 BI != BE; ++BI) {
00437 const BasicBlock &BB = *BI;
00438 for (BasicBlock::const_iterator II = BB.begin(), IE = BB.end();
00439 II != IE; ++II) {
00440 const Instruction &I = *II;
00441 std::cout<< "Instr = "<<I;
00442 for (unsigned op = 0, E = I.getNumOperands(); op != E; ++op) {
00443 const Value *Op = I.getOperand(op);
00444 std::cout<< "\top = "<<Op<<"("<<op<<")"<<std::endl;
00445
00446 }
00447 }
00448 }
00449 }
00450
00451 void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op)
00452 {
00453 assert(originalFunc);
00454 std::cout << "injecting function originalFunc " <<originalFunc->getName() <<std::endl;
00455 if (op != TGSI_OPCODE_LAST) {
00456
00457
00458
00459 llvm::Function *func = currentModule()->getFunction(originalFunc->getName());
00460 if (func) {
00461 m_functions[op] = func;
00462 return;
00463 }
00464 }
00465 llvm::Function *func = 0;
00466 if (originalFunc->isDeclaration()) {
00467 func = Function::Create(originalFunc->getFunctionType(), GlobalValue::ExternalLinkage,
00468 originalFunc->getName(), currentModule());
00469 func->setCallingConv(CallingConv::C);
00470 const AttrListPtr pal;
00471 func->setAttributes(pal);
00472 currentModule()->dump();
00473 } else {
00474 DenseMap<const Value*, Value *> val;
00475 val[m_builtins->getFunction("fabsf")] = currentModule()->getFunction("fabsf");
00476 val[m_builtins->getFunction("powf")] = currentModule()->getFunction("powf");
00477 val[m_builtins->getFunction("sqrtf")] = currentModule()->getFunction("sqrtf");
00478 func = CloneFunction(originalFunc, val);
00479 #if 0
00480 std::cout <<" replacing "<<m_builtins->getFunction("powf")
00481 <<", with " <<currentModule()->getFunction("powf")<<std::endl;
00482 std::cout<<"1111-------------------------------"<<std::endl;
00483 checkFunction(originalFunc);
00484 std::cout<<"2222-------------------------------"<<std::endl;
00485 checkFunction(func);
00486 std::cout <<"XXXX = " <<val[m_builtins->getFunction("powf")]<<std::endl;
00487 #endif
00488 currentModule()->getFunctionList().push_back(func);
00489 }
00490 if (op != TGSI_OPCODE_LAST) {
00491 m_functions[op] = func;
00492 }
00493 }
00494
00495 std::vector<llvm::Value*> InstructionsSoa::sub(const std::vector<llvm::Value*> in1,
00496 const std::vector<llvm::Value*> in2)
00497 {
00498 std::vector<llvm::Value*> res(4);
00499
00500 res[0] = m_builder.CreateSub(in1[0], in2[0], name("subx"));
00501 res[1] = m_builder.CreateSub(in1[1], in2[1], name("suby"));
00502 res[2] = m_builder.CreateSub(in1[2], in2[2], name("subz"));
00503 res[3] = m_builder.CreateSub(in1[3], in2[3], name("subw"));
00504
00505 return res;
00506 }
00507
00508 std::vector<llvm::Value*> InstructionsSoa::lit(const std::vector<llvm::Value*> in)
00509 {
00510 llvm::Function *func = function(TGSI_OPCODE_LIT);
00511 return callBuiltin(func, in);
00512 }
00513
00514 std::vector<llvm::Value*> InstructionsSoa::rsq(const std::vector<llvm::Value*> in)
00515 {
00516 llvm::Function *func = function(TGSI_OPCODE_RSQ);
00517 return callBuiltin(func, in);
00518 }
00519