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);
   }