changeset 18555:5b49430a5b30 draft

Fully uint16 type support
author LYH <lyh.kernel@gmail.com>
date Thu, 26 Sep 2013 19:14:08 +0800
parents bb937947ceb3
children 4d285a169b29
files libinterp/corefcn/jit-typeinfo.cc libinterp/corefcn/jit-typeinfo.h
diffstat 2 files changed, 193 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc	Thu Sep 26 19:14:08 2013 +0800
+++ b/libinterp/corefcn/jit-typeinfo.cc	Thu Sep 26 19:14:08 2013 +0800
@@ -69,6 +69,7 @@
 #include "ov-complex.h"
 #include "ov-scalar.h"
 #include "ov-float.h"
+#include "ov-uint16.h"
 #include "pager.h"
 
 static llvm::LLVMContext& context = llvm::getGlobalContext ();
@@ -207,6 +208,20 @@
   return new octave_float_scalar (value);
 }
 
+extern "C" uint16_t
+octave_jit_cast_uint16_any (octave_base_value *obv)
+{
+  uint16_t ret = obv->uint16_scalar_value ();
+  obv->release ();
+  return ret;
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_uint16 (uint16_t value)
+{
+  return new octave_uint16_scalar (value);
+}
+
 extern "C" Complex
 octave_jit_cast_complex_any (octave_base_value *obv)
 {
@@ -496,6 +511,53 @@
   return std::pow (lhs, rhs);
 }
 
+/************************************************************
+ *
+ * uint16 related external helper function
+ *
+ ************************************************************/
+
+extern "C" uint16_t
+octave_jit_add_uint16_uint16 (uint16_t lhs, uint16_t rhs)
+{
+  uint16_t res = lhs + rhs;
+  res |= -(res < lhs);
+
+  return res;
+}
+
+extern "C" uint16_t
+octave_jit_sub_uint16_uint16 (uint16_t lhs, uint16_t rhs)
+{
+  uint16_t res = lhs - rhs;
+  res &= -(res <= lhs);
+
+  return res;
+}
+
+extern "C" uint16_t
+octave_jit_mul_uint16_uint16 (uint16_t lhs, uint16_t rhs)
+{
+  uint32_t res = (uint32_t) lhs * (uint32_t) rhs;
+
+  uint16_t hi = res >> 16;
+  uint16_t lo = res;
+
+  return lo | -!!hi;
+}
+
+extern "C" uint16_t
+octave_jit_incr_uint16 (uint16_t val)
+{
+  return octave_jit_add_uint16_uint16 (val, 1);
+}
+
+extern "C" uint16_t
+octave_jit_decr_uint16 (uint16_t val)
+{
+  return octave_jit_sub_uint16_uint16 (val, 1);
+}
+
 extern "C" void
 octave_jit_print_matrix (jit_matrix *m)
 {
@@ -1117,6 +1179,7 @@
 
   llvm::Type *scalar_t = llvm::Type::getDoubleTy (context);
   llvm::Type *single_t = llvm::Type::getFloatTy (context);
+  llvm::Type *uint16__t = llvm::Type::getIntNTy (context, 16);
   llvm::Type *bool_t = llvm::Type::getInt1Ty (context);
   llvm::Type *string_t = llvm::Type::getInt8Ty (context);
   string_t = string_t->getPointerTo ();
@@ -1170,6 +1233,8 @@
   create_int (32);
   create_int (64);
 
+  create_uint (16);
+
   casts.resize (next_id + 1);
   identities.resize (next_id + 1);
 
@@ -1263,6 +1328,7 @@
 
   grab_fn.add_overload (create_identity (scalar));
   grab_fn.add_overload (create_identity (single));
+  grab_fn.add_overload (create_identity (uintN (16)));
   grab_fn.add_overload (create_identity (scalar_ptr));
   grab_fn.add_overload (create_identity (any_ptr));
   grab_fn.add_overload (create_identity (boolean));
@@ -1283,6 +1349,7 @@
   destroy_fn.stash_name ("destroy");
   destroy_fn.add_overload (create_identity(scalar));
   destroy_fn.add_overload (create_identity(single));
+  destroy_fn.add_overload (create_identity(uintN (16)));
   destroy_fn.add_overload (create_identity(boolean));
   destroy_fn.add_overload (create_identity(index));
   destroy_fn.add_overload (create_identity(complex));
@@ -1535,6 +1602,90 @@
   unary_ops[octave_value::op_transpose].add_overload (fn);
   unary_ops[octave_value::op_hermitian].add_overload (fn);
 
+  /************************************************************
+   *
+   * uint16 related operations
+   *
+   ************************************************************/
+
+  // now for binary uint16 operations
+  fn = create_external (JIT_FN (octave_jit_add_uint16_uint16), uintN (16), uintN (16),
+                        uintN (16));
+  binary_ops[octave_value::op_add].add_overload (fn);
+  fn = create_external (JIT_FN (octave_jit_sub_uint16_uint16), uintN (16), uintN (16),
+                        uintN (16));
+  binary_ops[octave_value::op_sub].add_overload (fn);
+  fn = create_external (JIT_FN (octave_jit_mul_uint16_uint16), uintN (16), uintN (16),
+                        uintN (16));
+  binary_ops[octave_value::op_mul].add_overload (fn);
+  binary_ops[octave_value::op_el_mul].add_overload (fn);
+
+  add_binary_icmp (uintN (16), octave_value::op_lt, llvm::CmpInst::ICMP_ULT);
+  add_binary_icmp (uintN (16), octave_value::op_le, llvm::CmpInst::ICMP_ULE);
+  add_binary_icmp (uintN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ);
+  add_binary_icmp (uintN (16), octave_value::op_ge, llvm::CmpInst::ICMP_UGE);
+  add_binary_icmp (uintN (16), octave_value::op_gt, llvm::CmpInst::ICMP_UGT);
+  add_binary_icmp (uintN (16), octave_value::op_ne, llvm::CmpInst::ICMP_NE);
+
+  // FIXME: saturation divide definition? interpreter convert uint to double, calculate and round.
+  // divide is annoying because it might error
+#if 0
+  fn = create_internal ("octave_jit_div_uint16_uint16", uintN (16), uintN (16), uintN (16));
+  fn.mark_can_error ();
+
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::BasicBlock *warn_block = fn.new_block ("warn");
+    llvm::BasicBlock *normal_block = fn.new_block ("normal");
+
+    llvm::Value *zero = llvm::ConstantInt::get (uint16__t, 0);
+    llvm::Value *check = builder.CreateICmpEQ (zero, fn.argument (builder, 1));
+    builder.CreateCondBr (check, warn_block, normal_block);
+
+    builder.SetInsertPoint (warn_block);
+    gripe_div0.call (builder);
+    builder.CreateBr (normal_block);
+
+    builder.SetInsertPoint (normal_block);
+    llvm::Value *ret = builder.CreateUDiv (fn.argument (builder, 0),
+                                           fn.argument (builder, 1));
+    fn.do_return (builder, ret);
+  }
+  binary_ops[octave_value::op_div].add_overload (fn);
+  binary_ops[octave_value::op_el_div].add_overload (fn);
+
+  // ldiv is the same as div with the operators reversed
+  fn = mirror_binary (fn);
+  binary_ops[octave_value::op_ldiv].add_overload (fn);
+  binary_ops[octave_value::op_el_ldiv].add_overload (fn);
+#endif
+
+  // FIXME: Implement pow
+
+  // now for unary uint16 operations
+  // FIXME: Impelment not
+  fn = create_external (JIT_FN (octave_jit_incr_uint16), uintN (16), uintN (16));
+  unary_ops[octave_value::op_incr].add_overload (fn);
+
+  fn = create_external (JIT_FN (octave_jit_decr_uint16), uintN (16), uintN (16));
+  unary_ops[octave_value::op_decr].add_overload (fn);
+
+  fn = create_internal ("octave_jit_uminus", uintN (16), uintN (16));
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *zero = llvm::ConstantInt::get (uint16__t, 0);
+
+    fn.do_return (builder, zero);
+  }
+  unary_ops[octave_value::op_uminus].add_overload (fn);
+
+  fn = create_identity (uintN (16));
+  unary_ops[octave_value::op_uplus].add_overload (fn);
+  unary_ops[octave_value::op_transpose].add_overload (fn);
+  unary_ops[octave_value::op_hermitian].add_overload (fn);
+
   fn = create_internal ("octave_jit_*_scalar_complex", complex, scalar,
                         complex);
   jit_function mul_scalar_complex = fn;
