8168770: Fix for 8151988 causes performance regression on SPARC
authorthartmann
Mon, 31 Oct 2016 09:50:12 +0100
changeset 42078 5ce569f4912c
parent 42077 ff3dd31ee8c2
child 42079 99e743c3dfbd
8168770: Fix for 8151988 causes performance regression on SPARC Summary: Reversed and re-implemented fix for 8151988 to eagerly cut off control input of Div and Mod nodes. Reviewed-by: kvn
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/divnode.cpp
--- a/hotspot/src/share/vm/opto/compile.cpp	Fri Oct 28 19:33:22 2016 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp	Mon Oct 31 09:50:12 2016 +0100
@@ -3173,65 +3173,45 @@
     break;
 #endif
 
-  case Op_ModI: {
-    Node* di = NULL;
+  case Op_ModI:
     if (UseDivMod) {
       // Check if a%b and a/b both exist
-      di = n->find_similar(Op_DivI);
-      if (di) {
+      Node* d = n->find_similar(Op_DivI);
+      if (d) {
         // Replace them with a fused divmod if supported
         if (Matcher::has_match_rule(Op_DivModI)) {
           DivModINode* divmod = DivModINode::make(n);
-          di->subsume_by(divmod->div_proj(), this);
+          d->subsume_by(divmod->div_proj(), this);
           n->subsume_by(divmod->mod_proj(), this);
         } else {
           // replace a%b with a-((a/b)*b)
-          Node* mult = new MulINode(di, di->in(2));
-          Node* sub  = new SubINode(di->in(1), mult);
+          Node* mult = new MulINode(d, d->in(2));
+          Node* sub  = new SubINode(d->in(1), mult);
           n->subsume_by(sub, this);
         }
       }
     }
-    if (di == NULL) {
-      // Remove useless control edge in case of not mod-zero.
-      const Type *t = n->in(2)->bottom_type();
-      const TypeInt *ti = t->is_int();
-      if (n->in(0) && (ti->_hi < 0 || ti->_lo > 0)) {
-        n->set_req(0, NULL);
-      }
-    }
     break;
-  }
-
-  case Op_ModL: {
-    Node* dl = NULL;
+
+  case Op_ModL:
     if (UseDivMod) {
       // Check if a%b and a/b both exist
-      dl = n->find_similar(Op_DivL);
-      if (dl) {
+      Node* d = n->find_similar(Op_DivL);
+      if (d) {
         // Replace them with a fused divmod if supported
         if (Matcher::has_match_rule(Op_DivModL)) {
           DivModLNode* divmod = DivModLNode::make(n);
-          dl->subsume_by(divmod->div_proj(), this);
+          d->subsume_by(divmod->div_proj(), this);
           n->subsume_by(divmod->mod_proj(), this);
         } else {
           // replace a%b with a-((a/b)*b)
-          Node* mult = new MulLNode(dl, dl->in(2));
-          Node* sub  = new SubLNode(dl->in(1), mult);
+          Node* mult = new MulLNode(d, d->in(2));
+          Node* sub  = new SubLNode(d->in(1), mult);
           n->subsume_by(sub, this);
         }
       }
     }
-    if (dl == NULL) {
-      // Remove useless control edge in case of not mod-zero.
-      const Type *t = n->in(2)->bottom_type();
-      const TypeLong *tl = t->is_long();
-      if (n->in(0) && (tl->_hi < 0 || tl->_lo > 0)) {
-        n->set_req(0, NULL);
-      }
-    }
     break;
-  }
 
   case Op_LoadVector:
   case Op_StoreVector:
--- a/hotspot/src/share/vm/opto/divnode.cpp	Fri Oct 28 19:33:22 2016 +0000
+++ b/hotspot/src/share/vm/opto/divnode.cpp	Mon Oct 31 09:50:12 2016 +0100
@@ -474,16 +474,19 @@
 
   const TypeInt *ti = t->isa_int();
   if( !ti ) return NULL;
+
+  // Check for useless control input
+  // Check for excluding div-zero case
+  if (in(0) && (ti->_hi < 0 || ti->_lo > 0)) {
+    set_req(0, NULL);           // Yank control input
+    return this;
+  }
+
   if( !ti->is_con() ) return NULL;
   jint i = ti->get_con();       // Get divisor
 
   if (i == 0) return NULL;      // Dividing by zero constant does not idealize
 
-  if (in(0) != NULL) {
-    phase->igvn_rehash_node_delayed(this);
-    set_req(0, NULL);           // Dividing by a not-zero constant; no faulting
-  }
-
   // Dividing by MININT does not optimize as a power-of-2 shift.
   if( i == min_jint ) return NULL;
 
@@ -576,16 +579,19 @@
 
   const TypeLong *tl = t->isa_long();
   if( !tl ) return NULL;
+
+  // Check for useless control input
+  // Check for excluding div-zero case
+  if (in(0) && (tl->_hi < 0 || tl->_lo > 0)) {
+    set_req(0, NULL);           // Yank control input
+    return this;
+  }
+
   if( !tl->is_con() ) return NULL;
   jlong l = tl->get_con();      // Get divisor
 
   if (l == 0) return NULL;      // Dividing by zero constant does not idealize
 
-  if (in(0) != NULL) {
-    phase->igvn_rehash_node_delayed(this);
-    set_req(0, NULL);           // Dividing by a not-zero constant; no faulting
-  }
-
   // Dividing by MINLONG does not optimize as a power-of-2 shift.
   if( l == min_jlong ) return NULL;
 
@@ -853,6 +859,13 @@
   if( t == Type::TOP ) return NULL;
   const TypeInt *ti = t->is_int();
 
+  // Check for useless control input
+  // Check for excluding mod-zero case
+  if (in(0) && (ti->_hi < 0 || ti->_lo > 0)) {
+    set_req(0, NULL);        // Yank control input
+    return this;
+  }
+
   // See if we are MOD'ing by 2^k or 2^k-1.
   if( !ti->is_con() ) return NULL;
   jint con = ti->get_con();
@@ -1017,6 +1030,13 @@
   if( t == Type::TOP ) return NULL;
   const TypeLong *tl = t->is_long();
 
+  // Check for useless control input
+  // Check for excluding mod-zero case
+  if (in(0) && (tl->_hi < 0 || tl->_lo > 0)) {
+    set_req(0, NULL);        // Yank control input
+    return this;
+  }
+
   // See if we are MOD'ing by 2^k or 2^k-1.
   if( !tl->is_con() ) return NULL;
   jlong con = tl->get_con();