changeset 17510:8376ff1462b8

Fully uint16 type support
author LYH <lyh.kernel@gmail.com>
date Thu, 26 Sep 2013 19:14:08 +0800
parents 5f884a545c06
children 79535e3d53e0
files libinterp/corefcn/jit-typeinfo.cc
diffstat 1 files changed, 105 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc
+++ b/libinterp/corefcn/jit-typeinfo.cc
@@ -509,6 +509,12 @@
   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)
 {
@@ -519,11 +525,37 @@
 }
 
 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)
 {
@@ -719,6 +751,10 @@
 jit_function::call (llvm::IRBuilderD& builder,
                     const std::vector<jit_value *>& in_args) const
 {
+  // FIXME: Unhandled case:
+  // function ret = lt(x, y)
+  //   ret = x < y;
+  // endfunction
   if (! valid ())
     throw jit_fail_exception ("Call not implemented");
 
@@ -1145,6 +1181,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 ();
@@ -1493,7 +1530,7 @@
   add_binary_fcmp (single, octave_value::op_ne, llvm::CmpInst::FCMP_UNE);
 
   // divide is annoying because it might error
-  fn = create_internal ("octave_jit_div_scalar_scalar", single, single, single);
+  fn = create_internal ("octave_jit_div_single_single", single, single, single);
   fn.mark_can_error ();
 
   body = fn.new_block ();
@@ -1581,14 +1618,80 @@
   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;