Implement frc and floor
authorZack Rusin <zack@tungstengraphics.com>
Thu, 18 Oct 2007 11:03:37 +0000 (07:03 -0400)
committerZack Rusin <zack@tungstengraphics.com>
Wed, 24 Oct 2007 15:21:04 +0000 (11:21 -0400)
src/mesa/pipe/llvm/instructions.cpp
src/mesa/pipe/llvm/instructions.h
src/mesa/pipe/llvm/llvmtgsi.cpp

index 1e6b74eac62f581dee2624101947049a2032f79a..ee9104434ff6c947c2605dd6355470755c186d94 100644 (file)
@@ -16,6 +16,7 @@ Instructions::Instructions(llvm::Module *mod, llvm::BasicBlock *block)
    m_llvmFSqrt = 0;
    m_llvmFAbs = 0;
    m_llvmPow = 0;
+   m_llvmFloor = 0;
 }
 
 llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
@@ -311,3 +312,53 @@ llvm::Value * Instructions::ex2(llvm::Value *in)
    return vectorFromVals(val, val, val, val);
 }
 
+llvm::Value * Instructions::callFloor(llvm::Value *val)
+{
+   if (!m_llvmFloor) {
+      // predeclare the intrinsic
+      std::vector<const Type*> floorArgs;
+      floorArgs.push_back(Type::FloatTy);
+      ParamAttrsList *floorPal = 0;
+      FunctionType* floorType = FunctionType::get(
+         /*Result=*/Type::FloatTy,
+         /*Params=*/floorArgs,
+         /*isVarArg=*/false,
+         /*ParamAttrs=*/floorPal);
+      m_llvmFloor = new Function(
+         /*Type=*/floorType,
+         /*Linkage=*/GlobalValue::ExternalLinkage,
+         /*Name=*/"floorf", m_mod);
+      m_llvmFloor->setCallingConv(CallingConv::C);
+   }
+   CallInst *call = new CallInst(m_llvmFloor, val,
+                                 name("floorf"),
+                                 m_block);
+   call->setCallingConv(CallingConv::C);
+   call->setTailCall(false);
+   return call;
+}
+
+llvm::Value * Instructions::floor(llvm::Value *in)
+{
+   ExtractElementInst *x = new ExtractElementInst(in, unsigned(0),
+                                                  name("extractx"),
+                                                  m_block);
+   ExtractElementInst *y = new ExtractElementInst(in, unsigned(1),
+                                                  name("extracty"),
+                                                  m_block);
+   ExtractElementInst *z = new ExtractElementInst(in, unsigned(2),
+                                                  name("extractz"),
+                                                  m_block);
+   ExtractElementInst *w = new ExtractElementInst(in, unsigned(3),
+                                                  name("extractw"),
+                                                  m_block);
+   return vectorFromVals(callFloor(x), callFloor(y),
+                         callFloor(z), callFloor(w));
+}
+
+llvm::Value * Instructions::frc(llvm::Value *in)
+{
+   llvm::Value *flr = floor(in);
+   return sub(in, flr);
+}
+
index de33b79e378435525243e3dec44c2b13739ebd52..17165ac9e70b3292ed03c678152aa983f9890c9f 100644 (file)
@@ -20,6 +20,8 @@ public:
    llvm::Value *dph(llvm::Value *in1, llvm::Value *in2);
    llvm::Value *dst(llvm::Value *in1, llvm::Value *in2);
    llvm::Value *ex2(llvm::Value *in1);
+   llvm::Value *floor(llvm::Value *in1);
+   llvm::Value *frc(llvm::Value *in1);
    llvm::Value *lit(llvm::Value *in1);
    llvm::Value *madd(llvm::Value *in1, llvm::Value *in2,
                      llvm::Value *in2);
@@ -31,8 +33,9 @@ public:
 private:
    const char *name(const char *prefix);
 
-   llvm::Value *callFSqrt(llvm::Value *val);
    llvm::Value *callFAbs(llvm::Value *val);
+   llvm::Value *callFloor(llvm::Value *val);
+   llvm::Value *callFSqrt(llvm::Value *val);
    llvm::Value *callPow(llvm::Value *val1, llvm::Value *val2);
 
    llvm::Value *vectorFromVals(llvm::Value *x, llvm::Value *y,
@@ -48,6 +51,7 @@ private:
    llvm::Function   *m_llvmFSqrt;
    llvm::Function   *m_llvmFAbs;
    llvm::Function   *m_llvmPow;
+   llvm::Function   *m_llvmFloor;
 };
 
 #endif
index 5ad45ff6ccf46794f799b005eb680a0495198d63..44caa59d52f932d5c0c17a52cc9e174d3241c0ec 100644 (file)
@@ -241,11 +241,15 @@ translate_instruction(llvm::Module *module,
       break;
    case TGSI_OPCODE_NEGATE:
       break;
-   case TGSI_OPCODE_FRAC:
+   case TGSI_OPCODE_FRAC: {
+      out = instr->frc(inputs[0]);
+   }
       break;
    case TGSI_OPCODE_CLAMP:
       break;
-   case TGSI_OPCODE_FLOOR:
+   case TGSI_OPCODE_FLOOR: {
+      out = instr->floor(inputs[0]);
+   }
       break;
    case TGSI_OPCODE_ROUND:
       break;