changeset 18558:1867774aaa2e draft

jit compiler: Add support for int64 type * libinterp/corefcn/pt-jit.cc: Add basic operations, casts und overloads
author LYH <lyh.kernel@gmail.com>
date Sat, 02 Nov 2013 17:14:07 +0100
parents e2770dfa0bc4
children 1a82df63d65e
files libinterp/corefcn/jit-typeinfo.cc
diffstat 1 files changed, 175 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc	Fri Sep 27 02:58:43 2013 +0800
+++ b/libinterp/corefcn/jit-typeinfo.cc	Sat Nov 02 17:14:07 2013 +0100
@@ -70,6 +70,7 @@
 #include "ov-scalar.h"
 #include "ov-float.h"
 #include "ov-int8.h"
+#include "ov-int64.h"
 #include "ov-uint16.h"
 #include "pager.h"
 
@@ -223,6 +224,20 @@
   return new octave_int8_scalar (value);
 }
 
+extern "C" int64_t
+octave_jit_cast_int64_any (octave_base_value *obv)
+{
+  int64_t ret = obv->int64_scalar_value ();
+  obv->release ();
+  return ret;
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_int64 (int64_t value)
+{
+  return new octave_int64_scalar (value);
+}
+
 extern "C" uint16_t
 octave_jit_cast_uint16_any (octave_base_value *obv)
 {
@@ -597,6 +612,89 @@
 
 /************************************************************
  *
+ * int64 related external helper function
+ *
+ ************************************************************/
+
+extern "C" int64_t
+octave_jit_add_int64_int64 (int64_t lhs, int64_t rhs)
+{
+  uint64_t ulhs = lhs;
+  uint64_t urhs = rhs;
+  uint64_t res = ulhs + urhs;
+
+  /* Calculate overflowed result. (Don't change the sign bit of ux) */
+  ulhs = (ulhs >> 63) + LONG_MAX;
+
+  /* Force compiler to use cmovns instruction */
+  if ((int64_t) ((ulhs ^ urhs) | ~(urhs ^ res)) >= 0)
+    {
+      res = ulhs;
+    }
+
+  return res;
+}
+
+extern "C" int64_t
+octave_jit_sub_int64_int64 (int64_t lhs, int64_t rhs)
+{
+  uint64_t ulhs = lhs;
+  uint64_t urhs = rhs;
+  uint64_t res = ulhs - urhs;
+
+  ulhs = (ulhs >> 63) + LONG_MAX;
+
+  /* Force compiler to use cmovns instruction */
+  if ((int64_t)((ulhs ^ urhs) & (ulhs ^ res)) < 0)
+    {
+      res = ulhs;
+    }
+
+  return res;
+}
+
+extern "C" int64_t
+octave_jit_mul_int64_int64 (int64_t lhs, int64_t rhs)
+{
+#ifdef OCTAVE_INT_USE_LONG_DOUBLE
+  long double p = static_cast<long double> (lhs) * static_cast<long double> (rhs);
+  if (p > static_cast<long double> (std::numeric_limits<int64_t>::max ()))
+    {
+      return std::numeric_limits<int64_t>::max ();
+    }
+  else if (p < static_cast<long double> (std::numeric_limits<int64_t>::min ()))
+    {
+	  return std::numeric_limits<int64_t>::min ();
+    }
+  else
+    return static_cast<int64_t> (p);
+#else
+  __int128_t res = (__int128_t) lhs * (__int128_t) rhs;
+  uint64_t res2 = ((uint64_t) (lhs ^ rhs) >> 63) + LONG_MAX;
+
+  int64_t hi = (res >> 64);
+  int64_t lo = res;
+
+  if (hi != (lo >> 63)) res = res2;
+
+  return res;
+#endif
+}
+
+extern "C" int64_t
+octave_jit_incr_int64 (int64_t val)
+{
+  return octave_jit_add_int64_int64 (val, 1);
+}
+
+extern "C" int64_t
+octave_jit_decr_int64 (int64_t val)
+{
+  return octave_jit_sub_int64_int64 (val, 1);
+}
+
+/************************************************************
+ *
  * uint16 related external helper function
  *
  ************************************************************/
@@ -1268,6 +1366,7 @@
   llvm::Type *scalar_t = llvm::Type::getDoubleTy (context);
   llvm::Type *single_t = llvm::Type::getFloatTy (context);
   llvm::Type *int8__t = llvm::Type::getIntNTy (context, 8);
+  llvm::Type *int64__t = llvm::Type::getIntNTy (context, 64);
   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);
@@ -1418,6 +1517,7 @@
   grab_fn.add_overload (create_identity (scalar));
   grab_fn.add_overload (create_identity (single));
   grab_fn.add_overload (create_identity (intN (8)));
+  grab_fn.add_overload (create_identity (intN (64)));
   grab_fn.add_overload (create_identity (uintN (16)));
   grab_fn.add_overload (create_identity (scalar_ptr));
   grab_fn.add_overload (create_identity (any_ptr));
@@ -1440,6 +1540,7 @@
   destroy_fn.add_overload (create_identity(scalar));
   destroy_fn.add_overload (create_identity(single));
   destroy_fn.add_overload (create_identity(intN (8)));
+  destroy_fn.add_overload (create_identity(intN (64)));
   destroy_fn.add_overload (create_identity(uintN (16)));
   destroy_fn.add_overload (create_identity(boolean));
   destroy_fn.add_overload (create_identity(index));
@@ -1750,6 +1851,62 @@
 
   /************************************************************
    *
+   * int64 related operations
+   *
+   ************************************************************/
+
+  // FIXME: overflow occurs at minus + minus, minus - plus
+  // now for binary int64 operations
+  fn = create_external (JIT_FN (octave_jit_add_int64_int64), intN (64), intN (64),
+                        intN (64));
+  binary_ops[octave_value::op_add].add_overload (fn);
+  fn = create_external (JIT_FN (octave_jit_sub_int64_int64), intN (64), intN (64),
+                        intN (64));
+  binary_ops[octave_value::op_sub].add_overload (fn);
+  fn = create_external (JIT_FN (octave_jit_mul_int64_int64), intN (64), intN (64),
+                        intN (64));
+  binary_ops[octave_value::op_mul].add_overload (fn);
+  binary_ops[octave_value::op_el_mul].add_overload (fn);
+
+  add_binary_icmp (intN (64), octave_value::op_lt, llvm::CmpInst::ICMP_SLT);
+  add_binary_icmp (intN (64), octave_value::op_le, llvm::CmpInst::ICMP_SLE);
+  add_binary_icmp (intN (64), octave_value::op_eq, llvm::CmpInst::ICMP_EQ);
+  add_binary_icmp (intN (64), octave_value::op_ge, llvm::CmpInst::ICMP_SGE);
+  add_binary_icmp (intN (64), octave_value::op_gt, llvm::CmpInst::ICMP_SGT);
+  add_binary_icmp (intN (64), octave_value::op_ne, llvm::CmpInst::ICMP_NE);
+
+  // FIXME: saturation divide definition? interpreter convert int to double, calculate and round.
+  // divide is annoying because it might error
+  // FIXME: Implement div
+
+  // FIXME: Implement pow
+
+  // now for unary int8 operations
+  // FIXME: Impelment not
+  fn = create_external (JIT_FN (octave_jit_incr_int64), intN (64), intN (64));
+  unary_ops[octave_value::op_incr].add_overload (fn);
+
+  fn = create_external (JIT_FN (octave_jit_decr_int64), intN (64), intN (64));
+  unary_ops[octave_value::op_decr].add_overload (fn);
+
+  fn = create_internal ("octave_jit_uminus", intN (64), intN (64));
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *mone = llvm::ConstantInt::get (int64__t, -1);
+    llvm::Value *val = fn.argument (builder, 0);
+    val = builder.CreateMul (val, mone);
+    fn.do_return (builder, val);
+  }
+  unary_ops[octave_value::op_uminus].add_overload (fn);
+
+  fn = create_identity (intN (64));
+  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);
+
+  /************************************************************
+   *
    * uint16 related operations
    *
    ************************************************************/
