8211451: ~2.5% regression on compression benchmark starting with 12-b11
authorroland
Thu, 08 Nov 2018 10:20:04 +0100
changeset 52608 61241fc2217a
parent 52607 da785658408b
child 52609 83b1d9797b20
8211451: ~2.5% regression on compression benchmark starting with 12-b11 Reviewed-by: kvn, thartmann
src/hotspot/share/opto/loopPredicate.cpp
src/hotspot/share/opto/loopTransform.cpp
src/hotspot/share/opto/loopnode.cpp
src/hotspot/share/opto/loopnode.hpp
--- a/src/hotspot/share/opto/loopPredicate.cpp	Mon Nov 19 13:49:50 2018 +0100
+++ b/src/hotspot/share/opto/loopPredicate.cpp	Thu Nov 08 10:20:04 2018 +0100
@@ -370,9 +370,9 @@
 
 // Clone loop predicates to cloned loops (peeled, unswitched, split_if).
 Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry,
-                                                bool clone_limit_check,
-                                                PhaseIdealLoop* loop_phase,
-                                                PhaseIterGVN* igvn) {
+                                            bool clone_limit_check,
+                                            PhaseIdealLoop* loop_phase,
+                                            PhaseIterGVN* igvn) {
 #ifdef ASSERT
   if (new_entry == NULL || !(new_entry->is_Proj() || new_entry->is_Region() || new_entry->is_SafePoint())) {
     if (new_entry != NULL)
@@ -385,7 +385,7 @@
   ProjNode* limit_check_proj = NULL;
   limit_check_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
   if (limit_check_proj != NULL) {
-    entry = entry->in(0)->in(0);
+    entry = skip_loop_predicates(entry);
   }
   ProjNode* profile_predicate_proj = NULL;
   ProjNode* predicate_proj = NULL;
@@ -467,7 +467,7 @@
   Node* predicate = NULL;
   predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
   if (predicate != NULL) {
-    entry = entry->in(0)->in(0);
+    entry = skip_loop_predicates(entry);
   }
   if (UseProfiledLoopPredicate) {
     predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_profile_predicate);
@@ -1363,7 +1363,7 @@
   // Loop limit check predicate should be near the loop.
   loop_limit_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
   if (loop_limit_proj != NULL) {
-    entry = loop_limit_proj->in(0)->in(0);
+    entry = skip_loop_predicates(loop_limit_proj);
   }
   bool has_profile_predicates = false;
   profile_predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_profile_predicate);
--- a/src/hotspot/share/opto/loopTransform.cpp	Mon Nov 19 13:49:50 2018 +0100
+++ b/src/hotspot/share/opto/loopTransform.cpp	Thu Nov 08 10:20:04 2018 +0100
@@ -1200,7 +1200,7 @@
     Node* predicate = NULL;
     predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
     if (predicate != NULL) {
-      entry = entry->in(0)->in(0);
+      entry = skip_loop_predicates(entry);
     }
     Node* profile_predicate = NULL;
     if (UseProfiledLoopPredicate) {
--- a/src/hotspot/share/opto/loopnode.cpp	Mon Nov 19 13:49:50 2018 +0100
+++ b/src/hotspot/share/opto/loopnode.cpp	Thu Nov 08 10:20:04 2018 +0100
@@ -324,6 +324,31 @@
   return outer_ilt;
 }
 
+void PhaseIdealLoop::insert_loop_limit_check(ProjNode* limit_check_proj, Node* cmp_limit, Node* bol) {
+  Node* new_predicate_proj = create_new_if_for_predicate(limit_check_proj, NULL,
+                                                         Deoptimization::Reason_loop_limit_check,
+                                                         Op_If);
+  Node* iff = new_predicate_proj->in(0);
+  assert(iff->Opcode() == Op_If, "bad graph shape");
+  Node* conv = iff->in(1);
+  assert(conv->Opcode() == Op_Conv2B, "bad graph shape");
+  Node* opaq = conv->in(1);
+  assert(opaq->Opcode() == Op_Opaque1, "bad graph shape");
+  cmp_limit = _igvn.register_new_node_with_optimizer(cmp_limit);
+  bol = _igvn.register_new_node_with_optimizer(bol);
+  set_subtree_ctrl(bol);
+  _igvn.replace_input_of(iff, 1, bol);
+
+#ifndef PRODUCT
+  // report that the loop predication has been actually performed
+  // for this loop
+  if (TraceLoopLimitCheck) {
+    tty->print_cr("Counted Loop Limit Check generated:");
+    debug_only( bol->dump(2); )
+  }
+#endif
+}
+
 //------------------------------is_counted_loop--------------------------------
 bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*& loop) {
   PhaseGVN *gvn = &_igvn;
@@ -540,7 +565,7 @@
       return false; // cyclic loop or this loop trips only once
   }
 