@@ -1912,6 +2063,7 @@
   casts[any->type_id ()].stash_name ("(any)");
   casts[scalar->type_id ()].stash_name ("(scalar)");
   casts[single->type_id ()].stash_name ("(single)");
+  casts[uintN (16)->type_id ()].stash_name ("(uint16)");
   casts[complex->type_id ()].stash_name ("(complex)");
   casts[matrix->type_id ()].stash_name ("(matrix)");
   casts[range->type_id ()].stash_name ("(range)");
@@ -1948,6 +2100,14 @@
   fn = create_external (JIT_FN (octave_jit_cast_single_any), single, any);
   casts[single->type_id ()].add_overload (fn);
 
+  // cast any <- uint16
+  fn = create_external (JIT_FN (octave_jit_cast_any_uint16), any, uintN (16));
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast uint16 <- any
+  fn = create_external (JIT_FN (octave_jit_cast_uint16_any), uintN (16), any);
+  casts[uintN (16)->type_id ()].add_overload (fn);
+
   // cast any <- complex
   fn = create_external (JIT_FN (octave_jit_cast_any_complex), any, complex);
   casts[any->type_id ()].add_overload (fn);
@@ -1985,6 +2145,10 @@
   fn = create_identity (single);
   casts[single->type_id ()].add_overload (fn);
 