@@ -2210,6 +2367,7 @@
   casts[scalar->type_id ()].stash_name ("(scalar)");
   casts[single->type_id ()].stash_name ("(single)");
   casts[intN (8)->type_id ()].stash_name ("(int8)");
+  casts[intN (64)->type_id ()].stash_name ("(int64)");
   casts[uintN (16)->type_id ()].stash_name ("(uint16)");
   casts[complex->type_id ()].stash_name ("(complex)");
   casts[matrix->type_id ()].stash_name ("(matrix)");
@@ -2255,6 +2413,14 @@
   fn = create_external (JIT_FN (octave_jit_cast_int8_any), intN (8), any);
   casts[intN (8)->type_id ()].add_overload (fn);
 
+  // cast any <- int64
+  fn = create_external (JIT_FN (octave_jit_cast_any_int64), any, intN (64));
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast int64 <- any
+  fn = create_external (JIT_FN (octave_jit_cast_int64_any), intN (64), any);
+  casts[intN (64)->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);
@@ -2304,6 +2470,10 @@
   fn = create_identity (intN (8));
   casts[intN (8)->type_id ()].add_overload (fn);
 
+  // cast int64 <- int64
+  fn = create_identity (intN (64));
+  casts[intN (64)->type_id ()].add_overload (fn);
+
   // cast uint16 <- uint16
   fn = create_identity (uintN (16));
   casts[uintN (16)->type_id ()].add_overload (fn);
@@ -2771,6 +2941,11 @@
       return intN (8);
     }
 
+  if (ov.is_int64_type())
+    {
+      return intN (64);
+    }
+
   if (ov.is_uint16_type())
     {
       return uintN (16);