# HG changeset patch # User LYH # Date 1395428379 14400 # Node ID f080e93de0bab3155182b7bb2a4a8e9f8af6d701 # Parent e315eef4d1e12df75fe95b64ebe3d7b2c91fd52a Fully uint16 type support diff -r e315eef4d1e1 -r f080e93de0ba libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc Fri Mar 21 14:59:39 2014 -0400 +++ b/libinterp/corefcn/jit-typeinfo.cc Fri Mar 21 14:59:39 2014 -0400 @@ -509,6 +509,12 @@ 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) { @@ -519,11 +525,37 @@ } 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) { @@ -719,6 +751,10 @@ jit_function::call (llvm::IRBuilderD& builder, const std::vector& in_args) const { + // FIXME: Unhandled case: + // function ret = lt(x, y) + // ret = x < y; + // endfunction if (! valid ()) throw jit_fail_exception ("Call not implemented"); @@ -1145,6 +1181,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 (); @@ -1493,7 +1530,7 @@ 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_scalar_scalar", single, single, single); + fn = create_internal ("octave_jit_div_single_single", single, single, single); fn.mark_can_error (); body = fn.new_block (); @@ -1581,14 +1618,80 @@ 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;