Mercurial > octave-nkf
changeset 18562:2204a9a252c0 draft
jit compiler: Add support for uint64 type
* libinter/corefcn/pt-jit.cc: Add basic operations, casts and overloads
author | LYH <lyh.kernel@gmail.com> |
---|---|
date | Sat, 02 Nov 2013 17:14:07 +0100 |
parents | 7a6da3d7e3f9 |
children | d464edd2552b |
files | libinterp/corefcn/jit-typeinfo.cc |
diffstat | 1 files changed, 148 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc Fri Sep 27 05:44:07 2013 +0800 +++ b/libinterp/corefcn/jit-typeinfo.cc Sat Nov 02 17:14:07 2013 +0100 @@ -75,6 +75,7 @@ #include "ov-int64.h" #include "ov-uint8.h" #include "ov-uint16.h" +#include "ov-uint64.h" #include "pager.h" static llvm::LLVMContext& context = llvm::getGlobalContext (); @@ -297,6 +298,20 @@ return new octave_uint16_scalar (value); } +extern "C" uint64_t +octave_jit_cast_uint64_any (octave_base_value *obv) +{ + uint64_t ret = obv->uint64_scalar_value (); + obv->release (); + return ret; +} + +extern "C" octave_base_value * +octave_jit_cast_any_uint64 (uint64_t value) +{ + return new octave_uint64_scalar (value); +} + extern "C" Complex octave_jit_cast_complex_any (octave_base_value *obv) { @@ -970,6 +985,63 @@ return octave_jit_sub_uint16_uint16 (val, 1); } +/************************************************************ + * + * uint64 related external helper function + * + ************************************************************/ + +extern "C" uint64_t +octave_jit_add_uint64_uint64 (uint64_t lhs, uint64_t rhs) +{ + uint64_t res = lhs + rhs; + res |= -(res < lhs); + + return res; +} + +extern "C" uint64_t +octave_jit_sub_uint64_uint64 (uint64_t lhs, uint64_t rhs) +{ + uint64_t res = lhs - rhs; + res &= -(res <= lhs); + + return res; +} + +extern "C" uint64_t +octave_jit_mul_uint64_uint64 (uint64_t lhs, uint64_t rhs) +{ +#ifdef OCTAVE_INT_USE_LONG_DOUBLE + long double p = static_cast<long double> (lhs) * static_cast<long double> (rhs); + if (p > static_cast<long double> (std::numeric_limits<uint64_t>::max ())) + { + return std::numeric_limits<uint64_t>::max (); + } + else + return static_cast<uint64_t> (p); +#else + __uint128_t res = (__uint128_t) lhs * (__uint128_t) rhs; + + uint64_t hi = res >> 64; + uint64_t lo = res; + + return lo | -!!hi; +#endif +} + +extern "C" uint64_t +octave_jit_incr_uint64 (uint64_t val) +{ + return octave_jit_add_uint64_uint64 (val, 1); +} + +extern "C" uint64_t +octave_jit_decr_uint64 (uint64_t val) +{ + return octave_jit_sub_uint64_uint64 (val, 1); +} + extern "C" void octave_jit_print_matrix (jit_matrix *m) { @@ -1601,6 +1673,7 @@ llvm::Type *int64__t = llvm::Type::getIntNTy (context, 64); llvm::Type *uint8__t = llvm::Type::getIntNTy (context, 8); llvm::Type *uint16__t = llvm::Type::getIntNTy (context, 16); + llvm::Type *uint64__t = llvm::Type::getIntNTy (context, 64); llvm::Type *bool_t = llvm::Type::getInt1Ty (context); llvm::Type *string_t = llvm::Type::getInt8Ty (context); string_t = string_t->getPointerTo (); @@ -1656,6 +1729,7 @@ create_uint (8); create_uint (16); + create_uint (64); casts.resize (next_id + 1); identities.resize (next_id + 1); @@ -1756,6 +1830,7 @@ grab_fn.add_overload (create_identity (intN (64))); grab_fn.add_overload (create_identity (uintN (8))); grab_fn.add_overload (create_identity (uintN (16))); + grab_fn.add_overload (create_identity (uintN (64))); grab_fn.add_overload (create_identity (scalar_ptr)); grab_fn.add_overload (create_identity (any_ptr)); grab_fn.add_overload (create_identity (boolean)); @@ -1782,6 +1857,7 @@ destroy_fn.add_overload (create_identity(intN (64))); destroy_fn.add_overload (create_identity(uintN (8))); destroy_fn.add_overload (create_identity(uintN (16))); + destroy_fn.add_overload (create_identity(uintN (64))); destroy_fn.add_overload (create_identity(boolean)); destroy_fn.add_overload (create_identity(index)); destroy_fn.add_overload (create_identity(complex)); @@ -2394,6 +2470,60 @@ unary_ops[octave_value::op_transpose].add_overload (fn); unary_ops[octave_value::op_hermitian].add_overload (fn); + /************************************************************ + * + * uint64 related operations + * + ************************************************************/ + + // now for binary uint64 operations + fn = create_external (JIT_FN (octave_jit_add_uint64_uint64), uintN (64), uintN (64), + uintN (64)); + binary_ops[octave_value::op_add].add_overload (fn); + fn = create_external (JIT_FN (octave_jit_sub_uint64_uint64), uintN (64), uintN (64), + uintN (64)); + binary_ops[octave_value::op_sub].add_overload (fn); + fn = create_external (JIT_FN (octave_jit_mul_uint64_uint64), uintN (64), uintN (64), + uintN (64)); + binary_ops[octave_value::op_mul].add_overload (fn); + binary_ops[octave_value::op_el_mul].add_overload (fn); + + add_binary_icmp (uintN (64), octave_value::op_lt, llvm::CmpInst::ICMP_ULT); + add_binary_icmp (uintN (64), octave_value::op_le, llvm::CmpInst::ICMP_ULE); + add_binary_icmp (uintN (64), octave_value::op_eq, llvm::CmpInst::ICMP_EQ); + add_binary_icmp (uintN (64), octave_value::op_ge, llvm::CmpInst::ICMP_UGE); + add_binary_icmp (uintN (64), octave_value::op_gt, llvm::CmpInst::ICMP_UGT); + add_binary_icmp (uintN (64), octave_value::op_ne, llvm::CmpInst::ICMP_NE); + + // FIXME: saturation divide definition? interpreter convert uint to double, calculate and round. + // divide is annoying because it might error + // FIXME: Implement div + + // FIXME: Implement pow + + // now for unary uint8 operations + // FIXME: Impelment not + fn = create_external (JIT_FN (octave_jit_incr_uint64), uintN (64), uintN (64)); + unary_ops[octave_value::op_incr].add_overload (fn); + + fn = create_external (JIT_FN (octave_jit_decr_uint64), uintN (64), uintN (64)); + unary_ops[octave_value::op_decr].add_overload (fn); + + fn = create_internal ("octave_jit_uminus", uintN (64), uintN (64)); + body = fn.new_block (); + builder.SetInsertPoint (body); + { + llvm::Value *zero = llvm::ConstantInt::get (uint64__t, 0); + + fn.do_return (builder, zero); + } + unary_ops[octave_value::op_uminus].add_overload (fn); + + fn = create_identity (uintN (64)); + 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; @@ -2777,6 +2907,7 @@ casts[intN (64)->type_id ()].stash_name ("(int64)"); casts[uintN (8)->type_id ()].stash_name ("(uint8)"); casts[uintN (16)->type_id ()].stash_name ("(uint16)"); + casts[uintN (64)->type_id ()].stash_name ("(uint64)"); casts[complex->type_id ()].stash_name ("(complex)"); casts[matrix->type_id ()].stash_name ("(matrix)"); casts[range->type_id ()].stash_name ("(range)"); @@ -2861,6 +2992,14 @@ fn = create_external (JIT_FN (octave_jit_cast_uint16_any), uintN (16), any); casts[uintN (16)->type_id ()].add_overload (fn); + // cast any <- uint64 + fn = create_external (JIT_FN (octave_jit_cast_any_uint64), any, uintN (64)); + casts[any->type_id ()].add_overload (fn); + + // cast uint64 <- any + fn = create_external (JIT_FN (octave_jit_cast_uint64_any), uintN (64), any); + casts[uintN (64)->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); @@ -2922,6 +3061,10 @@ fn = create_identity (uintN (16)); casts[uintN (16)->type_id ()].add_overload (fn); + // cast uint64 <- uint64 + fn = create_identity (uintN (64)); + casts[uintN (64)->type_id ()].add_overload (fn); + // cast complex <- complex fn = create_identity (complex); casts[complex->type_id ()].add_overload (fn); @@ -3410,6 +3553,11 @@ return uintN (16); } + if (ov.is_uint64_type()) + { + return uintN (64); + } + if (ov.is_complex_scalar ()) { Complex cv = ov.complex_value ();