# HG changeset patch # User LYH # Date 1380226739 -28800 # Node ID 1a82df63d65eb2eb66e799fe61d5bd9e11820394 # Parent 1867774aaa2e775eb068d456a2e1f710766fab12 Fully int16 type support *** Fix int16 type comments diff -r 1867774aaa2e -r 1a82df63d65e libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc Sat Nov 02 17:14:07 2013 +0100 +++ b/libinterp/corefcn/jit-typeinfo.cc Fri Sep 27 04:18:59 2013 +0800 @@ -70,6 +70,7 @@ #include "ov-scalar.h" #include "ov-float.h" #include "ov-int8.h" +#include "ov-int16.h" #include "ov-int64.h" #include "ov-uint16.h" #include "pager.h" @@ -224,6 +225,20 @@ return new octave_int8_scalar (value); } +extern "C" int16_t +octave_jit_cast_int16_any (octave_base_value *obv) +{ + int16_t ret = obv->int16_scalar_value (); + obv->release (); + return ret; +} + +extern "C" octave_base_value * +octave_jit_cast_any_int16 (int16_t value) +{ + return new octave_int16_scalar (value); +} + extern "C" int64_t octave_jit_cast_int64_any (octave_base_value *obv) { @@ -612,6 +627,75 @@ /************************************************************ * + * int16 related external helper function + * + ************************************************************/ + +extern "C" int16_t +octave_jit_add_int16_int16 (int16_t lhs, int16_t rhs) +{ + uint16_t ulhs = lhs; + uint16_t urhs = rhs; + uint16_t res = ulhs + urhs; + + /* Calculate overflowed result. (Don't change the sign bit of ux) */ + ulhs = (ulhs >> 15) + SHRT_MAX; + + /* Force compiler to use cmovns instruction */ + if ((int16_t) ((ulhs ^ urhs) | ~(urhs ^ res)) >= 0) + { + res = ulhs; + } + + return res; +} + +extern "C" int16_t +octave_jit_sub_int16_int16 (int16_t lhs, int16_t rhs) +{ + uint16_t ulhs = lhs; + uint16_t urhs = rhs; + uint16_t res = ulhs - urhs; + + ulhs = (ulhs >> 15) + SHRT_MAX; + + /* Force compiler to use cmovns instruction */ + if ((int16_t)((ulhs ^ urhs) & (ulhs ^ res)) < 0) + { + res = ulhs; + } + + return res; +} + +extern "C" int16_t +octave_jit_mul_int16_int16 (int16_t lhs, int16_t rhs) +{ + int32_t res = (int32_t) lhs * (int32_t) rhs; + uint16_t res2 = ((uint16_t) (lhs ^ rhs) >> 15) + SHRT_MAX; + + int16_t hi = (res >> 16); + int16_t lo = res; + + if (hi != (lo >> 15)) res = res2; + + return res; +} + +extern "C" int16_t +octave_jit_incr_int16 (int16_t val) +{ + return octave_jit_add_int16_int16 (val, 1); +} + +extern "C" int16_t +octave_jit_decr_int16 (int16_t val) +{ + return octave_jit_sub_int16_int16 (val, 1); +} + +/************************************************************ + * * int64 related external helper function * ************************************************************/ @@ -1366,6 +1450,7 @@ llvm::Type *scalar_t = llvm::Type::getDoubleTy (context); llvm::Type *single_t = llvm::Type::getFloatTy (context); llvm::Type *int8__t = llvm::Type::getIntNTy (context, 8); + llvm::Type *int16__t = llvm::Type::getIntNTy (context, 16); llvm::Type *int64__t = llvm::Type::getIntNTy (context, 64); llvm::Type *uint16__t = llvm::Type::getIntNTy (context, 16); llvm::Type *bool_t = llvm::Type::getInt1Ty (context); @@ -1517,6 +1602,7 @@ grab_fn.add_overload (create_identity (scalar)); grab_fn.add_overload (create_identity (single)); grab_fn.add_overload (create_identity (intN (8))); + grab_fn.add_overload (create_identity (intN (16))); grab_fn.add_overload (create_identity (intN (64))); grab_fn.add_overload (create_identity (uintN (16))); grab_fn.add_overload (create_identity (scalar_ptr)); @@ -1540,6 +1626,7 @@ destroy_fn.add_overload (create_identity(scalar)); destroy_fn.add_overload (create_identity(single)); destroy_fn.add_overload (create_identity(intN (8))); + destroy_fn.add_overload (create_identity(intN (16))); destroy_fn.add_overload (create_identity(intN (64))); destroy_fn.add_overload (create_identity(uintN (16))); destroy_fn.add_overload (create_identity(boolean)); @@ -1851,11 +1938,66 @@ /************************************************************ * + * int16 related operations + * + ************************************************************/ + + // now for binary int16 operations + fn = create_external (JIT_FN (octave_jit_add_int16_int16), intN (16), intN (16), + intN (16)); + binary_ops[octave_value::op_add].add_overload (fn); + fn = create_external (JIT_FN (octave_jit_sub_int16_int16), intN (16), intN (16), + intN (16)); + binary_ops[octave_value::op_sub].add_overload (fn); + fn = create_external (JIT_FN (octave_jit_mul_int16_int16), intN (16), intN (16), + intN (16)); + binary_ops[octave_value::op_mul].add_overload (fn); + binary_ops[octave_value::op_el_mul].add_overload (fn); + + add_binary_icmp (intN (16), octave_value::op_lt, llvm::CmpInst::ICMP_SLT); + add_binary_icmp (intN (16), octave_value::op_le, llvm::CmpInst::ICMP_SLE); + add_binary_icmp (intN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ); + add_binary_icmp (intN (16), octave_value::op_ge, llvm::CmpInst::ICMP_SGE); + add_binary_icmp (intN (16), octave_value::op_gt, llvm::CmpInst::ICMP_SGT); + add_binary_icmp (intN (16), octave_value::op_ne, llvm::CmpInst::ICMP_NE); + + // FIXME: saturation divide definition? interpreter convert int to double, calculate and round. + // divide is annoying because it might error + // FIXME: Implement div + + // FIXME: Implement pow + + // now for unary int16 operations + // FIXME: Impelment not + fn = create_external (JIT_FN (octave_jit_incr_int16), intN (16), intN (16)); + unary_ops[octave_value::op_incr].add_overload (fn); + + fn = create_external (JIT_FN (octave_jit_decr_int16), intN (16), intN (16)); + unary_ops[octave_value::op_decr].add_overload (fn); + + fn = create_internal ("octave_jit_uminus", intN (16), intN (16)); + body = fn.new_block (); + builder.SetInsertPoint (body); + { + llvm::Value *mone = llvm::ConstantInt::get (int16__t, -1); + llvm::Value *val = fn.argument (builder, 0); + val = builder.CreateMul (val, mone); + fn.do_return (builder, val); + } + unary_ops[octave_value::op_uminus].add_overload (fn); + + fn = create_identity (intN (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); + + /************************************************************ + * * int64 related operations * ************************************************************/ - // FIXME: overflow occurs at minus + minus, minus - plus + // FIXME: interpreter overflow occurs at minus + minus, minus - plus // now for binary int64 operations fn = create_external (JIT_FN (octave_jit_add_int64_int64), intN (64), intN (64), intN (64)); @@ -1881,7 +2023,7 @@ // FIXME: Implement pow - // now for unary int8 operations + // now for unary int64 operations // FIXME: Impelment not fn = create_external (JIT_FN (octave_jit_incr_int64), intN (64), intN (64)); unary_ops[octave_value::op_incr].add_overload (fn); @@ -2367,6 +2509,7 @@ casts[scalar->type_id ()].stash_name ("(scalar)"); casts[single->type_id ()].stash_name ("(single)"); casts[intN (8)->type_id ()].stash_name ("(int8)"); + casts[intN (16)->type_id ()].stash_name ("(int16)"); casts[intN (64)->type_id ()].stash_name ("(int64)"); casts[uintN (16)->type_id ()].stash_name ("(uint16)"); casts[complex->type_id ()].stash_name ("(complex)"); @@ -2413,6 +2556,14 @@ fn = create_external (JIT_FN (octave_jit_cast_int8_any), intN (8), any); casts[intN (8)->type_id ()].add_overload (fn); + // cast any <- int16 + fn = create_external (JIT_FN (octave_jit_cast_any_int16), any, intN (16)); + casts[any->type_id ()].add_overload (fn); + + // cast int16 <- any + fn = create_external (JIT_FN (octave_jit_cast_int16_any), intN (16), any); + casts[intN (16)->type_id ()].add_overload (fn); + // cast any <- int64 fn = create_external (JIT_FN (octave_jit_cast_any_int64), any, intN (64)); casts[any->type_id ()].add_overload (fn); @@ -2470,6 +2621,10 @@ fn = create_identity (intN (8)); casts[intN (8)->type_id ()].add_overload (fn); + // cast int16 <- int16 + fn = create_identity (intN (16)); + casts[intN (16)->type_id ()].add_overload (fn); + // cast int64 <- int64 fn = create_identity (intN (64)); casts[intN (64)->type_id ()].add_overload (fn); @@ -2941,6 +3096,11 @@ return intN (8); } + if (ov.is_int16_type()) + { + return intN (16); + } + if (ov.is_int64_type()) { return intN (64);