storagesoa.cpp \
instructionssoa.cpp
-INC_SOURCES = gallivm_builtins.cpp
+INC_SOURCES = gallivm_builtins.cpp gallivmsoabuiltins.cpp
CPP_SOURCES = \
$(GALLIVM_SOURCES)
gallivm_builtins.cpp: llvm_builtins.c
- clang --emit-llvm $< |llvm-as|opt -std-compile-opts|llvm2cpp -gen-contents -o=$@ -f -for=shader -funcname=createGallivmBuiltins
+ clang --emit-llvm < $< |llvm-as|opt -std-compile-opts|llvm2cpp -gen-contents -o=$@ -f -for=shader -funcname=createGallivmBuiltins
+gallivmsoabuiltins.cpp: soabuiltins.c
+ clang --emit-llvm < $< |llvm-as|opt -std-compile-opts|llvm2cpp -gen-module -o=$@ -f -for=shader -funcname=createSoaBuiltins
# Emacs tags
tags:
-rm -f *.o */*.o *~ *.so *~ server/*.o
-rm -f depend depend.bak
-rm -f gallivm_builtins.cpp
+ -rm -f gallivmsoabuiltins.cpp
symlinks:
#include <llvm/InstrTypes.h>
#include <llvm/Instructions.h>
#include <llvm/ParameterAttributes.h>
+#include <llvm/ParamAttrsList.h>
#include <sstream>
#include <fstream>
#include "gallivm_builtins.cpp"
+#if 0
+
+llvm::Value *arrayFromChannels(std::vector<llvm::Value*> &vals)
+{
+ VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
+ ArrayType *vectorArray = ArrayType::get(vectorType, 4);
+}
+#endif
+
static inline std::string createFuncName(int label)
{
std::ostringstream stream;
#include "storagesoa.h"
+#include "pipe/p_shader_tokens.h"
+
+#include <llvm/CallingConv.h>
#include <llvm/Constants.h>
+#include <llvm/Module.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+#include <llvm/ParamAttrsList.h>
+
+#include <iostream>
+
+/* 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_storage(storage),
m_idx(0)
{
+ createFunctionMap();
+ createBuiltins();
}
const char * InstructionsSoa::name(const char *prefix) const
return res;
}
+
+void InstructionsSoa::createFunctionMap()
+{
+ m_functionsMap[TGSI_OPCODE_DP3] = "dp3";
+}
+
+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 "<<func->getParent()
+ <<", cur is "<<currentModule() <<std::endl;
+ //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<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2)
+{
+ llvm::Function *func = function(TGSI_OPCODE_DP3);
+ std::vector<Value*> params;
+
+ llvm::Value *tmp = allocaTemp();
+ params.push_back(tmp);
+
+ 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(),
+ name("dp3"));
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+
+ std::vector<Value*> indices;
+ indices.push_back(m_storage->constantInt(0));
+ indices.push_back(m_storage->constantInt(0));
+
+ GetElementPtrInst *getElem = new GetElementPtrInst(tmp,
+ indices.begin(),
+ indices.end(),
+ name("allocaPtr"),
+ m_builder.GetInsertBlock());
+ indices = std::vector<Value*>();
+ indices.push_back(m_storage->constantInt(0));
+ GetElementPtrInst *xElemPtr = new GetElementPtrInst(getElem,
+ m_storage->constantInt(0),
+ name("xPtr"),
+ m_builder.GetInsertBlock());
+ GetElementPtrInst *yElemPtr = new GetElementPtrInst(getElem,
+ m_storage->constantInt(1),
+ name("yPtr"),
+ m_builder.GetInsertBlock());
+ GetElementPtrInst *zElemPtr = new GetElementPtrInst(getElem,
+ m_storage->constantInt(2),
+ name("zPtr"),
+ m_builder.GetInsertBlock());
+ GetElementPtrInst *wElemPtr = new GetElementPtrInst(getElem,
+ m_storage->constantInt(3),
+ name("wPtr"),
+ m_builder.GetInsertBlock());
+
+ std::vector<llvm::Value*> res(4);
+ res[0] = new LoadInst(xElemPtr);
+ res[1] = new LoadInst(yElemPtr);
+ res[2] = new LoadInst(zElemPtr);
+ res[3] = new LoadInst(wElemPtr);
+
+ return res;
+}
#include <llvm/Support/LLVMBuilder.h>
+#include <map>
#include <vector>
namespace llvm {
llvm::BasicBlock *block, StorageSoa *storage);
std::vector<llvm::Value*> arl(const std::vector<llvm::Value*> in);
-
std::vector<llvm::Value*> add(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
+ std::vector<llvm::Value*> dp3(const std::vector<llvm::Value*> in1,
+ const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> madd(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2,
const std::vector<llvm::Value*> in3);
const char * name(const char *prefix) const;
llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y,
llvm::Value *z, llvm::Value *w);
+ void createFunctionMap();
+ void createBuiltins();
+ llvm::Function *function(int);
+ llvm::Module *currentModule() const;
+ llvm::Value *allocaTemp();
private:
llvm::LLVMFoldingBuilder m_builder;
StorageSoa *m_storage;
+
+ std::map<int, std::string> m_functionsMap;
+ std::map<int, llvm::Function*> m_functions;
+ llvm::Module *m_builtins;
+
private:
mutable int m_idx;
mutable char m_name[32];
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * This file is compiled with clang into the LLVM bitcode
+ *
+ * Authors:
+ * Zack Rusin zack@tungstengraphics.com
+ */
+typedef __attribute__(( ocu_vector_type(4) )) float float4;
+
+void dp3(float4 *res,
+ float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
+ float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
+{
+ float4 dot = (tmp0x * tmp1x) + (tmp0y * tmp1y) +
+ (tmp0z * tmp1z);
+
+ res[0] = dot;
+ res[1] = dot;
+ res[2] = dot;
+ res[3] = dot;
+}
+
+#if 0
+void yo(float4 *out, float4 *in)
+{
+ float4 res[4];
+
+ dp3(res, in[0], in[1], in[2], in[3],
+ in[4], in[5], in[6], in[7]);
+ out[1] = res[1];
+}
+#endif
return constVector;
}
-std::vector<llvm::Value*> StorageSoa::load(Argument type, int idx, int swizzle,
+std::vector<llvm::Value*> StorageSoa::load(enum tgsi_file_type type, int idx, int swizzle,
llvm::Value *indIdx)
{
std::vector<llvm::Value*> val(4);
debug_printf("XXXXXXXXX realIdx = %p, indIdx = %p\n", realIndex, indIdx);
switch(type) {
- case Input:
+ case TGSI_FILE_INPUT:
val = inputElement(realIndex);
break;
- case Output:
+ case TGSI_FILE_OUTPUT:
val = outputElement(realIndex);
break;
- case Temp:
+ case TGSI_FILE_TEMPORARY:
val = tempElement(realIndex);
break;
- case Const:
+ case TGSI_FILE_CONSTANT:
val = constElement(realIndex);
break;
- case Immediate:
+ case TGSI_FILE_IMMEDIATE:
val = immediateElement(realIndex);
break;
- case Address:
+ case TGSI_FILE_ADDRESS:
debug_printf("Address not handled in the load phase!\n");
assert(0);
break;
+ default:
+ debug_printf("Unknown load!\n");
+ assert(0);
+ break;
}
if (!gallivm_is_swizzle(swizzle))
return val;
return res;
}
-void StorageSoa::store(Argument type, int idx, const std::vector<llvm::Value*> &val,
+void StorageSoa::store(enum tgsi_file_type type, int idx, const std::vector<llvm::Value*> &val,
int mask)
{
llvm::Value *out = 0;
switch(type) {
- case Output:
+ case TGSI_FILE_OUTPUT:
out = m_output;
break;
- case Temp:
+ case TGSI_FILE_TEMPORARY:
out = m_temps;
break;
- case Input:
+ case TGSI_FILE_INPUT:
out = m_input;
break;
- case Address: {
+ case TGSI_FILE_ADDRESS: {
llvm::Value *addr = m_addresses[idx];
if (!addr) {
addAddress(idx);
#ifndef STORAGESOA_H
#define STORAGESOA_H
+#include <pipe/p_shader_tokens.h>
+
#include <vector>
#include <list>
#include <map>
class StorageSoa
{
-public:
- enum Argument {
- Input,
- Output,
- Temp,
- Const,
- Immediate,
- Address
- };
public:
StorageSoa(llvm::BasicBlock *block,
llvm::Value *input,
llvm::Value *temps);
- std::vector<llvm::Value*> load(Argument type, int idx, int swizzle,
+ std::vector<llvm::Value*> load(enum tgsi_file_type type, int idx, int swizzle,
llvm::Value *indIdx =0);
- void store(Argument type, int idx, const std::vector<llvm::Value*> &val,
+ void store(enum tgsi_file_type type, int idx, const std::vector<llvm::Value*> &val,
int mask);
void addImmediate(float *vec);
if (src->SrcRegister.Indirect) {
indIdx = storage->addrElement(src->SrcRegisterInd.Index);
}
- if (src->SrcRegister.File == TGSI_FILE_CONSTANT) {
- val = storage->load(StorageSoa::Const,
- src->SrcRegister.Index, swizzle, indIdx);
- } else if (src->SrcRegister.File == TGSI_FILE_INPUT) {
- val = storage->load(StorageSoa::Input,
- src->SrcRegister.Index, swizzle, indIdx);
- } else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) {
- val = storage->load(StorageSoa::Temp,
- src->SrcRegister.Index, swizzle, indIdx);
- } else if (src->SrcRegister.File == TGSI_FILE_OUTPUT) {
- val = storage->load(StorageSoa::Output,
- src->SrcRegister.Index, swizzle, indIdx);
- } else if (src->SrcRegister.File == TGSI_FILE_IMMEDIATE) {
- val = storage->load(StorageSoa::Immediate,
- src->SrcRegister.Index, swizzle, indIdx);
- } else {
- fprintf(stderr, "ERROR: not supported llvm source %d\n", src->SrcRegister.File);
- return;
- }
+
+ val = storage->load((enum tgsi_file_type)src->SrcRegister.File,
+ src->SrcRegister.Index, swizzle, indIdx);
inputs[i] = val;
}
}
break;
case TGSI_OPCODE_DP3: {
+ out = instr->dp3(inputs[0], inputs[1]);
}
break;
case TGSI_OPCODE_DP4: {
for (int i = 0; i < inst->Instruction.NumDstRegs; ++i) {
struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
- if (dst->DstRegister.File == TGSI_FILE_OUTPUT) {
- storage->store(StorageSoa::Output,
- dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
- } else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) {
- storage->store(StorageSoa::Temp,
- dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
- } else if (dst->DstRegister.File == TGSI_FILE_ADDRESS) {
- storage->store(StorageSoa::Address,
- dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
- } else {
- fprintf(stderr, "ERROR: unsupported LLVM destination!");
- assert(!"wrong destination");
- }
+ storage->store((enum tgsi_file_type)dst->DstRegister.File,
+ dst->DstRegister.Index, out, dst->DstRegister.WriteMask);
}
}
unsigned Extended : 1; /* BOOL */
};
-#define TGSI_FILE_NULL 0
-#define TGSI_FILE_CONSTANT 1
-#define TGSI_FILE_INPUT 2
-#define TGSI_FILE_OUTPUT 3
-#define TGSI_FILE_TEMPORARY 4
-#define TGSI_FILE_SAMPLER 5
-#define TGSI_FILE_ADDRESS 6
-#define TGSI_FILE_IMMEDIATE 7
-#define TGSI_FILE_COUNT 8 /**< how many TGSI_FILE_ types */
+enum tgsi_file_type {
+ TGSI_FILE_NULL =0,
+ TGSI_FILE_CONSTANT =1,
+ TGSI_FILE_INPUT =2,
+ TGSI_FILE_OUTPUT =3,
+ TGSI_FILE_TEMPORARY =4,
+ TGSI_FILE_SAMPLER =5,
+ TGSI_FILE_ADDRESS =6,
+ TGSI_FILE_IMMEDIATE =7,
+ TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */
+};
#define TGSI_DECLARE_RANGE 0