-  if (phi_incr != NULL) {
+  if (phi_incr != NULL && bt != BoolTest::ne) {
     // check if there is a possiblity of IV overflowing after the first increment
     if (stride_con > 0) {
       if (init_t->_hi > max_jint - stride_con) {
@@ -631,28 +656,60 @@
       cmp_limit = new CmpINode(limit, _igvn.intcon(min_jint - stride_m));
       bol = new BoolNode(cmp_limit, BoolTest::ge);
     }
-    cmp_limit = _igvn.register_new_node_with_optimizer(cmp_limit);
-    bol = _igvn.register_new_node_with_optimizer(bol);
-    set_subtree_ctrl(bol);
-
-    // Replace condition in original predicate but preserve Opaque node
-    // so that previous predicates could be found.
-    assert(check_iff->in(1)->Opcode() == Op_Conv2B &&
-           check_iff->in(1)->in(1)->Opcode() == Op_Opaque1, "");
-    Node* opq = check_iff->in(1)->in(1);
-    _igvn.replace_input_of(opq, 1, bol);
-    // Update ctrl.
-    set_ctrl(opq, check_iff->in(0));
-    set_ctrl(check_iff->in(1), check_iff->in(0));
-
-#ifndef PRODUCT
-    // report that the loop predication has been actually performed
-    // for this loop
-    if (TraceLoopLimitCheck) {
-      tty->print_cr("Counted Loop Limit Check generated:");
-      debug_only( bol->dump(2); )
+
+    insert_loop_limit_check(limit_check_proj, cmp_limit, bol);
+  }
+
+  // Now we need to canonicalize loop condition.
+  if (bt == BoolTest::ne) {
+    assert(stride_con == 1 || stride_con == -1, "simple increment only");
+    if (stride_con > 0 && init_t->_hi < limit_t->_lo) {
+      // 'ne' can be replaced with 'lt' only when init < limit.
+      bt = BoolTest::lt;
+    } else if (stride_con < 0 && init_t->_lo > limit_t->_hi) {
+      // 'ne' can be replaced with 'gt' only when init > limit.
+      bt = BoolTest::gt;
+    } else {
+      ProjNode *limit_check_proj = find_predicate_insertion_point(init_control, Deoptimization::Reason_loop_limit_check);
+      if (!limit_check_proj) {
+        // The limit check predicate is not generated if this method trapped here before.
+#ifdef ASSERT
+        if (TraceLoopLimitCheck) {
+          tty->print("missing loop limit check:");
+          loop->dump_head();
+          x->dump(1);
+        }
+#endif
+        return false;
+      }
+      IfNode* check_iff = limit_check_proj->in(0)->as_If();
+
+      if (!is_dominator(get_ctrl(limit), check_iff->in(0)) ||
+          !is_dominator(get_ctrl(init_trip), check_iff->in(0))) {
+        return false;
+      }
+
+      Node* cmp_limit;
+      Node* bol;
+
+      if (stride_con > 0) {
+        cmp_limit = new CmpINode(init_trip, limit);
+        bol = new BoolNode(cmp_limit, BoolTest::lt);
+      } else {
+        cmp_limit = new CmpINode(init_trip, limit);
+        bol = new BoolNode(cmp_limit, BoolTest::gt);
+      }
+
+      insert_loop_limit_check(limit_check_proj, cmp_limit, bol);
+
+      if (stride_con > 0) {
+        // 'ne' can be replaced with 'lt' only when init < limit.
+        bt = BoolTest::lt;
+      } else if (stride_con < 0) {
+        // 'ne' can be replaced with 'gt' only when init > limit.
+        bt = BoolTest::gt;
+      }
     }
-#endif
   }
 
   if (phi_incr != NULL) {
@@ -668,17 +725,6 @@
     limit = gvn->transform(new AddINode(limit, stride));
   }
 
-  // Now we need to canonicalize loop condition.
-  if (bt == BoolTest::ne) {
-    assert(stride_con == 1 || stride_con == -1, "simple increment only");
-    // 'ne' can be replaced with 'lt' only when init < limit.
-    if (stride_con > 0 && init_t->_hi < limit_t->_lo)
-      bt = BoolTest::lt;
-    // 'ne' can be replaced with 'gt' only when init > limit.
-    if (stride_con < 0 && init_t->_lo > limit_t->_hi)
-      bt = BoolTest::gt;
-  }
-
   if (incl_limit) {
     // The limit check guaranties that 'limit <= (max_jint - stride)' so
     // we can convert 'i <= limit' to 'i < limit+1' since stride != 0.
@@ -2404,7 +2450,7 @@
   Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
   if (predicate != NULL ) {
     tty->print(" limit_check");
-    entry = entry->in(0)->in(0);
+    entry = PhaseIdealLoop::skip_loop_predicates(entry);
   }
   if (UseLoopPredicate) {
     entry = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
--- a/src/hotspot/share/opto/loopnode.hpp	Mon Nov 19 13:49:50 2018 +0100
+++ b/src/hotspot/share/opto/loopnode.hpp	Thu Nov 08 10:20:04 2018 +0100
@@ -749,6 +749,7 @@
                             LoopNode* outer_main_head, uint dd_main_head);
   Node* update_skeleton_predicate(Node* iff, Node* value, Node* predicate = NULL, Node* uncommon_proj = NULL,
                                   Node* current_proj = NULL, IdealLoopTree* outer_loop = NULL, Node* prev_proj = NULL);
+  void insert_loop_limit_check(ProjNode* limit_check_proj, Node* cmp_limit, Node* bol);
 
 public: