--- /dev/null
+#include "instructions.h"
+
+#include <llvm/CallingConv.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/InstrTypes.h>
+#include <llvm/Instructions.h>
+
+using namespace llvm;
+
+Instructions::Instructions(llvm::Module *mod, llvm::BasicBlock *block)
+ : m_mod(mod), m_block(block), m_idx(0)
+{
+ m_floatVecType = VectorType::get(Type::FloatTy, 4);
+ m_llvmFSqrt = 0;
+ m_llvmFAbs = 0;
+}
+
+llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
+{
+ BinaryOperator *res = BinaryOperator::create(Instruction::Add, in1, in2,
+ name("add"),
+ m_block);
+ return res;
+}
+
+llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2,
+ llvm::Value *in3)
+{
+ Value *mulRes = mul(in1, in2);
+ return add(mulRes, in3);
+}
+
+llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2)
+{
+ BinaryOperator *res = BinaryOperator::create(Instruction::Mul, in1, in2,
+ name("mul"),
+ m_block);
+ return res;
+}
+
+const char * Instructions::name(const char *prefix)
+{
+ ++m_idx;
+ snprintf(m_name, 32, "%s%d", prefix, m_idx);
+ return m_name;
+}
+
+llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2)
+{
+ Value *mulRes = mul(in1, in2);
+ ExtractElementInst *x = new ExtractElementInst(mulRes, unsigned(0),
+ name("extractx"),
+ m_block);
+ ExtractElementInst *y = new ExtractElementInst(mulRes, unsigned(1),
+ name("extracty"),
+ m_block);
+ ExtractElementInst *z = new ExtractElementInst(mulRes, unsigned(2),
+ name("extractz"),
+ m_block);
+ BinaryOperator *xy = BinaryOperator::create(Instruction::Add, x, y,
+ name("xy"),
+ m_block);
+ BinaryOperator *dot3 = BinaryOperator::create(Instruction::Add, xy, z,
+ name("dot3"),
+ m_block);
+ return vectorFromVals(dot3, dot3, dot3, dot3);
+}
+
+llvm::Value *Instructions::callFSqrt(llvm::Value *val)
+{
+ if (!m_llvmFSqrt) {
+ // predeclare the intrinsic
+ std::vector<const Type*> fsqrtArgs;
+ fsqrtArgs.push_back(Type::FloatTy);
+ ParamAttrsList *fsqrtPal = 0;
+ FunctionType* fsqrtType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/fsqrtArgs,
+ /*isVarArg=*/false,
+ /*ParamAttrs=*/fsqrtPal);
+ m_llvmFSqrt = new Function(
+ /*Type=*/fsqrtType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"llvm.sqrt.f32", m_mod);
+ m_llvmFSqrt->setCallingConv(CallingConv::C);
+ }
+ CallInst *call = new CallInst(m_llvmFSqrt, val,
+ name("sqrt"),
+ m_block);
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::rsq(llvm::Value *in1)
+{
+ ExtractElementInst *x = new ExtractElementInst(in1, unsigned(0),
+ name("extractx"),
+ m_block);
+ Value *abs = callFAbs(x);
+ Value *sqrt = callFSqrt(abs);
+
+ BinaryOperator *rsqrt = BinaryOperator::create(Instruction::FDiv,
+ ConstantFP::get(Type::FloatTy,
+ APFloat(1.f)),
+ sqrt,
+ name("rsqrt"),
+ m_block);
+ return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt);
+}
+
+llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y,
+ llvm::Value *z, llvm::Value *w)
+{
+ Constant *const_vec = Constant::getNullValue(m_floatVecType);
+ InsertElementInst *res = new InsertElementInst(const_vec, x, unsigned(0),
+ name("vecx"), m_block);
+ res = new InsertElementInst(res, y, unsigned(1),
+ name("vecxy"),
+ m_block);
+ res = new InsertElementInst(res, z, unsigned(2),
+ name("vecxyz"),
+ m_block);
+ if (w)
+ res = new InsertElementInst(res, w, unsigned(3),
+ name("vecxyw"),
+ m_block);
+ return res;
+}
+
+llvm::Value *Instructions::callFAbs(llvm::Value *val)
+{
+ if (!m_llvmFAbs) {
+ // predeclare the intrinsic
+ std::vector<const Type*> fabsArgs;
+ fabsArgs.push_back(Type::FloatTy);
+ ParamAttrsList *fabsPal = 0;
+ FunctionType* fabsType = FunctionType::get(
+ /*Result=*/Type::FloatTy,
+ /*Params=*/fabsArgs,
+ /*isVarArg=*/false,
+ /*ParamAttrs=*/fabsPal);
+ m_llvmFAbs = new Function(
+ /*Type=*/fabsType,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"fabs", m_mod);
+ m_llvmFAbs->setCallingConv(CallingConv::C);
+ }
+ CallInst *call = new CallInst(m_llvmFAbs, val,
+ name("fabs"),
+ m_block);
+ call->setCallingConv(CallingConv::C);
+ call->setTailCall(false);
+ return call;
+}
+
+llvm::Value * Instructions::lit(llvm::Value *in1)
+{
+ return in1;
+}
+
--- /dev/null
+#ifndef INSTRUCTIONS_H
+#define INSTRUCTIONS_H
+
+#include <llvm/BasicBlock.h>
+#include <llvm/Module.h>
+#include <llvm/Value.h>
+
+namespace llvm {
+ class VectorType;
+}
+
+class Instructions
+{
+public:
+ Instructions(llvm::Module *mod, llvm::BasicBlock *block);
+
+ llvm::Value *add(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *dp3(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *lit(llvm::Value *in1);
+ llvm::Value *madd(llvm::Value *in1, llvm::Value *in2,
+ llvm::Value *in2);
+ llvm::Value *mul(llvm::Value *in1, llvm::Value *in2);
+ llvm::Value *rsq(llvm::Value *in1);
+private:
+ const char *name(const char *prefix);
+
+ llvm::Value *callFSqrt(llvm::Value *val);
+ llvm::Value *callFAbs(llvm::Value *val);
+
+ llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y,
+ llvm::Value *z, llvm::Value *w=0);
+private:
+ llvm::Module *m_mod;
+ char m_name[32];
+ llvm::BasicBlock *m_block;
+ int m_idx;
+ llvm::Function *m_llvmFSqrt;
+ llvm::Function *m_llvmFAbs;
+
+ llvm::VectorType *m_floatVecType;
+};
+
+#endif
#include <llvm/Bitcode/ReaderWriter.h>
#include <iostream>
+#include "instructions.h"
using namespace llvm;
#include "llvm_base_shader.cpp"
#include "tgsillvmbuilder.cpp"
static void
translate_instruction(llvm::Module *module,
- VertexShaderBuilder *builder,
+ Storage *storage,
+ Instructions *instr,
struct tgsi_full_instruction *inst,
struct tgsi_full_instruction *fi)
{
+ llvm::Value *inputs[4];
+ for (int i = 0; i < inst->Instruction.NumSrcRegs; ++i) {
+ struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+ llvm::Value *val = 0;
+ if (src->SrcRegister.File == TGSI_FILE_CONSTANT) {
+ val = storage->constElement(src->SrcRegister.Index);
+ } else if (src->SrcRegister.File == TGSI_FILE_INPUT) {
+ val = storage->inputElement(src->SrcRegister.Index);
+ } else if (src->SrcRegister.File == TGSI_FILE_TEMPORARY) {
+ val = storage->tempElement(src->SrcRegister.Index);
+ } else {
+ fprintf(stderr, "ERROR: not support llvm source\n");
+ return;
+ }
+
+ if (src->SrcRegister.Extended) {
+ if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
+ src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
+ src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
+ src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
+ int swizzle = src->SrcRegisterExtSwz.ExtSwizzleX * 1000;
+ swizzle += src->SrcRegisterExtSwz.ExtSwizzleY * 100;
+ swizzle += src->SrcRegisterExtSwz.ExtSwizzleZ * 10;
+ swizzle += src->SrcRegisterExtSwz.ExtSwizzleW * 1;
+ val = storage->shuffleVector(val, swizzle);
+ }
+ } else if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
+ src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
+ src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
+ src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
+ int swizzle = src->SrcRegister.SwizzleX * 1000;
+ swizzle += src->SrcRegister.SwizzleY * 100;
+ swizzle += src->SrcRegister.SwizzleZ * 10;
+ swizzle += src->SrcRegister.SwizzleW * 1;
+ val = storage->shuffleVector(val, swizzle);
+ }
+ inputs[i] = val;
+ }
+
+ llvm::Value *out = 0;
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_ARL:
break;
- case TGSI_OPCODE_MOV:
+ case TGSI_OPCODE_MOV: {
+ out = inputs[0];
+ }
break;
- case TGSI_OPCODE_LIT:
+ case TGSI_OPCODE_LIT: {
+ //out = instr->lit(inputs[0]);
+ return;
+ }
break;
case TGSI_OPCODE_RCP:
break;
- case TGSI_OPCODE_RSQ:
+ case TGSI_OPCODE_RSQ: {
+ out = instr->rsq(inputs[0]);
+ }
break;
case TGSI_OPCODE_EXP:
break;
case TGSI_OPCODE_LOG:
break;
- case TGSI_OPCODE_MUL:
-
+ case TGSI_OPCODE_MUL: {
+ out = instr->mul(inputs[0], inputs[1]);
+ }
break;
case TGSI_OPCODE_ADD:
break;
- case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP3: {
+ out = instr->dp3(inputs[0], inputs[1]);
+ }
break;
case TGSI_OPCODE_DP4:
break;
break;
case TGSI_OPCODE_SGE:
break;
- case TGSI_OPCODE_MAD:
+ case TGSI_OPCODE_MAD: {
+ out = instr->madd(inputs[0], inputs[1], inputs[2]);
+ }
break;
case TGSI_OPCODE_SUB:
break;
break;
}
+
switch( inst->Instruction.Saturate ) {
case TGSI_SAT_NONE:
break;
default:
assert( 0 );
}
+
+ 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(dst->DstRegister.Index, out);
+ } else if (dst->DstRegister.File == TGSI_FILE_TEMPORARY) {
+ storage->setTempElement(dst->DstRegister.Index, out);
+ } else {
+ fprintf(stderr, "ERROR: unsupported LLVM destination!");
+ }
+
+#if 0
+ if (dst->DstRegister.WriteMask != TGSI_WRITEMASK_XYZW) {
+ if (dst->DstRegister.WriteMask & TGSI_WRITEMASK_X) {
+ }
+ if (dst->DstRegister.WriteMask & TGSI_WRITEMASK_Y) {
+ }
+ if (dst->DstRegister.WriteMask & TGSI_WRITEMASK_Z) {
+ }
+ if (dst->DstRegister.WriteMask & TGSI_WRITEMASK_W) {
+ }
+ }
+#endif
+ }
}
fi = tgsi_default_full_instruction();
fd = tgsi_default_full_declaration();
- VertexShaderBuilder builder(label_entry, ptr_IN, ptr_CONST);
+ Storage storage(label_entry, ptr_OUT, ptr_IN, ptr_CONST);
+ Instructions instr(mod, label_entry);
while(!tgsi_parse_end_of_tokens(&parse)) {
tgsi_parse_token(&parse);
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
- translate_instruction(mod, &builder,
+ translate_instruction(mod, &storage, &instr,
&parse.FullToken.FullInstruction,
&fi);
break;
#include <map>
-class VertexShaderBuilder
+class Storage
{
typedef std::map<int, llvm::LoadInst*> LoadMap;
public:
- VertexShaderBuilder(llvm::BasicBlock *block, llvm::Value *in, llvm::Value *consts);
+ Storage(llvm::BasicBlock *block,
+ llvm::Value *out,
+ llvm::Value *in, llvm::Value *consts);
llvm::ConstantInt *constantInt(int);
llvm::Constant *shuffleMask(int vec);
llvm::Value *inputElement(int idx);
llvm::Value *constElement(int idx);
+ llvm::Value *tempElement(int idx) const;
+ void setTempElement(int idx, llvm::Value *val);
+
llvm::Value *shuffleVector(llvm::Value *vec, int shuffle);
+ void store(int dstIdx, llvm::Value *val);
private:
llvm::BasicBlock *m_block;
+ llvm::Value *m_OUT;
llvm::Value *m_IN;
llvm::Value *m_CONST;
std::map<int, llvm::ConstantInt*> m_constInts;
- std::map<int, llvm::Constant*> m_intVecs;
- LoadMap m_inputs;
- LoadMap m_consts;
+ std::map<int, llvm::Constant*> m_intVecs;
+ std::vector<llvm::Value*> m_temps;
+ LoadMap m_inputs;
+ LoadMap m_consts;
- VectorType *m_floatVecType;
- VectorType *m_intVecType;
+ llvm::VectorType *m_floatVecType;
+ llvm::VectorType *m_intVecType;
- Value *m_undefFloatVec;
- Value *m_undefIntVec;
+ llvm::Value *m_undefFloatVec;
+ llvm::Value *m_undefIntVec;
int m_shuffleId;
};
-VertexShaderBuilder::VertexShaderBuilder(llvm::BasicBlock *block, llvm::Value *in, llvm::Value *consts)
- : m_block(block), m_IN(in), m_CONST(consts)
+Storage::Storage(llvm::BasicBlock *block, llvm::Value *out,
+ llvm::Value *in, llvm::Value *consts)
+ : m_block(block), m_OUT(out),
+ m_IN(in), m_CONST(consts),
+ m_temps(32)
{
m_floatVecType = VectorType::get(Type::FloatTy, 4);
m_intVecType = VectorType::get(IntegerType::get(32), 4);
}
//can only build vectors with all members in the [0, 9] range
-llvm::Constant *VertexShaderBuilder::shuffleMask(int vec)
+llvm::Constant *Storage::shuffleMask(int vec)
{
if (m_intVecs.find(vec) != m_intVecs.end()) {
return m_intVecs[vec];
return const_vec;
}
-llvm::ConstantInt *VertexShaderBuilder::constantInt(int idx)
+llvm::ConstantInt *Storage::constantInt(int idx)
{
if (m_constInts.find(idx) != m_constInts.end()) {
return m_constInts[idx];
return const_int;
}
-llvm::Value *VertexShaderBuilder::inputElement(int idx)
+llvm::Value *Storage::inputElement(int idx)
{
if (m_inputs.find(idx) != m_inputs.end()) {
return m_inputs[idx];
return load;
}
-llvm::Value *VertexShaderBuilder::constElement(int idx)
+llvm::Value *Storage::constElement(int idx)
{
if (m_consts.find(idx) != m_consts.end()) {
return m_consts[idx];
return load;
}
-llvm::Value *VertexShaderBuilder::shuffleVector(llvm::Value *vec, int shuffle)
+llvm::Value *Storage::shuffleVector(llvm::Value *vec, int shuffle)
{
Constant *mask = shuffleMask(shuffle);
++m_shuffleId;
name, m_block);
return res;
}
+
+
+llvm::Value *Storage::tempElement(int idx) const
+{
+ Value *ret = m_temps[idx];
+ if (!ret)
+ return m_undefFloatVec;
+ return ret;
+}
+
+void Storage::setTempElement(int idx, llvm::Value *val)
+{
+ m_temps[idx] = val;
+}
+
+void Storage::store(int dstIdx, llvm::Value *val)
+{
+ char ptrName[13];
+ snprintf(ptrName, 13, "out_ptr%d", dstIdx);
+ GetElementPtrInst *getElem = new GetElementPtrInst(m_OUT,
+ constantInt(dstIdx),
+ ptrName,
+ m_block);
+ new StoreInst(val, getElem, false, m_block);
+}
ifeq ($(MESA_NO_LLVM),0)
LLVMTGSI_SOURCES = \
- pipe/llvm/llvmtgsi.cpp
+ pipe/llvm/llvmtgsi.cpp \
+ pipe/llvm/instructions.cpp
endif
STATECACHE_SOURCES = \