src/cpu/x86/vm/c1_LIRGenerator_x86.cpp

Print this page
rev 3227 : 7133857: exp() and pow() should use the x87 ISA on x86
Summary: use x87 instructions to implement exp() and pow() in interpreter/c1/c2.
Reviewed-by:

*** 821,874 **** } } void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { ! assert(x->number_of_arguments() == 1, "wrong type"); LIRItem value(x->argument_at(0), this); bool use_fpu = false; if (UseSSE >= 2) { switch(x->id()) { case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: case vmIntrinsics::_dlog: case vmIntrinsics::_dlog10: use_fpu = true; } } else { value.set_destroys_register(); } value.load_item(); LIR_Opr calc_input = value.result(); LIR_Opr calc_result = rlock_result(x); ! // sin and cos need two free fpu stack slots, so register two temporary operands LIR_Opr tmp1 = FrameMap::caller_save_fpu_reg_at(0); LIR_Opr tmp2 = FrameMap::caller_save_fpu_reg_at(1); if (use_fpu) { LIR_Opr tmp = FrameMap::fpu0_double_opr; __ move(calc_input, tmp); calc_input = tmp; calc_result = tmp; ! tmp1 = FrameMap::caller_save_fpu_reg_at(1); ! tmp2 = FrameMap::caller_save_fpu_reg_at(2); } switch(x->id()) { case vmIntrinsics::_dabs: __ abs (calc_input, calc_result, LIR_OprFact::illegalOpr); break; case vmIntrinsics::_dsqrt: __ sqrt (calc_input, calc_result, LIR_OprFact::illegalOpr); break; case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break; case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break; default: ShouldNotReachHere(); } if (use_fpu) { __ move(calc_result, x->operand()); --- 821,895 ---- } } void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { ! assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type"); LIRItem value(x->argument_at(0), this); bool use_fpu = false; if (UseSSE >= 2) { switch(x->id()) { case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: case vmIntrinsics::_dlog: case vmIntrinsics::_dlog10: + case vmIntrinsics::_dexp: + case vmIntrinsics::_dpow: use_fpu = true; } } else { value.set_destroys_register(); } value.load_item(); LIR_Opr calc_input = value.result(); + LIR_Opr calc_input2 = NULL; + if (x->id() == vmIntrinsics::_dpow) { + LIRItem extra_arg(x->argument_at(1), this); + if (UseSSE < 2) { + extra_arg.set_destroys_register(); + } + extra_arg.load_item(); + calc_input2 = extra_arg.result(); + } LIR_Opr calc_result = rlock_result(x); ! // sin, cos, pow and exp need two free fpu stack slots, so register ! // two temporary operands LIR_Opr tmp1 = FrameMap::caller_save_fpu_reg_at(0); LIR_Opr tmp2 = FrameMap::caller_save_fpu_reg_at(1); if (use_fpu) { LIR_Opr tmp = FrameMap::fpu0_double_opr; + int tmp_start = 1; + if (calc_input2 != NULL) { + __ move(calc_input2, tmp); + tmp_start = 2; + calc_input2 = tmp; + } __ move(calc_input, tmp); calc_input = tmp; calc_result = tmp; ! ! tmp1 = FrameMap::caller_save_fpu_reg_at(tmp_start); ! tmp2 = FrameMap::caller_save_fpu_reg_at(tmp_start + 1); } switch(x->id()) { case vmIntrinsics::_dabs: __ abs (calc_input, calc_result, LIR_OprFact::illegalOpr); break; case vmIntrinsics::_dsqrt: __ sqrt (calc_input, calc_result, LIR_OprFact::illegalOpr); break; case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break; case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break; + case vmIntrinsics::_dexp: __ exp (calc_input, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break; + case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break; default: ShouldNotReachHere(); } if (use_fpu) { __ move(calc_result, x->operand());