src/share/vm/opto/divnode.cpp

Print this page

        

@@ -870,60 +870,36 @@
   const Type *bot = bottom_type();
   if( (t1 == bot) || (t2 == bot) ||
       (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
     return bot;
 
-  // If either is a NaN, return an input NaN
-  if( g_isnan(t1->getf()) )    return t1;
-  if( g_isnan(t2->getf()) )    return t2;
+  // If both numbers are not constants, we know nothing.
+  if ((t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon)) {
+    return Type::FLOAT;         // note: x%x can be either NaN or 0
+  }
 
-  // It is not worth trying to constant fold this stuff!
-  return Type::FLOAT;
+  float f1 = t1->getf();
+  float f2 = t2->getf();
+  jint  x1 = jint_cast(f1);
+  jint  x2 = jint_cast(f2);
 
-  /*
-  // If dividend is infinity or divisor is zero, or both, the result is NaN
-  if( !g_isfinite(t1->getf()) || ((t2->getf() == 0.0) || (jint_cast(t2->getf()) == 0x80000000)) )
-
-  // X MOD infinity = X
-  if( !g_isfinite(t2->getf()) && !g_isnan(t2->getf()) ) return t1;
-  // 0 MOD finite = dividend (positive or negative zero)
-  // Not valid for: NaN MOD any; any MOD nan; 0 MOD 0; or for 0 MOD NaN
-  // NaNs are handled previously.
-  if( !(t2->getf() == 0.0) && !((int)t2->getf() == 0x80000000)) {
-    if (((t1->getf() == 0.0) || ((int)t1->getf() == 0x80000000)) && g_isfinite(t2->getf()) ) {
-      return t1;
-    }
-  }
-  // X MOD X is 0
-  // Does not work for variables because of NaN's
-  if( phase->eqv( in(1), in(2) ) && t1->base() == Type::FloatCon)
-    if (!g_isnan(t1->getf()) && (t1->getf() != 0.0) && ((int)t1->getf() != 0x80000000)) {
-      if(t1->getf() < 0.0) {
-        float result = jfloat_cast(0x80000000);
-        return TypeF::make( result );
-      }
-      else
-        return TypeF::ZERO;
-    }
+  // If either is a NaN, return an input NaN
+  if (g_isnan(f1))    return t1;
+  if (g_isnan(f2))    return t2;
 
-  // If both numbers are not constants, we know nothing.
-  if( (t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon) )
+  // If operand is infinity or divisor is +/- zero, punt.
+  if (!g_isfinite(f1) || !g_isfinite(f2) || (x2 << 1) == 0)
     return Type::FLOAT;
 
   // We must be modulo'ing 2 float constants.
   // Make sure that the sign of the fmod is equal to the sign of the dividend
-  float result = (float)fmod( t1->getf(), t2->getf() );
-  float dividend = t1->getf();
-  if( (dividend < 0.0) || ((int)dividend == 0x80000000) ) {
-    if( result > 0.0 )
-      result = 0.0 - result;
-    else if( result == 0.0 ) {
-      result = jfloat_cast(0x80000000);
-    }
+  jint xr = jint_cast(fmod(f1, f2));
+  if ((x1 ^ xr) < 0) {
+    xr ^= min_jint;
   }
-  return TypeF::make( result );
-  */
+
+  return TypeF::make(jfloat_cast(xr));
 }
 
 
 //=============================================================================
 //------------------------------Value------------------------------------------

@@ -938,37 +914,36 @@
   const Type *bot = bottom_type();
   if( (t1 == bot) || (t2 == bot) ||
       (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
     return bot;
 
-  // If either is a NaN, return an input NaN
-  if( g_isnan(t1->getd()) )    return t1;
-  if( g_isnan(t2->getd()) )    return t2;
-  // X MOD infinity = X
-  if( !g_isfinite(t2->getd())) return t1;
-  // 0 MOD finite = dividend (positive or negative zero)
-  // Not valid for: NaN MOD any; any MOD nan; 0 MOD 0; or for 0 MOD NaN
-  // NaNs are handled previously.
-  if( !(t2->getd() == 0.0) ) {
-    if( t1->getd() == 0.0 && g_isfinite(t2->getd()) ) {
-      return t1;
-    }
+  // If both numbers are not constants, we know nothing.
+  if ((t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon)) {
+    return Type::DOUBLE;        // note: x%x can be either NaN or 0
   }
 
-  // X MOD X is 0
-  // does not work for variables because of NaN's
-  if( phase->eqv( in(1), in(2) ) && t1->base() == Type::DoubleCon )
-    if (!g_isnan(t1->getd()) && t1->getd() != 0.0)
-      return TypeD::ZERO;
+  double f1 = t1->getd();
+  double f2 = t2->getd();
+  jlong  x1 = jlong_cast(f1);
+  jlong  x2 = jlong_cast(f2);
 
+  // If either is a NaN, return an input NaN
+  if (g_isnan(f1))    return t1;
+  if (g_isnan(f2))    return t2;
 
-  // If both numbers are not constants, we know nothing.
-  if( (t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon) )
+  // If operand is infinity or divisor is +/- zero, punt.
+  if (!g_isfinite(f1) || !g_isfinite(f2) || (x2 << 1) == 0)
     return Type::DOUBLE;
 
   // We must be modulo'ing 2 double constants.
-  return TypeD::make( fmod( t1->getd(), t2->getd() ) );
+  // Make sure that the sign of the fmod is equal to the sign of the dividend
+  jlong xr = jlong_cast(fmod(f1, f2));
+  if ((x1 ^ xr) < 0) {
+    xr ^= min_jlong;
+  }
+
+  return TypeF::make(jfloat_cast(xr));
 }
 
 //=============================================================================
 
 DivModNode::DivModNode( Node *c, Node *dividend, Node *divisor ) : MultiNode(3) {