#include "instructionssoa.h" #include "storagesoa.h" #include "pipe/p_shader_tokens.h" #include #include #include #include #include #include #include #include /* disable some warnings. this file is autogenerated */ #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-variable" #endif using namespace llvm; #include "gallivmsoabuiltins.cpp" #if defined(__GNUC__) #pragma GCC diagnostic warning "-Wunused-variable" #endif InstructionsSoa::InstructionsSoa(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block, StorageSoa *storage) : m_builder(block), m_storage(storage), m_idx(0) { createFunctionMap(); createBuiltins(); } const char * InstructionsSoa::name(const char *prefix) const { ++m_idx; snprintf(m_name, 32, "%s%d", prefix, m_idx); return m_name; } llvm::Value * InstructionsSoa::vectorFromVals(llvm::Value *x, llvm::Value *y, llvm::Value *z, llvm::Value *w) { VectorType *vectorType = VectorType::get(Type::FloatTy, 4); Constant *constVector = Constant::getNullValue(vectorType); Value *res = m_builder.CreateInsertElement(constVector, x, m_storage->constantInt(0), name("vecx")); res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1), name("vecxy")); res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2), name("vecxyz")); if (w) res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3), name("vecxyzw")); return res; } std::vector InstructionsSoa::arl(const std::vector in) { std::vector res(4); //Extract x's llvm::Value *x1 = m_builder.CreateExtractElement(in[0], m_storage->constantInt(0), name("extractX")); //cast it to an unsigned int x1 = m_builder.CreateFPToUI(x1, IntegerType::get(32), name("x1IntCast")); res[0] = x1;//vectorFromVals(x1, x2, x3, x4); //only x is valid. the others shouldn't be necessary /* res[1] = Constant::getNullValue(m_floatVecType); res[2] = Constant::getNullValue(m_floatVecType); res[3] = Constant::getNullValue(m_floatVecType); */ return res; } std::vector InstructionsSoa::add(const std::vector in1, const std::vector in2) { std::vector res(4); res[0] = m_builder.CreateAdd(in1[0], in2[0], name("addx")); res[1] = m_builder.CreateAdd(in1[1], in2[1], name("addy")); res[2] = m_builder.CreateAdd(in1[2], in2[2], name("addz")); res[3] = m_builder.CreateAdd(in1[3], in2[3], name("addw")); return res; } std::vector InstructionsSoa::mul(const std::vector in1, const std::vector in2) { std::vector res(4); res[0] = m_builder.CreateMul(in1[0], in2[0], name("mulx")); res[1] = m_builder.CreateMul(in1[1], in2[1], name("muly")); res[2] = m_builder.CreateMul(in1[2], in2[2], name("mulz")); res[3] = m_builder.CreateMul(in1[3], in2[3], name("mulw")); return res; } void InstructionsSoa::end() { m_builder.CreateRetVoid(); } std::vector InstructionsSoa::madd(const std::vector in1, const std::vector in2, const std::vector in3) { std::vector res = mul(in1, in2); return add(res, in3); } std::vector InstructionsSoa::extractVector(llvm::Value *vector) { std::vector res(4); res[0] = m_builder.CreateExtractElement(vector, m_storage->constantInt(0), name("extract1X")); res[1] = m_builder.CreateExtractElement(vector, m_storage->constantInt(1), name("extract2X")); res[2] = m_builder.CreateExtractElement(vector, m_storage->constantInt(2), name("extract3X")); res[3] = m_builder.CreateExtractElement(vector, m_storage->constantInt(3), name("extract4X")); return res; } void InstructionsSoa::createFunctionMap() { m_functionsMap[TGSI_OPCODE_DP3] = "dp3"; m_functionsMap[TGSI_OPCODE_DP4] = "dp4"; } llvm::Function * InstructionsSoa::function(int op) { if (m_functions.find(op) != m_functions.end()) return m_functions[op]; std::string name = m_functionsMap[op]; llvm::Function *originalFunc = m_builtins->getFunction(name); llvm::Function *func = CloneFunction(originalFunc); currentModule()->getFunctionList().push_back(func); std::cout << "Func parent is "<getParent() <<", cur is "<dump(); //func->setParent(currentModule()); m_functions[op] = func; return func; } llvm::Module * InstructionsSoa::currentModule() const { BasicBlock *block = m_builder.GetInsertBlock(); if (!block || !block->getParent()) return 0; return block->getParent()->getParent(); } void InstructionsSoa::createBuiltins() { m_builtins = createSoaBuiltins(); } std::vector InstructionsSoa::dp3(const std::vector in1, const std::vector in2) { llvm::Function *func = function(TGSI_OPCODE_DP3); return callBuiltin(func, in1, in2); } llvm::Value * InstructionsSoa::allocaTemp() { VectorType *vector = VectorType::get(Type::FloatTy, 4); ArrayType *vecArray = ArrayType::get(vector, 4); AllocaInst *alloca = new AllocaInst(vecArray, name("tmpRes"), m_builder.GetInsertBlock()); std::vector indices; indices.push_back(m_storage->constantInt(0)); indices.push_back(m_storage->constantInt(0)); GetElementPtrInst *getElem = new GetElementPtrInst(alloca, indices.begin(), indices.end(), name("allocaPtr"), m_builder.GetInsertBlock()); return getElem; } std::vector InstructionsSoa::allocaToResult(llvm::Value *allocaPtr) { GetElementPtrInst *xElemPtr = new GetElementPtrInst(allocaPtr, m_storage->constantInt(0), name("xPtr"), m_builder.GetInsertBlock()); GetElementPtrInst *yElemPtr = new GetElementPtrInst(allocaPtr, m_storage->constantInt(1), name("yPtr"), m_builder.GetInsertBlock()); GetElementPtrInst *zElemPtr = new GetElementPtrInst(allocaPtr, m_storage->constantInt(2), name("zPtr"), m_builder.GetInsertBlock()); GetElementPtrInst *wElemPtr = new GetElementPtrInst(allocaPtr, m_storage->constantInt(3), name("wPtr"), m_builder.GetInsertBlock()); std::vector res(4); res[0] = new LoadInst(xElemPtr, name("xRes"), false, m_builder.GetInsertBlock()); res[1] = new LoadInst(yElemPtr, name("yRes"), false, m_builder.GetInsertBlock()); res[2] = new LoadInst(zElemPtr, name("zRes"), false, m_builder.GetInsertBlock()); res[3] = new LoadInst(wElemPtr, name("wRes"), false, m_builder.GetInsertBlock()); return res; } std::vector InstructionsSoa::dp4(const std::vector in1, const std::vector in2) { llvm::Function *func = function(TGSI_OPCODE_DP4); return callBuiltin(func, in1, in2); } std::vector InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector in1) { std::vector params; llvm::Value *allocaPtr = allocaTemp(); params.push_back(allocaPtr); params.push_back(in1[0]); params.push_back(in1[1]); params.push_back(in1[2]); params.push_back(in1[3]); CallInst *call = m_builder.CreateCall(func, params.begin(), params.end()); call->setCallingConv(CallingConv::C); call->setTailCall(false); return allocaToResult(allocaPtr); } std::vector InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector in1, const std::vector in2) { std::vector params; llvm::Value *allocaPtr = allocaTemp(); params.push_back(allocaPtr); params.push_back(in1[0]); params.push_back(in1[1]); params.push_back(in1[2]); params.push_back(in1[3]); params.push_back(in2[0]); params.push_back(in2[1]); params.push_back(in2[2]); params.push_back(in2[3]); CallInst *call = m_builder.CreateCall(func, params.begin(), params.end()); call->setCallingConv(CallingConv::C); call->setTailCall(false); return allocaToResult(allocaPtr); } std::vector InstructionsSoa::callBuiltin(llvm::Function *func, const std::vector in1, const std::vector in2, const std::vector in3) { std::vector params; llvm::Value *allocaPtr = allocaTemp(); params.push_back(allocaPtr); params.push_back(in1[0]); params.push_back(in1[1]); params.push_back(in1[2]); params.push_back(in1[3]); params.push_back(in2[0]); params.push_back(in2[1]); params.push_back(in2[2]); params.push_back(in2[3]); params.push_back(in3[0]); params.push_back(in3[1]); params.push_back(in3[2]); params.push_back(in3[3]); CallInst *call = m_builder.CreateCall(func, params.begin(), params.end()); call->setCallingConv(CallingConv::C); call->setTailCall(false); return allocaToResult(allocaPtr); }