diff src/share/vm/opto/parse1.cpp @ 2383:9dc311b8473e

7008866: Missing loop predicate for loop with multiple entries Summary: Add predicates when loop head bytecode is parsed instead of when back branch bytecode is parsed. Reviewed-by: never
author kvn
date Mon, 21 Mar 2011 11:28:14 -0700
parents f95d63e2154a
children 1d1603768966
line wrap: on
line diff
--- a/src/share/vm/opto/parse1.cpp	Mon Mar 21 02:30:49 2011 -0700
+++ b/src/share/vm/opto/parse1.cpp	Mon Mar 21 11:28:14 2011 -0700
@@ -637,6 +637,25 @@
         // (Note that dead locals do not get phis built, ever.)
         ensure_phis_everywhere();
 
+        if (block->is_SEL_head() &&
+            UseLoopPredicate) {
+          // Add predicate to single entry (not irreducible) loop head.
+          assert(!block->has_merged_backedge(), "only entry paths should be merged for now");
+          // Need correct bci for predicate.
+          // It is fine to set it here since do_one_block() will set it anyway.
+          set_parse_bci(block->start());
+          add_predicate();
+          // Add new region for back branches.
+          int edges = block->pred_count() - block->preds_parsed() + 1; // +1 for original region
+          RegionNode *r = new (C, edges+1) RegionNode(edges+1);
+          _gvn.set_type(r, Type::CONTROL);
+          record_for_igvn(r);
+          r->init_req(edges, control());
+          set_control(r);
+          // Add new phis.
+          ensure_phis_everywhere();
+        }
+
         // Leave behind an undisturbed copy of the map, for future merges.
         set_map(clone_map());
       }
@@ -1113,7 +1132,7 @@
   _preds_parsed = 0;
   _count = 0;
   assert(pred_count() == 0 && preds_parsed() == 0, "sanity");
-  assert(!(is_merged() || is_parsed() || is_handler()), "sanity");
+  assert(!(is_merged() || is_parsed() || is_handler() || has_merged_backedge()), "sanity");
   assert(_live_locals.size() == 0, "sanity");
 
   // entry point has additional predecessor
@@ -1350,10 +1369,6 @@
     set_parse_bci(iter().cur_bci());
 
     if (bci() == block()->limit()) {
-      // insert a predicate if it falls through to a loop head block
-      if (should_add_predicate(bci())){
-        add_predicate();
-      }
       // Do not walk into the next block until directed by do_all_blocks.
       merge(bci());
       break;
@@ -1498,17 +1513,29 @@
         || target->is_handler()       // These have unpredictable inputs.
         || target->is_loop_head()     // Known multiple inputs
         || control()->is_Region()) {  // We must hide this guy.
+
+      int current_bci = bci();
+      set_parse_bci(target->start()); // Set target bci
+      if (target->is_SEL_head()) {
+        DEBUG_ONLY( target->mark_merged_backedge(block()); )
+        if (target->start() == 0) {
+          // Add loop predicate for the special case when
+          // there are backbranches to the method entry.
+          add_predicate();
+        }
+      }
       // Add a Region to start the new basic block.  Phis will be added
       // later lazily.
       int edges = target->pred_count();
       if (edges < pnum)  edges = pnum;  // might be a new path!
-      Node *r = new (C, edges+1) RegionNode(edges+1);
+      RegionNode *r = new (C, edges+1) RegionNode(edges+1);
       gvn().set_type(r, Type::CONTROL);
       record_for_igvn(r);
       // zap all inputs to NULL for debugging (done in Node(uint) constructor)
       // for (int j = 1; j < edges+1; j++) { r->init_req(j, NULL); }
       r->init_req(pnum, control());
       set_control(r);
+      set_parse_bci(current_bci); // Restore bci
     }
 
     // Convert the existing Parser mapping into a mapping at this bci.
@@ -1517,7 +1544,11 @@
 
   } else {                      // Prior mapping at this bci
     if (TraceOptoParse) {  tty->print(" with previous state"); }
-
+#ifdef ASSERT
+    if (target->is_SEL_head()) {
+      target->mark_merged_backedge(block());
+    }
+#endif
     // We must not manufacture more phis if the target is already parsed.
     bool nophi = target->is_parsed();
 
@@ -2054,37 +2085,6 @@
   }
 }
 
-//------------------------------should_add_predicate--------------------------
-bool Parse::should_add_predicate(int target_bci) {
-  if (!UseLoopPredicate) return false;
-  Block* target = successor_for_bci(target_bci);
-  if (target != NULL          &&
-      target->is_loop_head()  &&
-      block()->rpo() < target->rpo()) {
-    return true;
-  }
-  return false;
-}
-
-//------------------------------add_predicate---------------------------------
-void Parse::add_predicate() {
-  assert(UseLoopPredicate,"use only for loop predicate");
-  Node *cont    = _gvn.intcon(1);
-  Node* opq     = _gvn.transform(new (C, 2) Opaque1Node(C, cont));
-  Node *bol     = _gvn.transform(new (C, 2) Conv2BNode(opq));
-  IfNode* iff   = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN);
-  Node* iffalse = _gvn.transform(new (C, 1) IfFalseNode(iff));
-  C->add_predicate_opaq(opq);
-  {
-    PreserveJVMState pjvms(this);
-    set_control(iffalse);
-    uncommon_trap(Deoptimization::Reason_predicate,
-                  Deoptimization::Action_maybe_recompile);
-  }
-  Node* iftrue = _gvn.transform(new (C, 1) IfTrueNode(iff));
-  set_control(iftrue);
-}
-
 #ifndef PRODUCT
 //------------------------show_parse_info--------------------------------------
 void Parse::show_parse_info() {