changeset 18554:bb937947ceb3 draft

single support
author LYH <lyh.kernel@gmail.com>
date Thu, 26 Sep 2013 19:14:08 +0800
parents 6b2cee8c110e
children 5b49430a5b30
files libinterp/corefcn/jit-typeinfo.cc libinterp/corefcn/jit-typeinfo.h
diffstat 2 files changed, 164 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc	Fri Sep 27 17:21:33 2013 +0800
+++ b/libinterp/corefcn/jit-typeinfo.cc	Thu Sep 26 19:14:08 2013 +0800
@@ -68,6 +68,7 @@
 #include "ov-builtin.h"
 #include "ov-complex.h"
 #include "ov-scalar.h"
+#include "ov-float.h"
 #include "pager.h"
 
 static llvm::LLVMContext& context = llvm::getGlobalContext ();
@@ -192,6 +193,20 @@
   return new octave_scalar (value);
 }
 
+extern "C" float
+octave_jit_cast_single_any (octave_base_value *obv)
+{
+  float ret = obv->float_value ();
+  obv->release ();
+  return ret;
+}
+
+extern "C" octave_base_value *
+octave_jit_cast_any_single (float value)
+{
+  return new octave_float_scalar (value);
+}
+
 extern "C" Complex
 octave_jit_cast_complex_any (octave_base_value *obv)
 {
@@ -446,6 +461,25 @@
   return std::pow (lhs, rhs);
 }
 
+// FIXME: should handle FloatComplex
+extern "C" Complex
+octave_jit_pow_single_single (float lhs, float rhs)
+{
+  // FIXME: almost CP from libinterp/corefcn/xpow.cc
+  float retval;
+
+  if (lhs < 0.0 && ! xisint (rhs))
+    {
+      FloatComplex lhstmp (lhs);
+
+      return std::pow (lhstmp, rhs);
+    }
+  else
+    retval = std::pow (lhs, rhs);
+
+  return retval;
+}
+
 extern "C" Complex
 octave_jit_pow_complex_scalar (Complex lhs, double rhs)
 {
@@ -1082,6 +1116,7 @@
   any_t = any_t->getPointerTo ();
 
   llvm::Type *scalar_t = llvm::Type::getDoubleTy (context);
+  llvm::Type *single_t = llvm::Type::getFloatTy (context);
   llvm::Type *bool_t = llvm::Type::getInt1Ty (context);
   llvm::Type *string_t = llvm::Type::getInt8Ty (context);
   string_t = string_t->getPointerTo ();
@@ -1122,6 +1157,7 @@
   matrix = new_type ("matrix", any, matrix_t);
   complex = new_type ("complex", any, complex_t);
   scalar = new_type ("scalar", complex, scalar_t);
+  single = new_type ("single", any, single_t);
   scalar_ptr = new_type ("scalar_ptr", 0, scalar_t->getPointerTo ());
   any_ptr = new_type ("any_ptr", 0, any_t->getPointerTo ());
   range = new_type ("range", any, range_t);
@@ -1226,6 +1262,7 @@
   grab_fn.add_overload (fn);
 
   grab_fn.add_overload (create_identity (scalar));
+  grab_fn.add_overload (create_identity (single));
   grab_fn.add_overload (create_identity (scalar_ptr));
   grab_fn.add_overload (create_identity (any_ptr));
   grab_fn.add_overload (create_identity (boolean));
@@ -1245,6 +1282,7 @@
   destroy_fn = release_fn;
   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(boolean));
   destroy_fn.add_overload (create_identity(index));
   destroy_fn.add_overload (create_identity(complex));
@@ -1346,6 +1384,12 @@
   unary_ops[octave_value::op_transpose].add_overload (fn);
   unary_ops[octave_value::op_hermitian].add_overload (fn);
 
+  /************************************************************
+   *
+   * complex related operations
+   *
+   ************************************************************/
+
   // now for binary complex operations
   fn = create_internal ("octave_jit_+_complex_complex", complex, complex,
                         complex);
@@ -1393,6 +1437,104 @@
   binary_ops[octave_value::op_pow].add_overload (fn);
   binary_ops[octave_value::op_el_pow].add_overload (fn);
 
