7133857: exp() and pow() should use the x87 ISA on x86

Use x87 instructions to implement exp() and pow() in interpreter/c1/c2.

Reviewed-by: kvn, never, twisti
This commit is contained in:
Roland Westrelin 2012-05-15 10:10:23 +02:00
parent eb4a860bc3
commit b305cf722e
26 changed files with 783 additions and 279 deletions

View file

@ -624,11 +624,13 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
{
assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
if (op2->_info) do_info(op2->_info);
if (op2->_opr1->is_valid()) do_input(op2->_opr1);
if (op2->_opr2->is_valid()) do_input(op2->_opr2);
if (op2->_tmp->is_valid()) do_temp(op2->_tmp);
if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1);
if (op2->_result->is_valid()) do_output(op2->_result);
break;
@ -641,7 +643,8 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
assert(op2->_info == NULL && op2->_tmp->is_illegal(), "not used");
assert(op2->_info == NULL && op2->_tmp1->is_illegal() && op2->_tmp2->is_illegal() &&
op2->_tmp3->is_illegal() && op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
assert(op2->_opr1->is_valid() && op2->_opr2->is_valid() && op2->_result->is_valid(), "used");
do_input(op2->_opr1);
@ -665,10 +668,12 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
assert(op2->_opr1->is_valid(), "used");
assert(op2->_opr2->is_valid(), "used");
assert(op2->_result->is_valid(), "used");
assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
do_input(op2->_opr1); do_temp(op2->_opr1);
do_input(op2->_opr2); do_temp(op2->_opr2);
if (op2->_tmp->is_valid()) do_temp(op2->_tmp);
if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1);
do_output(op2->_result);
break;
@ -682,6 +687,8 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
if (op2->_opr1->is_valid()) do_temp(op2->_opr1);
if (op2->_opr2->is_valid()) do_input(op2->_opr2); // exception object is input parameter
assert(op2->_result->is_illegal(), "no result");
assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
break;
}
@ -702,7 +709,8 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
case lir_sin:
case lir_cos:
case lir_log:
case lir_log10: {
case lir_log10:
case lir_exp: {
assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
@ -711,16 +719,47 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
// Register input operand as temp to guarantee that it doesn't
// overlap with the input.
assert(op2->_info == NULL, "not used");
assert(op2->_tmp5->is_illegal(), "not used");
assert(op2->_tmp2->is_valid() == (op->code() == lir_exp), "not used");
assert(op2->_tmp3->is_valid() == (op->code() == lir_exp), "not used");
assert(op2->_tmp4->is_valid() == (op->code() == lir_exp), "not used");
assert(op2->_opr1->is_valid(), "used");
do_input(op2->_opr1); do_temp(op2->_opr1);
if (op2->_opr2->is_valid()) do_temp(op2->_opr2);
if (op2->_tmp->is_valid()) do_temp(op2->_tmp);
if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1);
if (op2->_tmp2->is_valid()) do_temp(op2->_tmp2);
if (op2->_tmp3->is_valid()) do_temp(op2->_tmp3);
if (op2->_tmp4->is_valid()) do_temp(op2->_tmp4);
if (op2->_result->is_valid()) do_output(op2->_result);
break;
}
case lir_pow: {
assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
// On x86 pow needs two temporary fpu stack slots: tmp1 and
// tmp2. Register input operands as temps to guarantee that it
// doesn't overlap with the temporary slots.
assert(op2->_info == NULL, "not used");
assert(op2->_opr1->is_valid() && op2->_opr2->is_valid(), "used");
assert(op2->_tmp1->is_valid() && op2->_tmp2->is_valid() && op2->_tmp3->is_valid()
&& op2->_tmp4->is_valid() && op2->_tmp5->is_valid(), "used");
assert(op2->_result->is_valid(), "used");
do_input(op2->_opr1); do_temp(op2->_opr1);
do_input(op2->_opr2); do_temp(op2->_opr2);
do_temp(op2->_tmp1);
do_temp(op2->_tmp2);
do_temp(op2->_tmp3);
do_temp(op2->_tmp4);
do_temp(op2->_tmp5);
do_output(op2->_result);
break;
}
// LIR_Op3
case lir_idiv:
@ -1670,6 +1709,8 @@ const char * LIR_Op::name() const {
case lir_tan: s = "tan"; break;
case lir_log: s = "log"; break;
case lir_log10: s = "log10"; break;
case lir_exp: s = "exp"; break;
case lir_pow: s = "pow"; break;
case lir_logic_and: s = "logic_and"; break;
case lir_logic_or: s = "logic_or"; break;
case lir_logic_xor: s = "logic_xor"; break;
@ -1892,7 +1933,11 @@ void LIR_Op2::print_instr(outputStream* out) const {
}
in_opr1()->print(out); out->print(" ");
in_opr2()->print(out); out->print(" ");
if (tmp_opr()->is_valid()) { tmp_opr()->print(out); out->print(" "); }
if (tmp1_opr()->is_valid()) { tmp1_opr()->print(out); out->print(" "); }
if (tmp2_opr()->is_valid()) { tmp2_opr()->print(out); out->print(" "); }
if (tmp3_opr()->is_valid()) { tmp3_opr()->print(out); out->print(" "); }
if (tmp4_opr()->is_valid()) { tmp4_opr()->print(out); out->print(" "); }
if (tmp5_opr()->is_valid()) { tmp5_opr()->print(out); out->print(" "); }
result_opr()->print(out);
}