Mercurial > hg > openjdk6-mips
changeset 17:85b046e5468b
Fix 3 bugs related to the float remainder operation.
Fix three bugs related to float remainder operation, TwoOperandLIRForm
and integer multiplication respectively:
1. In mips both single-precision and double-precision remainder
operations need three registers except result, so they should be
three-operand-operation.
2. We made a mistake which setting TwoOperandLIRForm to true. However,
LIR mips used is not of TwoOperandLIRForm.
3. In operation, value of a source register must not be changed
except that the source register is same as the result one. However,
in function strength_reduce_multiply value of left source regiser is
always changed.
author | YANG Yongqiang <yangyongqiang@loongson.cn> |
---|---|
date | Thu, 28 Oct 2010 11:07:44 +0800 |
parents | 88ad8d87be77 |
children | d2a6a000ff33 |
files | hotspot/src/cpu/mips/vm/assembler_mips.cpp hotspot/src/cpu/mips/vm/assembler_mips.hpp hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp hotspot/src/cpu/mips/vm/c1_LIRGenerator_mips.cpp hotspot/src/cpu/mips/vm/c1_globals_mips.hpp hotspot/src/cpu/mips/vm/templateTable_mips.cpp hotspot/src/share/vm/c1/c1_LIR.cpp hotspot/src/share/vm/c1/c1_LIR.hpp hotspot/src/share/vm/c1/c1_LIRAssembler.hpp hotspot/src/share/vm/c1/c1_Runtime1.cpp |
diffstat | 10 files changed, 184 insertions(+), 129 deletions(-) [+] |
line wrap: on
line diff
--- a/hotspot/src/cpu/mips/vm/assembler_mips.cpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/cpu/mips/vm/assembler_mips.cpp Thu Oct 28 11:07:44 2010 +0800 @@ -2304,24 +2304,23 @@ } // be sure the three register is different -void MacroAssembler::rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft) { - assert_different_registers(fd, fs, ft); - div_s(fd, fs, ft); - trunc_l_s(fd, fd); - cvt_s_l(fd, fd); - mul_s(fd, fd, ft); - sub_s(fd, fs, fd); +void MacroAssembler::rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp) { + assert_different_registers(tmp, fs, ft); + div_s(tmp, fs, ft); + trunc_l_s(tmp, tmp); + cvt_s_l(tmp, tmp); + mul_s(tmp, tmp, ft); + sub_s(fd, fs, tmp); } // be sure the three register is different -void MacroAssembler::rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft) { - assert_different_registers(fd, fs, ft); - - div_d(fd, fs, ft); - trunc_l_d(fd, fd); - cvt_d_l(fd, fd); - mul_d(fd, fd, ft); - sub_d(fd, fs, fd); +void MacroAssembler::rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp) { + assert_different_registers(tmp, fs, ft); + div_d(tmp, fs, ft); + trunc_l_d(tmp, tmp); + cvt_d_l(tmp, tmp); + mul_d(tmp, tmp, ft); + sub_d(fd, fs, tmp); } class ControlWord {
--- a/hotspot/src/cpu/mips/vm/assembler_mips.hpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/cpu/mips/vm/assembler_mips.hpp Thu Oct 28 11:07:44 2010 +0800 @@ -1278,8 +1278,8 @@ // Sign extension void sign_extend_short(Register reg) { shl(reg, 16); sar(reg, 16); } void sign_extend_byte(Register reg) { shl(reg, 24); sar(reg, 24); } - void rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft); - void rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft); + void rem_s(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp); + void rem_d(FloatRegister fd, FloatRegister fs, FloatRegister ft, FloatRegister tmp); // Inlined sin/cos generator for Java; must not use CPU instruction // directly on Intel as it does not have high enough precision
--- a/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp Thu Oct 28 11:07:44 2010 +0800 @@ -1241,7 +1241,17 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) { - switch (op->code()) { + switch (op->code()) { + case lir_frem: + arithmetic_frem( + op->code(), + op->in_opr1(), + op->in_opr2(), + op->in_opr3(), + op->result_opr(), + op->info()); + break; + case lir_idiv: case lir_irem: arithmetic_idiv( @@ -2855,39 +2865,7 @@ __ bind(done); } break; -//FIXME, where is the new div and rem? -/* case lir_div_strictfp: - case lir_div: - __ call(Runtime1::entry_for(Runtime1::ldiv_stub_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - add_call_info(code_offset(), info); - - if ( dst_lo != V0 ) { - __ move(dst_lo, V0); - } - - if ( dst_hi != V1) { - __ move(dst_hi, V1); - } - - break; -*/ - /* - case lir_rem: - __ call(Runtime1::entry_for(Runtime1::lrem_stub_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - add_call_info(code_offset(), info); - - if ( dst_lo != V0 ) { - __ move(dst_lo, V0); - } - - if ( dst_hi != V1) { - __ move(dst_hi, V1); - } - - break; - */ + default: ShouldNotReachHere(); } @@ -2902,15 +2880,18 @@ case lir_add: __ addu(res, lreg, rreg); break; + case lir_mul: __ mult(lreg, rreg); __ nop(); __ nop(); __ mflo(res); break; + case lir_sub: __ subu(res, lreg, rreg); break; + default: ShouldNotReachHere(); } @@ -2976,9 +2957,9 @@ case lir_div_strictfp: __ div_s(res, lreg, rreg); break; - case lir_rem: - __ rem_s(res, lreg, rreg); - break; +// case lir_rem: +// __ rem_s(res, lreg, rreg); +// break; default : ShouldNotReachHere(); } } else if (left->is_double_fpu()) { @@ -3006,9 +2987,9 @@ case lir_div_strictfp: __ div_d(res, lreg, rreg); break; - case lir_rem: - __ rem_d(res, lreg, rreg); - break; +// case lir_rem: +// __ rem_d(res, lreg, rreg); +// break; default : ShouldNotReachHere(); } } @@ -3197,39 +3178,74 @@ // we assume that eax and edx can be overwritten void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) { - assert(left->is_single_cpu(), "left must be register"); - assert(right->is_single_cpu() || right->is_constant(), "right must be register or constant"); - assert(result->is_single_cpu(), "result must be register"); - - Register lreg = left->as_register(); - Register dreg = result->as_register(); - - if (right->is_constant()) { - int divisor = right->as_constant_ptr()->as_jint(); - assert(divisor!=0, "must be nonzero"); - __ move(AT, divisor); - __ div(lreg, AT); - __ nop(); - __ nop(); - } else { - Register rreg = right->as_register(); - int idivl_offset = code_offset(); - __ div(lreg, rreg); - __ nop(); - __ nop(); - add_debug_info_for_div0(idivl_offset, info); - } - - // get the result - if (code == lir_irem) { - __ mfhi(dreg); - } else if (code == lir_idiv) { - __ mflo(dreg); - } else { - ShouldNotReachHere(); - } + assert(left->is_single_cpu(), "left must be register"); + assert(right->is_single_cpu() || right->is_constant(), "right must be register or constant"); + assert(result->is_single_cpu(), "result must be register"); + + Register lreg = left->as_register(); + Register dreg = result->as_register(); + + if (right->is_constant()) { + int divisor = right->as_constant_ptr()->as_jint(); + assert(divisor!=0, "must be nonzero"); + __ move(AT, divisor); + __ div(lreg, AT); + __ nop(); + __ nop(); + } else { + Register rreg = right->as_register(); + int idivl_offset = code_offset(); + __ div(lreg, rreg); + __ nop(); + __ nop(); + add_debug_info_for_div0(idivl_offset, info); + } + + // get the result + if (code == lir_irem) { + __ mfhi(dreg); + } else if (code == lir_idiv) { + __ mflo(dreg); + } else { + ShouldNotReachHere(); + } } +void LIR_Assembler::arithmetic_frem(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) { + if (left->is_single_fpu()) { + assert(right->is_single_fpu(),"right must be float"); + assert(result->is_single_fpu(), "dest must be float"); + assert(temp->is_single_fpu(), "dest must be float"); + + FloatRegister lreg = left->as_float_reg(); + FloatRegister rreg = right->as_float_reg(); + FloatRegister res = result->as_float_reg(); + FloatRegister tmp = temp->as_float_reg(); + + switch (code) { + case lir_frem: + __ rem_s(res, lreg, rreg, tmp); + break; + default : ShouldNotReachHere(); + } + } else if (left->is_double_fpu()) { + assert(right->is_double_fpu(),"right must be double"); + assert(result->is_double_fpu(), "dest must be double"); + assert(temp->is_double_fpu(), "dest must be double"); + + FloatRegister lreg = left->as_double_reg(); + FloatRegister rreg = right->as_double_reg(); + FloatRegister res = result->as_double_reg(); + FloatRegister tmp = temp->as_double_reg(); + + switch (code) { + case lir_frem: + __ rem_d(res, lreg, rreg, tmp); + break; + default : ShouldNotReachHere(); + } + } +} void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst,LIR_Op2 * op) { Register dstreg = dst->as_register(); @@ -3662,7 +3678,6 @@ Register desthi = dest->as_register_hi(); assert_different_registers(destlo, valuehi, desthi); count = count & 0x3f; - switch (code) { case lir_shl: if (count==0) { @@ -3938,7 +3953,9 @@ __ push(length); - assert_different_registers(A0, A1, length); + assert(A0 != A1 && + A0 != length && + A1 != length, "register checks"); __ move(AT, dst_pos); if (shift_amount > 0 && basic_type != T_OBJECT) { __ sll(A2, length, shift_amount); @@ -3947,6 +3964,10 @@ __ move(A2, length); } __ move(A3, src_pos ); + assert(A0 != dst_pos && + A0 != dst && + dst_pos != dst, "register checks"); + assert_different_registers(A0, dst_pos, dst); __ sll(AT, AT, shift_amount); __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(basic_type));
--- a/hotspot/src/cpu/mips/vm/c1_LIRGenerator_mips.cpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/cpu/mips/vm/c1_LIRGenerator_mips.cpp Thu Oct 28 11:07:44 2010 +0800 @@ -299,14 +299,14 @@ bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, int c, LIR_Opr result, LIR_Opr tmp) { if (tmp->is_valid()) { if (is_power_of_2(c + 1)) { - __ move(left, tmp); - __ shift_left(left, log2_intptr(c + 1), left); - __ sub(left, tmp, result); + __ move(left, result); + __ shift_left(result, log2_intptr(c + 1), result); + __ sub(result, left, result); return true; } else if (is_power_of_2(c - 1)) { - __ move(left, tmp); - __ shift_left(left, log2_intptr(c - 1), left); - __ add(left, tmp, result); + __ move(left, result); + __ shift_left(result, log2_intptr(c - 1), result); + __ add(result, left, result); return true; } } @@ -454,12 +454,24 @@ // for _fadd, _fmul, _fsub, _fdiv, _frem // _dadd, _dmul, _dsub, _ddiv, _drem void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { - LIRItem left(x->x(), this); - LIRItem right(x->y(), this); - left.load_item(); - right.load_item(); - rlock_result(x); - arithmetic_op_fpu(x->op(), x->operand(), left.result(), right.result(), x->is_strictfp()); + LIR_Opr tmp; + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + left.load_item(); + right.load_item(); + rlock_result(x); + switch (x->op()) { + case Bytecodes::_drem: + tmp = new_register(T_DOUBLE); + __ frem(left.result(), right.result(), x->operand(), tmp); + + break; + case Bytecodes::_frem: + tmp = new_register(T_FLOAT); + __ frem(left.result(), right.result(), x->operand(), tmp); + break; + default: arithmetic_op_fpu(x->op(), x->operand(), left.result(), right.result(), x->is_strictfp()); + } } @@ -540,30 +552,30 @@ // for: _iadd, _imul, _isub, _idiv, _irem void LIRGenerator::do_ArithmeticOp_Int(ArithmeticOp* x) { - bool is_div_rem = x->op() == Bytecodes::_idiv || x->op() == Bytecodes::_irem; - LIRItem left(x->x(), this); - LIRItem right(x->y(), this); - // missing test if instr is commutative and if we should swap - right.load_nonconstant(); - assert(right.is_constant() || right.is_register(), "wrong state of right"); - left.load_item(); - rlock_result(x); - if (is_div_rem) { - CodeEmitInfo* info = state_for(x); - LIR_Opr tmp =new_register(T_INT); - if (x->op() == Bytecodes::_irem) { - __ irem(left.result(), right.result(), x->operand(), tmp, info); - } else if (x->op() == Bytecodes::_idiv) { - __ idiv(left.result(), right.result(), x->operand(), tmp, info); - } - } else { - //arithmetic_op_int(x->op(), x->operand(), left.result(), - //right.result(), FrameMap::G1_opr); + bool is_div_rem = x->op() == Bytecodes::_idiv || x->op() == Bytecodes::_irem; + LIRItem left(x->x(), this); + LIRItem right(x->y(), this); + // missing test if instr is commutative and if we should swap + right.load_nonconstant(); + assert(right.is_constant() || right.is_register(), "wrong state of right"); + left.load_item(); + rlock_result(x); + if (is_div_rem) { + CodeEmitInfo* info = state_for(x); + LIR_Opr tmp =new_register(T_INT); + if (x->op() == Bytecodes::_irem) { + __ irem(left.result(), right.result(), x->operand(), tmp, info); + } else if (x->op() == Bytecodes::_idiv) { + __ idiv(left.result(), right.result(), x->operand(), tmp, info); + } + } else { + //arithmetic_op_int(x->op(), x->operand(), left.result(), + //right.result(), FrameMap::G1_opr); - LIR_Opr tmp =new_register(T_INT); - arithmetic_op_int(x->op(), x->operand(), left.result(), right.result(), - tmp); - } + LIR_Opr tmp =new_register(T_INT); + arithmetic_op_int(x->op(), x->operand(), left.result(), right.result(), + tmp); + } }
--- a/hotspot/src/cpu/mips/vm/c1_globals_mips.hpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/cpu/mips/vm/c1_globals_mips.hpp Thu Oct 28 11:07:44 2010 +0800 @@ -69,7 +69,7 @@ define_pd_global(bool, LIRFillDelaySlots, false); define_pd_global(bool, OptimizeSinglePrecision, true); define_pd_global(bool, CSEArrayLength, false); -define_pd_global(bool, TwoOperandLIRForm, true); +define_pd_global(bool, TwoOperandLIRForm, false); define_pd_global(intx, SafepointPollOffset, 256);
--- a/hotspot/src/cpu/mips/vm/templateTable_mips.cpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/cpu/mips/vm/templateTable_mips.cpp Thu Oct 28 11:07:44 2010 +0800 @@ -1669,7 +1669,7 @@ __ mfc1(FSR, FSF); __ mtc1(FSR, F12); __ lwc1(FTF, at_sp()); - __ rem_s(FSF, FTF, F12); + __ rem_s(FSF, FTF, F12, FSF); break; default : ShouldNotReachHere(); } @@ -1710,7 +1710,7 @@ __ mtc1(SSR, F13); __ lwc1(FTF, at_sp()); __ lwc1(STF, at_sp_p1()); - __ rem_d(FSF, FTF, F12); + __ rem_d(FSF, FTF, F12, FSF); break; default : ShouldNotReachHere(); }
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Oct 28 11:07:44 2010 +0800 @@ -735,6 +735,9 @@ // LIR_Op3 +#ifdef MIPS32 + case lir_frem: +#endif case lir_idiv: case lir_irem: { assert(op->as_Op3() != NULL, "must be"); @@ -1250,6 +1253,17 @@ } +#ifdef MIPS32 +void LIR_List::frem(LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp, CodeEmitInfo* info) { + append(new LIR_Op3( + lir_frem, + left, + right, + tmp, + res, + info)); +} +#endif void LIR_List::idiv(LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp, CodeEmitInfo* info) { append(new LIR_Op3( @@ -1773,6 +1787,9 @@ case lir_ushr: s = "ushift_right"; break; case lir_alloc_array: s = "alloc_array"; break; // LIR_Op3 +#ifdef MIPS32 + case lir_frem: s = "frem"; break; +#endif case lir_idiv: s = "idiv"; break; case lir_irem: s = "irem"; break; // LIR_OpJavaCall
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Thu Oct 28 11:07:44 2010 +0800 @@ -872,6 +872,7 @@ , lir_compare_to , end_op2 , begin_op3 + , lir_frem , lir_idiv , lir_irem , end_op3 @@ -2138,6 +2139,9 @@ void volatile_store_mem_reg(LIR_Opr src, LIR_Address* address, CodeEmitInfo* info, LIR_PatchCode patch_code = lir_patch_none); void volatile_store_unsafe_reg(LIR_Opr src, LIR_Opr base, LIR_Opr offset, BasicType type, CodeEmitInfo* info, LIR_PatchCode patch_code); +#ifdef MIPS32 + void frem(LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp, CodeEmitInfo* info = NULL); +#endif void idiv(LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp, CodeEmitInfo* info); void idiv(LIR_Opr left, int right, LIR_Opr res, LIR_Opr tmp, CodeEmitInfo* info); void irem(LIR_Opr left, LIR_Opr right, LIR_Opr res, LIR_Opr tmp, CodeEmitInfo* info);
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Thu Oct 28 11:07:44 2010 +0800 @@ -192,6 +192,9 @@ void emit_delay(LIR_OpDelay* op); void arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack); +#ifdef MIPS32 + void arithmetic_frem(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info = NULL); +#endif void arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info); void intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, LIR_Opr dest, LIR_Op* op);
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Tue Oct 26 20:09:04 2010 +0800 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Oct 28 11:07:44 2010 +0800 @@ -1059,7 +1059,6 @@ { // Enter VM mode - printf("%s %d\n", __FILE__, __LINE__); ResetNoHandleMark rnhm; patch_code(thread, access_field_patching_id); }