# HG changeset patch # User LYH # Date 1380141456 -28800 # Node ID 7c14949789ab5e5c9dde46374ec3e68e2592b5f5 # Parent a0014fa5cf6391d394b7ec8a235f1d19c41a866f Fully single type support & clean the code diff --git a/libinterp/corefcn/jit-typeinfo.cc b/libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc +++ b/libinterp/corefcn/jit-typeinfo.cc @@ -474,6 +474,25 @@ return std::pow (lhs, rhs); } +// FIXME: should handle FloatComplex +extern "C" Complex +octave_jit_pow_single_single (float lhs, float rhs) +{ + // FIXME: almost CP from libinterp/corefcn/xpow.cc + float retval; + + if (lhs < 0.0 && ! xisint (rhs)) + { + FloatComplex lhstmp (lhs); + + return std::pow (lhstmp, rhs); + } + else + retval = std::pow (lhs, rhs); + + return retval; +} + extern "C" Complex octave_jit_pow_complex_scalar (Complex lhs, double rhs) { @@ -1300,6 +1319,12 @@ destroy_fn.add_overload (create_identity(index)); destroy_fn.add_overload (create_identity(complex)); + /************************************************************ + * + * scalar related operations + * + ************************************************************/ + // now for binary scalar operations add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd); add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub); @@ -1316,26 +1341,6 @@ jit_function gripe_div0 = create_external (JIT_FN (gripe_divide_by_zero), 0); gripe_div0.mark_can_error (); - // now for binary single operations - add_binary_op (single, octave_value::op_add, llvm::Instruction::FAdd); - add_binary_op (single, octave_value::op_sub, llvm::Instruction::FSub); - add_binary_op (single, octave_value::op_mul, llvm::Instruction::FMul); - add_binary_op (single, octave_value::op_el_mul, llvm::Instruction::FMul); - - add_binary_fcmp (single, octave_value::op_lt, llvm::CmpInst::FCMP_ULT); - add_binary_fcmp (single, octave_value::op_le, llvm::CmpInst::FCMP_ULE); - add_binary_fcmp (single, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ); - add_binary_fcmp (single, octave_value::op_ge, llvm::CmpInst::FCMP_UGE); - add_binary_fcmp (single, octave_value::op_gt, llvm::CmpInst::FCMP_UGT); - add_binary_fcmp (single, octave_value::op_ne, llvm::CmpInst::FCMP_UNE); - - // 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); - - add_binary_icmp (uintN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ); - // divide is annoying because it might error fn = create_internal ("octave_jit_div_scalar_scalar", scalar, scalar, scalar); fn.mark_can_error (); @@ -1414,49 +1419,11 @@ unary_ops[octave_value::op_transpose].add_overload (fn); unary_ops[octave_value::op_hermitian].add_overload (fn); - // now for unary single operations - // FIXME: Impelment not - fn = create_internal ("octave_jit_++", single, single); - body = fn.new_block (); - builder.SetInsertPoint (body); - { - llvm::Value *one = llvm::ConstantFP::get (single_t, 1); - llvm::Value *val = fn.argument (builder, 0); - val = builder.CreateFAdd (val, one); - fn.do_return (builder, val); - } - unary_ops[octave_value::op_incr].add_overload (fn); - - fn = create_internal ("octave_jit_--", single, single); - body = fn.new_block (); - builder.SetInsertPoint (body); - { - llvm::Value *one = llvm::ConstantFP::get (single_t, 1); - llvm::Value *val = fn.argument (builder, 0); - val = builder.CreateFSub (val, one); - fn.do_return (builder, val); - } - unary_ops[octave_value::op_decr].add_overload (fn); - - fn = create_internal ("octave_jit_uminus", single, single); - body = fn.new_block (); - builder.SetInsertPoint (body); - { - llvm::Value *mone = llvm::ConstantFP::get (single_t, -1); - llvm::Value *val = fn.argument (builder, 0); - val = builder.CreateFMul (val, mone); - fn.do_return (builder, val); - } - - fn = create_identity (single); - 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); - - // 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); + /************************************************************ + * + * complex related operations + * + ************************************************************/ // now for binary complex operations fn = create_internal ("octave_jit_+_complex_complex", complex, complex, @@ -1505,6 +1472,122 @@ binary_ops[octave_value::op_pow].add_overload (fn); binary_ops[octave_value::op_el_pow].add_overload (fn); + /************************************************************ + * + * single related operations + * + ************************************************************/ + + // now for binary single operations + add_binary_op (single, octave_value::op_add, llvm::Instruction::FAdd); + add_binary_op (single, octave_value::op_sub, llvm::Instruction::FSub); + add_binary_op (single, octave_value::op_mul, llvm::Instruction::FMul); + add_binary_op (single, octave_value::op_el_mul, llvm::Instruction::FMul); + + add_binary_fcmp (single, octave_value::op_lt, llvm::CmpInst::FCMP_ULT); + add_binary_fcmp (single, octave_value::op_le, llvm::CmpInst::FCMP_ULE); + add_binary_fcmp (single, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ); + add_binary_fcmp (single, octave_value::op_ge, llvm::CmpInst::FCMP_UGE); + add_binary_fcmp (single, octave_value::op_gt, llvm::CmpInst::FCMP_UGT); + 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.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::ConstantFP::get (single_t, 0); + llvm::Value *check = builder.CreateFCmpUEQ (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.CreateFDiv (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); + + // In general, the result of scalar ^ scalar is a complex number. We might be + // able to improve on this if we keep track of the range of values varaibles + // can take on. + fn = create_external (JIT_FN (octave_jit_pow_single_single), complex, single, + single); + binary_ops[octave_value::op_pow].add_overload (fn); + binary_ops[octave_value::op_el_pow].add_overload (fn); + + // now for unary single operations + // FIXME: Impelment not + fn = create_internal ("octave_jit_++", single, single); + body = fn.new_block (); + builder.SetInsertPoint (body); + { + llvm::Value *one = llvm::ConstantFP::get (single_t, 1); + llvm::Value *val = fn.argument (builder, 0); + val = builder.CreateFAdd (val, one); + fn.do_return (builder, val); + } + unary_ops[octave_value::op_incr].add_overload (fn); + + fn = create_internal ("octave_jit_--", single, single); + body = fn.new_block (); + builder.SetInsertPoint (body); + { + llvm::Value *one = llvm::ConstantFP::get (single_t, 1); + llvm::Value *val = fn.argument (builder, 0); + val = builder.CreateFSub (val, one); + fn.do_return (builder, val); + } + unary_ops[octave_value::op_decr].add_overload (fn); + + fn = create_internal ("octave_jit_uminus", single, single); + body = fn.new_block (); + builder.SetInsertPoint (body); + { + llvm::Value *mone = llvm::ConstantFP::get (single_t, -1); + llvm::Value *val = fn.argument (builder, 0); + val = builder.CreateFMul (val, mone); + fn.do_return (builder, val); + } + unary_ops[octave_value::op_uminus].add_overload (fn); + + fn = create_identity (single); + 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); + + /************************************************************ + * + * 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); + + add_binary_icmp (uintN (16), octave_value::op_eq, llvm::CmpInst::ICMP_EQ); + + // 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_internal ("octave_jit_*_scalar_complex", complex, scalar, complex); jit_function mul_scalar_complex = fn;