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:


 806   else if (type == intType)
 807     __ cas_int(addr, cmp.result(), val.result(), ill, ill);
 808   else if (type == longType)
 809     __ cas_long(addr, cmp.result(), val.result(), ill, ill);
 810   else {
 811     ShouldNotReachHere();
 812   }
 813 
 814   // generate conditional move of boolean result
 815   LIR_Opr result = rlock_result(x);
 816   __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
 817            result, as_BasicType(type));
 818   if (type == objectType) {   // Write-barrier needed for Object fields.
 819     // Seems to be precise
 820     post_barrier(addr, val.result());
 821   }
 822 }
 823 
 824 
 825 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
 826   assert(x->number_of_arguments() == 1, "wrong type");
 827   LIRItem value(x->argument_at(0), this);
 828 
 829   bool use_fpu = false;
 830   if (UseSSE >= 2) {
 831     switch(x->id()) {
 832       case vmIntrinsics::_dsin:
 833       case vmIntrinsics::_dcos:
 834       case vmIntrinsics::_dtan:
 835       case vmIntrinsics::_dlog:
 836       case vmIntrinsics::_dlog10:


 837         use_fpu = true;
 838     }
 839   } else {
 840     value.set_destroys_register();
 841   }
 842 
 843   value.load_item();
 844 
 845   LIR_Opr calc_input = value.result();





 846   LIR_Opr calc_result = rlock_result(x);
 847 
 848   // sin and cos need two free fpu stack slots, so register two temporary operands

 849   LIR_Opr tmp1 = FrameMap::caller_save_fpu_reg_at(0);
 850   LIR_Opr tmp2 = FrameMap::caller_save_fpu_reg_at(1);
 851 
 852   if (use_fpu) {
 853     LIR_Opr tmp = FrameMap::fpu0_double_opr;






 854     __ move(calc_input, tmp);
 855 
 856     calc_input = tmp;
 857     calc_result = tmp;
 858     tmp1 = FrameMap::caller_save_fpu_reg_at(1);
 859     tmp2 = FrameMap::caller_save_fpu_reg_at(2);

 860   }
 861 
 862   switch(x->id()) {
 863     case vmIntrinsics::_dabs:   __ abs  (calc_input, calc_result, LIR_OprFact::illegalOpr); break;
 864     case vmIntrinsics::_dsqrt:  __ sqrt (calc_input, calc_result, LIR_OprFact::illegalOpr); break;
 865     case vmIntrinsics::_dsin:   __ sin  (calc_input, calc_result, tmp1, tmp2);              break;
 866     case vmIntrinsics::_dcos:   __ cos  (calc_input, calc_result, tmp1, tmp2);              break;
 867     case vmIntrinsics::_dtan:   __ tan  (calc_input, calc_result, tmp1, tmp2);              break;
 868     case vmIntrinsics::_dlog:   __ log  (calc_input, calc_result, tmp1);                    break;
 869     case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1);                    break;


 870     default:                    ShouldNotReachHere();
 871   }
 872 
 873   if (use_fpu) {
 874     __ move(calc_result, x->operand());
 875   }
 876 }
 877 
 878 
 879 void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
 880   assert(x->number_of_arguments() == 5, "wrong type");
 881 
 882   // Make all state_for calls early since they can emit code
 883   CodeEmitInfo* info = state_for(x, x->state());
 884 
 885   LIRItem src(x->argument_at(0), this);
 886   LIRItem src_pos(x->argument_at(1), this);
 887   LIRItem dst(x->argument_at(2), this);
 888   LIRItem dst_pos(x->argument_at(3), this);
 889   LIRItem length(x->argument_at(4), this);




 806   else if (type == intType)
 807     __ cas_int(addr, cmp.result(), val.result(), ill, ill);
 808   else if (type == longType)
 809     __ cas_long(addr, cmp.result(), val.result(), ill, ill);
 810   else {
 811     ShouldNotReachHere();
 812   }
 813 
 814   // generate conditional move of boolean result
 815   LIR_Opr result = rlock_result(x);
 816   __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
 817            result, as_BasicType(type));
 818   if (type == objectType) {   // Write-barrier needed for Object fields.
 819     // Seems to be precise
 820     post_barrier(addr, val.result());
 821   }
 822 }
 823 
 824 
 825 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
 826   assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
 827   LIRItem value(x->argument_at(0), this);
 828 
 829   bool use_fpu = false;
 830   if (UseSSE >= 2) {
 831     switch(x->id()) {
 832       case vmIntrinsics::_dsin:
 833       case vmIntrinsics::_dcos:
 834       case vmIntrinsics::_dtan:
 835       case vmIntrinsics::_dlog:
 836       case vmIntrinsics::_dlog10:
 837       case vmIntrinsics::_dexp:
 838       case vmIntrinsics::_dpow:
 839         use_fpu = true;
 840     }
 841   } else {
 842     value.set_destroys_register();
 843   }
 844 
 845   value.load_item();
 846 
 847   LIR_Opr calc_input = value.result();
 848   LIR_Opr calc_input2 = NULL;
 849   if (x->id() == vmIntrinsics::_dpow) {
 850     LIRItem extra_arg(x->argument_at(1), this);
 851     calc_input2 = extra_arg.result();
 852   }
 853   LIR_Opr calc_result = rlock_result(x);
 854 
 855   // sin, cos, pow and exp need two free fpu stack slots, so register
 856   // two temporary operands
 857   LIR_Opr tmp1 = FrameMap::caller_save_fpu_reg_at(0);
 858   LIR_Opr tmp2 = FrameMap::caller_save_fpu_reg_at(1);
 859 
 860   if (use_fpu) {
 861     LIR_Opr tmp = FrameMap::fpu0_double_opr;
 862     int tmp_start = 1;
 863     if (calc_input2 != NULL) {
 864       __ move(calc_input2, tmp);
 865       tmp_start = 2;
 866       calc_input2 = tmp;
 867     }
 868     __ move(calc_input, tmp);
 869 
 870     calc_input = tmp;
 871     calc_result = tmp;
 872 
 873     tmp1 = FrameMap::caller_save_fpu_reg_at(tmp_start);
 874     tmp2 = FrameMap::caller_save_fpu_reg_at(tmp_start + 1);
 875   }
 876 
 877   switch(x->id()) {
 878     case vmIntrinsics::_dabs:   __ abs  (calc_input, calc_result, LIR_OprFact::illegalOpr); break;
 879     case vmIntrinsics::_dsqrt:  __ sqrt (calc_input, calc_result, LIR_OprFact::illegalOpr); break;
 880     case vmIntrinsics::_dsin:   __ sin  (calc_input, calc_result, tmp1, tmp2);              break;
 881     case vmIntrinsics::_dcos:   __ cos  (calc_input, calc_result, tmp1, tmp2);              break;
 882     case vmIntrinsics::_dtan:   __ tan  (calc_input, calc_result, tmp1, tmp2);              break;
 883     case vmIntrinsics::_dlog:   __ log  (calc_input, calc_result, tmp1);                    break;
 884     case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1);                    break;
 885     case vmIntrinsics::_dexp:   __ exp  (calc_input, calc_result,              tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
 886     case vmIntrinsics::_dpow:   __ pow  (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
 887     default:                    ShouldNotReachHere();
 888   }
 889 
 890   if (use_fpu) {
 891     __ move(calc_result, x->operand());
 892   }
 893 }
 894 
 895 
 896 void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
 897   assert(x->number_of_arguments() == 5, "wrong type");
 898 
 899   // Make all state_for calls early since they can emit code
 900   CodeEmitInfo* info = state_for(x, x->state());
 901 
 902   LIRItem src(x->argument_at(0), this);
 903   LIRItem src_pos(x->argument_at(1), this);
 904   LIRItem dst(x->argument_at(2), this);
 905   LIRItem dst_pos(x->argument_at(3), this);
 906   LIRItem length(x->argument_at(4), this);