comparison libinterp/corefcn/jit-typeinfo.cc @ 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
comparison
equal deleted inserted replaced
18561:7a6da3d7e3f9 18562:2204a9a252c0
73 #include "ov-int16.h" 73 #include "ov-int16.h"
74 #include "ov-int32.h" 74 #include "ov-int32.h"
75 #include "ov-int64.h" 75 #include "ov-int64.h"
76 #include "ov-uint8.h" 76 #include "ov-uint8.h"
77 #include "ov-uint16.h" 77 #include "ov-uint16.h"
78 #include "ov-uint64.h"
78 #include "pager.h" 79 #include "pager.h"
79 80
80 static llvm::LLVMContext& context = llvm::getGlobalContext (); 81 static llvm::LLVMContext& context = llvm::getGlobalContext ();
81 82
82 jit_typeinfo *jit_typeinfo::instance = 0; 83 jit_typeinfo *jit_typeinfo::instance = 0;
293 294
294 extern "C" octave_base_value * 295 extern "C" octave_base_value *
295 octave_jit_cast_any_uint16 (uint16_t value) 296 octave_jit_cast_any_uint16 (uint16_t value)
296 { 297 {
297 return new octave_uint16_scalar (value); 298 return new octave_uint16_scalar (value);
299 }
300
301 extern "C" uint64_t
302 octave_jit_cast_uint64_any (octave_base_value *obv)
303 {
304 uint64_t ret = obv->uint64_scalar_value ();
305 obv->release ();
306 return ret;
307 }
308
309 extern "C" octave_base_value *
310 octave_jit_cast_any_uint64 (uint64_t value)
311 {
312 return new octave_uint64_scalar (value);
298 } 313 }
299 314
300 extern "C" Complex 315 extern "C" Complex
301 octave_jit_cast_complex_any (octave_base_value *obv) 316 octave_jit_cast_complex_any (octave_base_value *obv)
302 { 317 {
968 octave_jit_decr_uint16 (uint16_t val) 983 octave_jit_decr_uint16 (uint16_t val)
969 { 984 {
970 return octave_jit_sub_uint16_uint16 (val, 1); 985 return octave_jit_sub_uint16_uint16 (val, 1);
971 } 986 }
972 987
988 /************************************************************
989 *
990 * uint64 related external helper function
991 *
992 ************************************************************/
993
994 extern "C" uint64_t
995 octave_jit_add_uint64_uint64 (uint64_t lhs, uint64_t rhs)
996 {
997 uint64_t res = lhs + rhs;
998 res |= -(res < lhs);
999
1000 return res;
1001 }
1002
1003 extern "C" uint64_t
1004 octave_jit_sub_uint64_uint64 (uint64_t lhs, uint64_t rhs)
1005 {
1006 uint64_t res = lhs - rhs;
1007 res &= -(res <= lhs);
1008
1009 return res;
1010 }
1011
1012 extern "C" uint64_t
1013 octave_jit_mul_uint64_uint64 (uint64_t lhs, uint64_t rhs)
1014 {
1015 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
1016 long double p = static_cast<long double> (lhs) * static_cast<long double> (rhs);
1017 if (p > static_cast<long double> (std::numeric_limits<uint64_t>::max ()))
1018 {
1019 return std::numeric_limits<uint64_t>::max ();
1020 }
1021 else
1022 return static_cast<uint64_t> (p);
1023 #else
1024 __uint128_t res = (__uint128_t) lhs * (__uint128_t) rhs;
1025
1026 uint64_t hi = res >> 64;
1027 uint64_t lo = res;
1028
1029 return lo | -!!hi;
1030 #endif
1031 }
1032
1033 extern "C" uint64_t
1034 octave_jit_incr_uint64 (uint64_t val)
1035 {
1036 return octave_jit_add_uint64_uint64 (val, 1);
1037 }
1038
1039 extern "C" uint64_t
1040 octave_jit_decr_uint64 (uint64_t val)
1041 {
1042 return octave_jit_sub_uint64_uint64 (val, 1);
1043 }
1044
973 extern "C" void 1045 extern "C" void
974 octave_jit_print_matrix (jit_matrix *m) 1046 octave_jit_print_matrix (jit_matrix *m)
975 { 1047 {
976 std::cout << *m << std::endl; 1048 std::cout << *m << std::endl;
977 } 1049 }
1599 llvm::Type *int16__t = llvm::Type::getIntNTy (context, 16); 1671 llvm::Type *int16__t = llvm::Type::getIntNTy (context, 16);
1600 llvm::Type *int32__t = llvm::Type::getIntNTy (context, 32); 1672 llvm::Type *int32__t = llvm::Type::getIntNTy (context, 32);
1601 llvm::Type *int64__t = llvm::Type::getIntNTy (context, 64); 1673 llvm::Type *int64__t = llvm::Type::getIntNTy (context, 64);
1602 llvm::Type *uint8__t = llvm::Type::getIntNTy (context, 8); 1674 llvm::Type *uint8__t = llvm::Type::getIntNTy (context, 8);
1603 llvm::Type *uint16__t = llvm::Type::getIntNTy (context, 16); 1675 llvm::Type *uint16__t = llvm::Type::getIntNTy (context, 16);
1676 llvm::Type *uint64__t = llvm::Type::getIntNTy (context, 64);
1604 llvm::Type *bool_t = llvm::Type::getInt1Ty (context); 1677 llvm::Type *bool_t = llvm::Type::getInt1Ty (context);
1605 llvm::Type *string_t = llvm::Type::getInt8Ty (context); 1678 llvm::Type *string_t = llvm::Type::getInt8Ty (context);
1606 string_t = string_t->getPointerTo (); 1679 string_t = string_t->getPointerTo ();
1607 llvm::Type *index_t = llvm::Type::getIntNTy (context, 1680 llvm::Type *index_t = llvm::Type::getIntNTy (context,
1608 sizeof(octave_idx_type) * 8); 1681 sizeof(octave_idx_type) * 8);
1654 create_int (32); 1727 create_int (32);
1655 create_int (64); 1728 create_int (64);
1656 1729
1657 create_uint (8); 1730 create_uint (8);
1658 create_uint (16); 1731 create_uint (16);
1732 create_uint (64);
1659 1733
1660 casts.resize (next_id + 1); 1734 casts.resize (next_id + 1);
1661 identities.resize (next_id + 1); 1735 identities.resize (next_id + 1);
1662 1736
1663 // specify calling conventions 1737 // specify calling conventions
1754 grab_fn.add_overload (create_identity (intN (16))); 1828 grab_fn.add_overload (create_identity (intN (16)));
1755 grab_fn.add_overload (create_identity (intN (32))); 1829 grab_fn.add_overload (create_identity (intN (32)));
1756 grab_fn.add_overload (create_identity (intN (64))); 1830 grab_fn.add_overload (create_identity (intN (64)));
1757 grab_fn.add_overload (create_identity (uintN (8))); 1831 grab_fn.add_overload (create_identity (uintN (8)));
1758 grab_fn.add_overload (create_identity (uintN (16))); 1832 grab_fn.add_overload (create_identity (uintN (16)));
1833 grab_fn.add_overload (create_identity (uintN (64)));
1759 grab_fn.add_overload (create_identity (scalar_ptr)); 1834 grab_fn.add_overload (create_identity (scalar_ptr));
1760 grab_fn.add_overload (create_identity (any_ptr)); 1835 grab_fn.add_overload (create_identity (any_ptr));
1761 grab_fn.add_overload (create_identity (boolean)); 1836 grab_fn.add_overload (create_identity (boolean));
1762 grab_fn.add_overload (create_identity (complex)); 1837 grab_fn.add_overload (create_identity (complex));
1763 grab_fn.add_overload (create_identity (index)); 1838 grab_fn.add_overload (create_identity (index));
1780 destroy_fn.add_overload (create_identity(intN (16))); 1855 destroy_fn.add_overload (create_identity(intN (16)));
1781 destroy_fn.add_overload (create_identity(intN (32))); 1856 destroy_fn.add_overload (create_identity(intN (32)));
1782 destroy_fn.add_overload (create_identity(intN (64))); 1857 destroy_fn.add_overload (create_identity(intN (64)));
1783 destroy_fn.add_overload (create_identity(uintN (8))); 1858 destroy_fn.add_overload (create_identity(uintN (8)));
1784 destroy_fn.add_overload (create_identity(uintN (16))); 1859 destroy_fn.add_overload (create_identity(uintN (16)));
1860 destroy_fn.add_overload (create_identity(uintN (64)));
1785 destroy_fn.add_overload (create_identity(boolean)); 1861 destroy_fn.add_overload (create_identity(boolean));
1786 destroy_fn.add_overload (create_identity(index)); 1862 destroy_fn.add_overload (create_identity(index));
1787 destroy_fn.add_overload (create_identity(complex)); 1863 destroy_fn.add_overload (create_identity(complex));
1788 1864
1789 // -------------------- scalar related operations -------------------- 1865 // -------------------- scalar related operations --------------------
2392 fn = create_identity (uintN (16)); 2468 fn = create_identity (uintN (16));
2393 unary_ops[octave_value::op_uplus].add_overload (fn); 2469 unary_ops[octave_value::op_uplus].add_overload (fn);
2394 unary_ops[octave_value::op_transpose].add_overload (fn); 2470 unary_ops[octave_value::op_transpose].add_overload (fn);
2395 unary_ops[octave_value::op_hermitian].add_overload (fn); 2471 unary_ops[octave_value::op_hermitian].add_overload (fn);
2396 2472
2473 /************************************************************
2474 *
2475 * uint64 related operations
2476 *
2477 ************************************************************/
2478
2479 // now for binary uint64 operations
2480 fn = create_external (JIT_FN (octave_jit_add_uint64_uint64), uintN (64), uintN (64),
2481 uintN (64));
2482 binary_ops[octave_value::op_add].add_overload (fn);
2483 fn = create_external (JIT_FN (octave_jit_sub_uint64_uint64), uintN (64), uintN (64),
2484 uintN (64));
2485 binary_ops[octave_value::op_sub].add_overload (fn);
2486 fn = create_external (JIT_FN (octave_jit_mul_uint64_uint64), uintN (64), uintN (64),
2487 uintN (64));
2488 binary_ops[octave_value::op_mul].add_overload (fn);
2489 binary_ops[octave_value::op_el_mul].add_overload (fn);
2490
2491 add_binary_icmp (uintN (64), octave_value::op_lt, llvm::CmpInst::ICMP_ULT);
2492 add_binary_icmp (uintN (64), octave_value::op_le, llvm::CmpInst::ICMP_ULE);
2493 add_binary_icmp (uintN (64), octave_value::op_eq, llvm::CmpInst::ICMP_EQ);
2494 add_binary_icmp (uintN (64), octave_value::op_ge, llvm::CmpInst::ICMP_UGE);
2495 add_binary_icmp (uintN (64), octave_value::op_gt, llvm::CmpInst::ICMP_UGT);
2496 add_binary_icmp (uintN (64), octave_value::op_ne, llvm::CmpInst::ICMP_NE);
2497
2498 // FIXME: saturation divide definition? interpreter convert uint to double, calculate and round.
2499 // divide is annoying because it might error
2500 // FIXME: Implement div
2501
2502 // FIXME: Implement pow
2503
2504 // now for unary uint8 operations
2505 // FIXME: Impelment not
2506 fn = create_external (JIT_FN (octave_jit_incr_uint64), uintN (64), uintN (64));
2507 unary_ops[octave_value::op_incr].add_overload (fn);
2508
2509 fn = create_external (JIT_FN (octave_jit_decr_uint64), uintN (64), uintN (64));
2510 unary_ops[octave_value::op_decr].add_overload (fn);
2511
2512 fn = create_internal ("octave_jit_uminus", uintN (64), uintN (64));
2513 body = fn.new_block ();
2514 builder.SetInsertPoint (body);
2515 {
2516 llvm::Value *zero = llvm::ConstantInt::get (uint64__t, 0);
2517
2518 fn.do_return (builder, zero);
2519 }
2520 unary_ops[octave_value::op_uminus].add_overload (fn);
2521
2522 fn = create_identity (uintN (64));
2523 unary_ops[octave_value::op_uplus].add_overload (fn);
2524 unary_ops[octave_value::op_transpose].add_overload (fn);
2525 unary_ops[octave_value::op_hermitian].add_overload (fn);
2526
2397 fn = create_internal ("octave_jit_*_scalar_complex", complex, scalar, 2527 fn = create_internal ("octave_jit_*_scalar_complex", complex, scalar,
2398 complex); 2528 complex);
2399 jit_function mul_scalar_complex = fn; 2529 jit_function mul_scalar_complex = fn;
2400 body = fn.new_block (); 2530 body = fn.new_block ();
2401 builder.SetInsertPoint (body); 2531 builder.SetInsertPoint (body);
2775 casts[intN (16)->type_id ()].stash_name ("(int16)"); 2905 casts[intN (16)->type_id ()].stash_name ("(int16)");
2776 casts[intN (32)->type_id ()].stash_name ("(int32)"); 2906 casts[intN (32)->type_id ()].stash_name ("(int32)");
2777 casts[intN (64)->type_id ()].stash_name ("(int64)"); 2907 casts[intN (64)->type_id ()].stash_name ("(int64)");
2778 casts[uintN (8)->type_id ()].stash_name ("(uint8)"); 2908 casts[uintN (8)->type_id ()].stash_name ("(uint8)");
2779 casts[uintN (16)->type_id ()].stash_name ("(uint16)"); 2909 casts[uintN (16)->type_id ()].stash_name ("(uint16)");
2910 casts[uintN (64)->type_id ()].stash_name ("(uint64)");
2780 casts[complex->type_id ()].stash_name ("(complex)"); 2911 casts[complex->type_id ()].stash_name ("(complex)");
2781 casts[matrix->type_id ()].stash_name ("(matrix)"); 2912 casts[matrix->type_id ()].stash_name ("(matrix)");
2782 casts[range->type_id ()].stash_name ("(range)"); 2913 casts[range->type_id ()].stash_name ("(range)");
2783 2914
2784 // cast any <- matrix 2915 // cast any <- matrix
2858 casts[any->type_id ()].add_overload (fn); 2989 casts[any->type_id ()].add_overload (fn);
2859 2990
2860 // cast uint16 <- any 2991 // cast uint16 <- any
2861 fn = create_external (JIT_FN (octave_jit_cast_uint16_any), uintN (16), any); 2992 fn = create_external (JIT_FN (octave_jit_cast_uint16_any), uintN (16), any);
2862 casts[uintN (16)->type_id ()].add_overload (fn); 2993 casts[uintN (16)->type_id ()].add_overload (fn);
2994
2995 // cast any <- uint64
2996 fn = create_external (JIT_FN (octave_jit_cast_any_uint64), any, uintN (64));
2997 casts[any->type_id ()].add_overload (fn);
2998
2999 // cast uint64 <- any
3000 fn = create_external (JIT_FN (octave_jit_cast_uint64_any), uintN (64), any);
3001 casts[uintN (64)->type_id ()].add_overload (fn);
2863 3002
2864 // cast any <- complex 3003 // cast any <- complex
2865 fn = create_external (JIT_FN (octave_jit_cast_any_complex), any, complex); 3004 fn = create_external (JIT_FN (octave_jit_cast_any_complex), any, complex);
2866 casts[any->type_id ()].add_overload (fn); 3005 casts[any->type_id ()].add_overload (fn);
2867 3006
2919 casts[uintN (8)->type_id ()].add_overload (fn); 3058 casts[uintN (8)->type_id ()].add_overload (fn);
2920 3059
2921 // cast uint16 <- uint16 3060 // cast uint16 <- uint16
2922 fn = create_identity (uintN (16)); 3061 fn = create_identity (uintN (16));
2923 casts[uintN (16)->type_id ()].add_overload (fn); 3062 casts[uintN (16)->type_id ()].add_overload (fn);
3063
3064 // cast uint64 <- uint64
3065 fn = create_identity (uintN (64));
3066 casts[uintN (64)->type_id ()].add_overload (fn);
2924 3067
2925 // cast complex <- complex 3068 // cast complex <- complex
2926 fn = create_identity (complex); 3069 fn = create_identity (complex);
2927 casts[complex->type_id ()].add_overload (fn); 3070 casts[complex->type_id ()].add_overload (fn);
2928 3071
3408 if (ov.is_uint16_type()) 3551 if (ov.is_uint16_type())
3409 { 3552 {
3410 return uintN (16); 3553 return uintN (16);
3411 } 3554 }
3412 3555
3556 if (ov.is_uint64_type())
3557 {
3558 return uintN (64);
3559 }
3560
3413 if (ov.is_complex_scalar ()) 3561 if (ov.is_complex_scalar ())
3414 { 3562 {
3415 Complex cv = ov.complex_value (); 3563 Complex cv = ov.complex_value ();
3416 3564
3417 // We don't really represent complex values, instead we represent 3565 // We don't really represent complex values, instead we represent