+  /************************************************************
+   *
+   * single related operations
+   *
+   ************************************************************/
+
+  // now for binary single operations
+  add_binary_op (single, octave_value::op_add, llvm::Instruction::FAdd);
+  add_binary_op (single, octave_value::op_sub, llvm::Instruction::FSub);
+  add_binary_op (single, octave_value::op_mul, llvm::Instruction::FMul);
+  add_binary_op (single, octave_value::op_el_mul, llvm::Instruction::FMul);
+
+  add_binary_fcmp (single, octave_value::op_lt, llvm::CmpInst::FCMP_ULT);
+  add_binary_fcmp (single, octave_value::op_le, llvm::CmpInst::FCMP_ULE);
+  add_binary_fcmp (single, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ);
+  add_binary_fcmp (single, octave_value::op_ge, llvm::CmpInst::FCMP_UGE);
+  add_binary_fcmp (single, octave_value::op_gt, llvm::CmpInst::FCMP_UGT);
+  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_single_single", single, single, single);
+  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::ConstantFP::get (single_t, 0);
+    llvm::Value *check = builder.CreateFCmpUEQ (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.CreateFDiv (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);
+
+  // In general, the result of scalar ^ scalar is a complex number. We might be
+  // able to improve on this if we keep track of the range of values varaibles
+  // can take on.
+  fn = create_external (JIT_FN (octave_jit_pow_single_single), complex, single,
+                        single);
+  binary_ops[octave_value::op_pow].add_overload (fn);
+  binary_ops[octave_value::op_el_pow].add_overload (fn);
+
+  // now for unary single operations
+  // FIXME: Impelment not
+  fn = create_internal ("octave_jit_++", single, single);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *one = llvm::ConstantFP::get (single_t, 1);
+    llvm::Value *val = fn.argument (builder, 0);
+    val = builder.CreateFAdd (val, one);
+    fn.do_return (builder, val);
+  }
+  unary_ops[octave_value::op_incr].add_overload (fn);
+
+  fn = create_internal ("octave_jit_--", single, single);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *one = llvm::ConstantFP::get (single_t, 1);
+    llvm::Value *val = fn.argument (builder, 0);
+    val = builder.CreateFSub (val, one);
+    fn.do_return (builder, val);
+  }
+  unary_ops[octave_value::op_decr].add_overload (fn);
+
+  fn = create_internal ("octave_jit_uminus", single, single);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *mone = llvm::ConstantFP::get (single_t, -1);
+    llvm::Value *val = fn.argument (builder, 0);
+    val = builder.CreateFMul (val, mone);
+    fn.do_return (builder, val);
+  }
+  unary_ops[octave_value::op_uminus].add_overload (fn);
+
+  fn = create_identity (single);
+  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;
@@ -1769,6 +1911,7 @@
 
   casts[any->type_id ()].stash_name ("(any)");
   casts[scalar->type_id ()].stash_name ("(scalar)");
+  casts[single->type_id ()].stash_name ("(single)");
   casts[complex->type_id ()].stash_name ("(complex)");
   casts[matrix->type_id ()].stash_name ("(matrix)");
   casts[range->type_id ()].stash_name ("(range)");
@@ -1797,6 +1940,14 @@
   fn = create_external (JIT_FN (octave_jit_cast_scalar_any), scalar, any);
   casts[scalar->type_id ()].add_overload (fn);
 
+  // cast any <- single
+  fn = create_external (JIT_FN (octave_jit_cast_any_single), any, single);
+  casts[any->type_id ()].add_overload (fn);
+
+  // cast single <- any
+  fn = create_external (JIT_FN (octave_jit_cast_single_any), single, any);
+  casts[single->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);
@@ -1830,6 +1981,10 @@
   fn = create_identity (scalar);
   casts[scalar->type_id ()].add_overload (fn);
 
+  // cast single <- single
+  fn = create_identity (single);
+  casts[single->type_id ()].add_overload (fn);
+
   // cast complex <- complex
   fn = create_identity (complex);
   casts[complex->type_id ()].add_overload (fn);
@@ -2263,6 +2418,12 @@
         return get_matrix ();
     }
 
+  if (ov.is_single_type () && ! ov.is_complex_type ())
+    {
+      if (ov.is_real_scalar ())
+        return get_single ();
+    }
+
   if (ov.is_complex_scalar ())
     {
       Complex cv = ov.complex_value ();
--- a/libinterp/corefcn/jit-typeinfo.h	Fri Sep 27 17:21:33 2013 +0800
+++ b/libinterp/corefcn/jit-typeinfo.h	Thu Sep 26 19:14:08 2013 +0800
@@ -460,6 +460,8 @@
   static llvm::Type *get_scalar_llvm (void)
   { return instance->scalar->to_llvm (); }
 
+  static jit_type *get_single (void) { return instance->single; }
+
   static jit_type *get_scalar_ptr (void) { return instance->scalar_ptr; }
 
   static jit_type *get_any_ptr (void) { return instance->any_ptr; }
@@ -809,6 +811,7 @@
   jit_type *any;
   jit_type *matrix;
   jit_type *scalar;
+  jit_type *single;
   jit_type *scalar_ptr; // a fake type for interfacing with C++
   jit_type *any_ptr; // a fake type for interfacing with C++
   jit_type *range;