# HG changeset patch # User LYH # Date 1395428378 14400 # Node ID c31fe3239c8b391ef5cc6ead76489ab4db229a29 # Parent f3314c4b9266520e73338cde5b096082893f46df partial support of single/uint16 diff -r f3314c4b9266 -r c31fe3239c8b libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc Fri Mar 21 14:59:38 2014 -0400 +++ b/libinterp/corefcn/jit-typeinfo.cc Fri Mar 21 14:59:38 2014 -0400 @@ -66,6 +66,8 @@ #include "ov-builtin.h" #include "ov-complex.h" #include "ov-scalar.h" +#include "ov-float.h" +#include "ov-uint16.h" #include "pager.h" static llvm::LLVMContext& context = llvm::getGlobalContext (); @@ -190,6 +192,34 @@ 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" uint16_t +octave_jit_cast_uint16_any (octave_base_value *obv) +{ + uint16_t ret = obv->uint16_scalar_value (); + obv->release (); + return ret; +} + +extern "C" octave_base_value * +octave_jit_cast_any_uint16 (uint16_t value) +{ + return new octave_uint16_scalar (value); +} + extern "C" Complex octave_jit_cast_complex_any (octave_base_value *obv) { @@ -460,6 +490,21 @@ return std::pow (lhs, rhs); } +extern "C" uint16_t +octave_jit_add_uint16_uint16 (uint16_t lhs, uint16_t rhs) +{ + uint16_t res = lhs + rhs; + res |= -(res < lhs); + + return res; +} + +extern "C" uint16_t +octave_jit_incr_uint16 (uint16_t val) +{ + return octave_jit_add_uint16_uint16 (val, 1); +} + extern "C" void octave_jit_print_matrix (jit_matrix *m) { @@ -1080,6 +1125,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 (); @@ -1120,6 +1166,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); @@ -1132,6 +1179,8 @@ create_int (32); create_int (64); + create_uint (16); + casts.resize (next_id + 1); identities.resize (next_id + 1); @@ -1224,6 +1273,8 @@ 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 (uintN (16))); grab_fn.add_overload (create_identity (scalar_ptr)); grab_fn.add_overload (create_identity (any_ptr)); grab_fn.add_overload (create_identity (boolean)); @@ -1243,6 +1294,8 @@ 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(uintN (16))); destroy_fn.add_overload (create_identity(boolean)); destroy_fn.add_overload (create_identity(index)); destroy_fn.add_overload (create_identity(complex)); @@ -1263,6 +1316,26 @@ 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 (); @@ -1341,6 +1414,50 @@ 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); + // now for binary complex operations fn = create_internal ("octave_jit_+_complex_complex", complex, complex, complex); @@ -1767,6 +1884,8 @@ casts[any->type_id ()].stash_name ("(any)"); casts[scalar->type_id ()].stash_name ("(scalar)"); + casts[single->type_id ()].stash_name ("(single)"); + casts[uintN (16)->type_id ()].stash_name ("(uint16)"); casts[complex->type_id ()].stash_name ("(complex)"); casts[matrix->type_id ()].stash_name ("(matrix)"); casts[range->type_id ()].stash_name ("(range)"); @@ -1795,6 +1914,22 @@ 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 <- uint16 + fn = create_external (JIT_FN (octave_jit_cast_any_uint16), any, uintN (16)); + casts[any->type_id ()].add_overload (fn); + + // cast uint16 <- any + fn = create_external (JIT_FN (octave_jit_cast_uint16_any), uintN (16), any); + casts[uintN (16)->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); @@ -1828,6 +1963,14 @@ 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 uint16 <- uint16 + fn = create_identity (uintN (16)); + casts[uintN (16)->type_id ()].add_overload (fn); + // cast complex <- complex fn = create_identity (complex); casts[complex->type_id ()].add_overload (fn); @@ -2226,6 +2369,15 @@ nbits)); } +void +jit_typeinfo::create_uint (size_t nbits) +{ + std::stringstream tname; + tname << "uint" << nbits; + uints[nbits] = new_type (tname.str (), any, llvm::Type::getIntNTy (context, + nbits)); +} + jit_type * jit_typeinfo::intN (size_t nbits) const { @@ -2237,6 +2389,16 @@ } jit_type * +jit_typeinfo::uintN (size_t nbits) const +{ + std::map::const_iterator iter = uints.find (nbits); + if (iter != uints.end ()) + return iter->second; + + throw jit_fail_exception ("No such unsigned integer type"); +} + +jit_type * jit_typeinfo::do_type_of (const octave_value &ov) const { if (ov.is_function ()) @@ -2261,6 +2423,16 @@ return get_matrix (); } + if (ov.is_float_type ()) + { + return get_single (); + } + + if (ov.is_uint16_type()) + { + return uintN (16); + } + if (ov.is_complex_scalar ()) { Complex cv = ov.complex_value (); diff -r f3314c4b9266 -r c31fe3239c8b libinterp/corefcn/jit-typeinfo.h --- a/libinterp/corefcn/jit-typeinfo.h Fri Mar 21 14:59:38 2014 -0400 +++ b/libinterp/corefcn/jit-typeinfo.h Fri Mar 21 14:59:38 2014 -0400 @@ -458,6 +458,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; } @@ -790,8 +792,12 @@ void create_int (size_t nbits); + void create_uint (size_t nbits); + jit_type *intN (size_t nbits) const; + jit_type *uintN (size_t nbits) const; + static jit_typeinfo *instance; llvm::Module *module; @@ -807,6 +813,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; @@ -816,6 +823,7 @@ jit_type *complex; jit_type *unknown_function; std::map ints; + std::map uints; std::map builtins; llvm::StructType *complex_ret;