changeset 15147:709e8928e68c

Scalar unary operation support in JIT * jit-typeinfo.cc (jit_typeinfo::jit_typeinfo): Add scalar unary operations. * jit-typeinfo.h (jit_typeinfo::unary_op, jit_typeinfo::do_unary_op): New function. * pt-jit.cc (jit_convert::visit_postfix_expression, jit_convert::visit_prefix_expression): Impelment. (jit_convert::visit): Protect result.
author Max Brister <max@2bass.com>
date Fri, 10 Aug 2012 15:05:29 -0500
parents 142e377e7e28
children 98a65d9e426f
files src/interp-core/jit-typeinfo.cc src/interp-core/jit-typeinfo.h src/interp-core/pt-jit.cc
diffstat 3 files changed, 96 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/interp-core/jit-typeinfo.cc
+++ b/src/interp-core/jit-typeinfo.cc
@@ -1106,6 +1106,14 @@
       binary_ops[i].stash_name ("binary" + op_name);
     }
 
+  unary_ops.resize (octave_value::num_unary_ops);
+  for (size_t i = 0; i < octave_value::num_unary_ops; ++i)
+    {
+      octave_value::unary_op op = static_cast<octave_value::unary_op> (i);
+      std::string op_name = octave_value::unary_op_as_string (op);
+      unary_ops[i].stash_name ("unary" + op_name);
+    }
+
   for (int op = 0; op < octave_value::num_binary_ops; ++op)
     {
       llvm::Twine fn_name ("octave_jit_binary_any_any_");
@@ -1164,7 +1172,6 @@
   release_fn.add_overload (fn);
 
   // now for binary scalar operations
-  // FIXME: Finish all operations
   add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
   add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
   add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul);
@@ -1224,6 +1231,48 @@
   binary_ops[octave_value::op_pow].add_overload (fn);
   binary_ops[octave_value::op_el_pow].add_overload (fn);
 
+  // now for unary scalar operations
+  // FIXME: Impelment not
+  fn = create_function (jit_convention::internal, "octave_jit_++", scalar,
+                        scalar);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *one = llvm::ConstantFP::get (scalar_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_function (jit_convention::internal, "octave_jit_--", scalar,
+                        scalar);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *one = llvm::ConstantFP::get (scalar_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_function (jit_convention::internal, "octave_jit_uminus", scalar,
+                        scalar);
+  body = fn.new_block ();
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *mone = llvm::ConstantFP::get (scalar_t, -1);
+    llvm::Value *val = fn.argument (builder, 0);
+    val = builder.CreateFMul (val, mone);
+    fn.do_return (builder, val);
+  }
+
+  fn = create_identity (scalar);
+  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);
+
   // now for binary complex operations
   add_binary_op (complex, octave_value::op_add, llvm::Instruction::FAdd);
   add_binary_op (complex, octave_value::op_sub, llvm::Instruction::FSub);
--- a/src/interp-core/jit-typeinfo.h
+++ b/src/interp-core/jit-typeinfo.h
@@ -476,6 +476,11 @@
     return instance->do_binary_op (op);
   }
 
+  static const jit_operation& unary_op (int op)
+  {
+    return instance->do_unary_op (op);
+  }
+
   static const jit_operation& grab (void) { return instance->grab_fn; }
 
   static const jit_function& get_grab (jit_type *type)
@@ -607,6 +612,12 @@
     return binary_ops[op];
   }
 
+  const jit_operation& do_unary_op (int op) const
+  {
+    assert (static_cast<size_t> (op) < unary_ops.size ());
+    return unary_ops[op];
+  }
+
   const jit_operation& do_cast (jit_type *to)
   {
     static jit_operation null_function;
@@ -737,6 +748,7 @@
   llvm::StructType *complex_ret;
 
   std::vector<jit_operation> binary_ops;
+  std::vector<jit_operation> unary_ops;
   jit_operation grab_fn;
   jit_operation release_fn;
   jit_operation print_fn;
--- a/src/interp-core/pt-jit.cc
+++ b/src/interp-core/pt-jit.cc
@@ -581,15 +581,33 @@
 }
 
 void
-jit_convert::visit_postfix_expression (tree_postfix_expression&)
+jit_convert::visit_postfix_expression (tree_postfix_expression& tpe)
 {
-  throw jit_fail_exception ();
+  octave_value::unary_op etype = tpe.op_type ();
+  tree_expression *operand = tpe.operand ();
+  jit_value *operandv = visit (operand);
+
+  const jit_operation& fn = jit_typeinfo::unary_op (etype);
+  result = create_checked (fn, operandv);
+
+  if (etype == octave_value::op_incr || etype == octave_value::op_decr)
+    {
+      // FIXME: Somehow copy operandv
+      // do_assign (operand, operandv);
+      throw jit_fail_exception ("Postfix ++ and -- not yet supported");
+    }
 }
 
 void
-jit_convert::visit_prefix_expression (tree_prefix_expression&)
+jit_convert::visit_prefix_expression (tree_prefix_expression& tpe)
 {
-  throw jit_fail_exception ();
+  octave_value::unary_op etype = tpe.op_type ();
+  tree_expression *operand = tpe.operand ();
+  const jit_operation& fn = jit_typeinfo::unary_op (etype);
+  result = create_checked (fn, visit (operand));
+
+  if (etype == octave_value::op_incr || etype == octave_value::op_decr)
+    do_assign (operand, result);
 }
 
 void
@@ -905,12 +923,11 @@
 jit_value *
 jit_convert::visit (tree& tee)
 {
-  result = 0;
-  tee.accept (*this);
+  unwind_protect prot;
+  prot.protect_var (result);
 
-  jit_value *ret = result;
-  result = 0;
-  return ret;
+  tee.accept (*this);
+  return result;
 }
 
 void
@@ -1963,4 +1980,12 @@
 %! endwhile
 %! assert (i == 10);
 
+%!test
+%! i = 0;
+%! while i < 10
+%!   a = ++i;
+%! endwhile
+%! assert (i == 10);
+%! assert (a == 10);
+
 */