+  // cast uint16 <- uint16
+  fn = create_identity (uintN (16));
+  casts[uintN (16)->type_id ()].add_overload (fn);
+
   // cast complex <- complex
   fn = create_identity (complex);
   casts[complex->type_id ()].add_overload (fn);
@@ -2383,6 +2547,15 @@
                                                                     nbits));
 }
 
+void
+jit_typeinfo::create_uint (size_t nbits)
+{
+  std::stringstream tname;
+  tname << "uint" << nbits;
+  uints[nbits] = new_type (tname.str (), any, llvm::Type::getIntNTy (context,
+                                                                     nbits));
+}
+
 jit_type *
 jit_typeinfo::intN (size_t nbits) const
 {
@@ -2394,6 +2567,16 @@
 }
 
 jit_type *
+jit_typeinfo::uintN (size_t nbits) const
+{
+  std::map<size_t, jit_type *>::const_iterator iter = uints.find (nbits);
+  if (iter != uints.end ())
+    return iter->second;
+
+  throw jit_fail_exception ("No such unsigned integer type");
+}
+
+jit_type *
 jit_typeinfo::do_type_of (const octave_value &ov) const
 {
   if (ov.is_function ())
@@ -2424,6 +2607,11 @@
         return get_single ();
     }
 
+  if (ov.is_uint16_type())
+    {
+      return uintN (16);
+    }
+
   if (ov.is_complex_scalar ())
     {
       Complex cv = ov.complex_value ();
--- a/libinterp/corefcn/jit-typeinfo.h	Thu Sep 26 19:14:08 2013 +0800
+++ b/libinterp/corefcn/jit-typeinfo.h	Thu Sep 26 19:14:08 2013 +0800
@@ -794,8 +794,12 @@
 
   void create_int (size_t nbits);
 
+  void create_uint (size_t nbits);
+
   jit_type *intN (size_t nbits) const;
 
+  jit_type *uintN (size_t nbits) const;
+
   static jit_typeinfo *instance;
 
   llvm::Module *module;
@@ -821,6 +825,7 @@
   jit_type *complex;
   jit_type *unknown_function;
   std::map<size_t, jit_type *> ints;
+  std::map<size_t, jit_type *> uints;
   std::map<std::string, jit_type *> builtins;
 
   llvm::StructType *complex_ret;