Implement basic opcode translation and storage translation.

This commit is contained in:
Zack Rusin 2007-10-17 11:27:46 -04:00
parent fa2962d148
commit 3975f34fd3
5 changed files with 350 additions and 27 deletions

View file

@ -0,0 +1,162 @@
#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;
}

View file

@ -0,0 +1,43 @@
#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

View file

@ -30,6 +30,7 @@
#include <llvm/Bitcode/ReaderWriter.h>
#include <iostream>
#include "instructions.h"
using namespace llvm;
#include "llvm_base_shader.cpp"
#include "tgsillvmbuilder.cpp"
@ -117,31 +118,82 @@ translate_immediate(llvm::Module *module,
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;
@ -155,7 +207,9 @@ translate_instruction(llvm::Module *module,
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;
@ -400,6 +454,7 @@ translate_instruction(llvm::Module *module,
break;
}
switch( inst->Instruction.Saturate ) {
case TGSI_SAT_NONE:
break;
@ -412,6 +467,31 @@ translate_instruction(llvm::Module *module,
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
}
}
@ -450,7 +530,8 @@ tgsi_to_llvm(const struct tgsi_token *tokens)
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);
@ -469,7 +550,7 @@ tgsi_to_llvm(const struct tgsi_token *tokens)
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
translate_instruction(mod, &builder,
translate_instruction(mod, &storage, &instr,
&parse.FullToken.FullInstruction,
&fi);
break;

View file

@ -1,41 +1,52 @@
#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);
@ -47,7 +58,7 @@ VertexShaderBuilder::VertexShaderBuilder(llvm::BasicBlock *block, llvm::Value *i
}
//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];
@ -73,7 +84,7 @@ llvm::Constant *VertexShaderBuilder::shuffleMask(int 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];
@ -83,7 +94,7 @@ llvm::ConstantInt *VertexShaderBuilder::constantInt(int 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];
@ -102,7 +113,7 @@ llvm::Value *VertexShaderBuilder::inputElement(int 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];
@ -121,7 +132,7 @@ llvm::Value *VertexShaderBuilder::constElement(int 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;
@ -132,3 +143,28 @@ llvm::Value *VertexShaderBuilder::shuffleVector(llvm::Value *vec, int shuffle)
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);
}

View file

@ -191,7 +191,8 @@ TGSIMESA_SOURCES = \
ifeq ($(MESA_NO_LLVM),0)
LLVMTGSI_SOURCES = \
pipe/llvm/llvmtgsi.cpp
pipe/llvm/llvmtgsi.cpp \
pipe/llvm/instructions.cpp
endif
STATECACHE_SOURCES = \