Mercurial > hg > octave-nkf
changeset 18623:5b49430a5b30 draft
Fully uint16 type support
author | LYH <lyh.kernel@gmail.com> |
---|---|
date | Thu, 26 Sep 2013 19:14:08 +0800 |
parents | bb937947ceb3 |
children | 4d285a169b29 |
files | libinterp/corefcn/jit-typeinfo.cc libinterp/corefcn/jit-typeinfo.h |
diffstat | 2 files changed, 193 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/jit-typeinfo.cc +++ b/libinterp/corefcn/jit-typeinfo.cc @@ -69,6 +69,7 @@ #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 (); @@ -207,6 +208,20 @@ 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) { @@ -496,6 +511,53 @@ return std::pow (lhs, rhs); } +/************************************************************ + * + * uint16 related external helper function + * + ************************************************************/ + +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_sub_uint16_uint16 (uint16_t lhs, uint16_t rhs) +{ + uint16_t res = lhs - rhs; + res &= -(res <= lhs); + + return res; +} + +extern "C" uint16_t +octave_jit_mul_uint16_uint16 (uint16_t lhs, uint16_t rhs) +{ + uint32_t res = (uint32_t) lhs * (uint32_t) rhs; + + uint16_t hi = res >> 16; + uint16_t lo = res; + + return lo | -!!hi; +} + +extern "C" uint16_t +octave_jit_incr_uint16 (uint16_t val) +{ + return octave_jit_add_uint16_uint16 (val, 1); +} + +extern "C" uint16_t +octave_jit_decr_uint16 (uint16_t val) +{ + return octave_jit_sub_uint16_uint16 (val, 1); +} + extern "C" void octave_jit_print_matrix (jit_matrix *m) { @@ -1117,6 +1179,7 @@ llvm::Type *scalar_t = llvm::Type::getDoubleTy (context); llvm::Type *single_t = llvm::Type::getFloatTy (context); + llvm::Type *uint16__t = llvm::Type::getIntNTy (context, 16); llvm::Type *bool_t = llvm::Type::getInt1Ty (context); llvm::Type *string_t = llvm::Type::getInt8Ty (context); string_t = string_t->getPointerTo (); @@ -1170,6 +1233,8 @@ create_int (32); create_int (64); + create_uint (16); + casts.resize (next_id + 1); identities.resize (next_id + 1); @@ -1263,6 +1328,7 @@ 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)); @@ -1283,6 +1349,7 @@ 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)); @@ -1535,6 +1602,90 @@ 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); + fn = create_external (JIT_FN (octave_jit_sub_uint16_uint16), uintN (16), uintN (16), + uintN (16)); + binary_ops[octave_value::op_sub].add_overload (fn); + fn = create_external (JIT_FN (octave_jit_mul_uint16_uint16), uintN (16), uintN (16), + uintN (16)); + binary_ops[octave_value::op_mul].add_overload (fn); + binary_ops[octave_value::op_el_mul].add_overload (fn); + + add_binary_icmp (uintN (16), octave_value::op_lt, llvm::CmpInst::ICMP_ULT); + add_binary_icmp (uintN (16), octave_value::op_le, llvm::CmpInst::ICMP_ULE); + add_binary_icmp (uintN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ); + add_binary_icmp (uintN (16), octave_value::op_ge, llvm::CmpInst::ICMP_UGE); + add_binary_icmp (uintN (16), octave_value::op_gt, llvm::CmpInst::ICMP_UGT); + add_binary_icmp (uintN (16), 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 +#if 0 + fn = create_internal ("octave_jit_div_uint16_uint16", uintN (16), uintN (16), uintN (16)); + 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::ConstantInt::get (uint16__t, 0); + llvm::Value *check = builder.CreateICmpEQ (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.CreateUDiv (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); +#endif + + // FIXME: Implement pow + + // 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_external (JIT_FN (octave_jit_decr_uint16), uintN (16), uintN (16)); + unary_ops[octave_value::op_decr].add_overload (fn); + + fn = create_internal ("octave_jit_uminus", uintN (16), uintN (16)); + body = fn.new_block (); + builder.SetInsertPoint (body); + { + llvm::Value *zero = llvm::ConstantInt::get (uint16__t, 0); + + fn.do_return (builder, zero); + } + unary_ops[octave_value::op_uminus].add_overload (fn); + + fn = create_identity (uintN (16)); + 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; @@ -1912,6 +2063,7 @@ 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)"); @@ -1948,6 +2100,14 @@ 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); @@ -1985,6 +2145,10 @@ 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); @@ -2383,6 +2547,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 { @@ -2394,6 +2567,16 @@ } jit_type * +jit_typeinfo::uintN (size_t nbits) const +{ + std::map<size_t, jit_type *>::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 ()) @@ -2424,6 +2607,11 @@ return get_single (); } + if (ov.is_uint16_type()) + { + return uintN (16); + } + if (ov.is_complex_scalar ()) { Complex cv = ov.complex_value ();
--- a/libinterp/corefcn/jit-typeinfo.h +++ b/libinterp/corefcn/jit-typeinfo.h @@ -794,8 +794,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; @@ -821,6 +825,7 @@ jit_type *complex; jit_type *unknown_function; std::map<size_t, jit_type *> ints; + std::map<size_t, jit_type *> uints; std::map<std::string, jit_type *> builtins; llvm::StructType *complex_ret;