changeset 17499:7c14949789ab

Fully single type support & clean the code
author LYH <lyh.kernel@gmail.com>
date Thu, 26 Sep 2013 04:37:36 +0800
parents a0014fa5cf63
children e8d3d5a5a867
files libinterp/corefcn/jit-typeinfo.cc
diffstat 1 files changed, 146 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc
+++ b/libinterp/corefcn/jit-typeinfo.cc
@@ -474,6 +474,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)
 {
@@ -1300,6 +1319,12 @@
   destroy_fn.add_overload (create_identity(index));
   destroy_fn.add_overload (create_identity(complex));
 
+  /************************************************************
+   *
+   * scalar related operations
+   *
+   ************************************************************/
+
   // now for binary scalar operations
   add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
   add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
@@ -1316,26 +1341,6 @@
   jit_function gripe_div0 = create_external (JIT_FN (gripe_divide_by_zero), 0);
   gripe_div0.mark_can_error ();
 
-  // 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);
-
-  // 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);
-
-  add_binary_icmp (uintN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ);
-
   // divide is annoying because it might error
   fn = create_internal ("octave_jit_div_scalar_scalar", scalar, scalar, scalar);
   fn.mark_can_error ();
@@ -1414,49 +1419,11 @@
   unary_ops[octave_value::op_transpose].add_overload (fn);
   unary_ops[octave_value::op_hermitian].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);
-  }
-
-  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);
-
-  // 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);
+  /************************************************************
+   *
+   * complex related operations
+   *
+   ************************************************************/
 
   // now for binary complex operations
   fn = create_internal ("octave_jit_+_complex_complex", complex, complex,
@@ -1505,6 +1472,122 @@
   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_scalar_scalar", 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);
+
+  /************************************************************
+   *
+   * 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);
+
+  add_binary_icmp (uintN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ);
+
+  // 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_internal ("octave_jit_*_scalar_complex", complex, scalar,
                         complex);
   jit_function mul_scalar_complex = fn;