LIR_Opr result() { assert(!_destroys_register || (!_result->is_register() || _result->is_virtual()), "shouldn't use set_destroys_register with physical regsiters"); if (_destroys_register && _result->is_register()) { if (_new_result->is_illegal()) { _new_result = _gen->new_register(type()); gen()->lir()->move(_result, _new_result); } return _new_result; } else { return _result; } return _result; }
void FpuStackAllocator::handle_op2(LIR_Op2* op2) { LIR_Opr left = op2->in_opr1(); if (!left->is_float_kind()) { return; } if (left->is_xmm_register()) { return; } LIR_Opr right = op2->in_opr2(); LIR_Opr res = op2->result_opr(); LIR_Opr new_left = left; // new operands relative to the actual fpu stack top LIR_Opr new_right = right; LIR_Opr new_res = res; assert(!left->is_xmm_register() && !right->is_xmm_register() && !res->is_xmm_register(), "not for xmm registers"); switch (op2->code()) { case lir_cmp: case lir_cmp_fd2i: case lir_ucmp_fd2i: case lir_assert: { assert(left->is_fpu_register(), "invalid LIR"); assert(right->is_fpu_register(), "invalid LIR"); // the left-hand side must be on top of stack. // the right-hand side is never popped, even if is_last_use is set insert_exchange(left); new_left = to_fpu_stack_top(left); new_right = to_fpu_stack(right); pop_if_last_use(op2, left); break; } case lir_mul_strictfp: case lir_div_strictfp: { assert(op2->tmp1_opr()->is_fpu_register(), "strict operations need temporary fpu stack slot"); insert_free_if_dead(op2->tmp1_opr()); assert(sim()->stack_size() <= 7, "at least one stack slot must be free"); // fall-through: continue with the normal handling of lir_mul and lir_div } case lir_add: case lir_sub: case lir_mul: case lir_div: { assert(left->is_fpu_register(), "must be"); assert(res->is_fpu_register(), "must be"); assert(left->is_equal(res), "must be"); // either the left-hand or the right-hand side must be on top of stack // (if right is not a register, left must be on top) if (!right->is_fpu_register()) { insert_exchange(left); new_left = to_fpu_stack_top(left); } else { // no exchange necessary if right is alredy on top of stack if (tos_offset(right) == 0) { new_left = to_fpu_stack(left); new_right = to_fpu_stack_top(right); } else { insert_exchange(left); new_left = to_fpu_stack_top(left); new_right = to_fpu_stack(right); } if (right->is_last_use()) { op2->set_fpu_pop_count(1); if (tos_offset(right) == 0) { sim()->pop(); } else { // if left is on top of stack, the result is placed in the stack // slot of right, so a renaming from right to res is necessary assert(tos_offset(left) == 0, "must be"); sim()->pop(); do_rename(right, res); } } } new_res = to_fpu_stack(res); break; } case lir_rem: { assert(left->is_fpu_register(), "must be"); assert(right->is_fpu_register(), "must be"); assert(res->is_fpu_register(), "must be"); assert(left->is_equal(res), "must be"); // Must bring both operands to top of stack with following operand ordering: // * fpu stack before rem: ... right left // * fpu stack after rem: ... left if (tos_offset(right) != 1) { insert_exchange(right); insert_exchange(1); } insert_exchange(left); assert(tos_offset(right) == 1, "check"); assert(tos_offset(left) == 0, "check"); new_left = to_fpu_stack_top(left); new_right = to_fpu_stack(right); op2->set_fpu_pop_count(1); sim()->pop(); do_rename(right, res); new_res = to_fpu_stack_top(res); break; } case lir_abs: case lir_sqrt: { // Right argument appears to be unused assert(right->is_illegal(), "must be"); assert(left->is_fpu_register(), "must be"); assert(res->is_fpu_register(), "must be"); assert(left->is_last_use(), "old value gets destroyed"); insert_free_if_dead(res, left); insert_exchange(left); do_rename(left, res); new_left = to_fpu_stack_top(res); new_res = new_left; op2->set_fpu_stack_size(sim()->stack_size()); break; } default: { assert(false, "missed a fpu-operation"); } } op2->set_in_opr1(new_left); op2->set_in_opr2(new_right); op2->set_result_opr(new_res); }