Implement basic opcode translation and storage translation.
authorZack Rusin <zack@tungstengraphics.com>
Wed, 17 Oct 2007 15:27:46 +0000 (11:27 -0400)
committerZack Rusin <zack@tungstengraphics.com>
Wed, 24 Oct 2007 15:21:03 +0000 (11:21 -0400)
src/mesa/pipe/llvm/instructions.cpp [new file with mode: 0644]
src/mesa/pipe/llvm/instructions.h [new file with mode: 0644]
src/mesa/pipe/llvm/llvmtgsi.cpp
src/mesa/pipe/llvm/tgsillvmbuilder.cpp
src/mesa/sources

diff --git a/src/mesa/pipe/llvm/instructions.cpp b/src/mesa/pipe/llvm/instructions.cpp
new file mode 100644 (file)
index 0000000..147a1b6
--- /dev/null
@@ -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;
+}
+
diff --git a/src/mesa/pipe/llvm/instructions.h b/src/mesa/pipe/llvm/instructions.h
new file mode 100644 (file)
index 0000000..c6e7771
--- /dev/null
@@ -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
index 375e61c..5cbd0ae 100644 (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;
index 4088da1..ca70a46 100644 (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);
+}
index c2544ed..7e1d909 100644 (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 = \