# HG changeset patch # User LYH # Date 1380194048 -28800 # Node ID bb937947ceb3a69b43c2ff7494891034e510f565 # Parent 6b2cee8c110e61b142d40141fb30759af5ad8677 single support diff -r 6b2cee8c110e -r bb937947ceb3 libinterp/corefcn/jit-typeinfo.cc --- 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 (); diff -r 6b2cee8c110e -r bb937947ceb3 libinterp/corefcn/jit-typeinfo.h --- 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;