src/share/vm/opto/cfgnode.cpp

Print this page
rev 3904 : 8005071: Incremental inlining for JSR 292
Summary: post parse inlining driven by number of live nodes.
Reviewed-by:

@@ -361,10 +361,68 @@
   }
 
   return true; // The Region node is unreachable - it is dead.
 }
 
+bool RegionNode::try_clean_mem_phi(PhaseGVN *phase) {
+  // Incremental inlining + PhaseStringOpts sometimes produce:
+  //
+  //                              Some Node \
+  //                               \         Phi
+  //                               MergeMem /  /
+  //                                          /
+  //                              IfFalse    /
+  // cmpP with 1 top input -- If /       \ Region
+  //                             \       /
+  //                              IfTrue
+  //
+  // It's expected by PhaseStringOpts that the Region goes away and is
+  // replaced by If's control input but because there's still a Phi,
+  // the Region stays in the graph. The top input from the cmpP is
+  // propagated forward and a subgraph that is useful goes away. The
+  // code below replaces the Phi with the MergeMem so that the Region
+  // is simplified.
+
+  Node* phi = NULL;
+  for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+    Node* n = fast_out(i);
+    if (n->is_Phi()) {
+      if (phi == NULL) {
+        phi = n;
+      } else if (phi != n) {
+        return true; // more than one phi
+      }
+    }
+  }
+    
+  if (phi->as_Phi()->type() == Type::MEMORY && req() == 3 && in(1) && in(2) && in(1)->in(0) == in(2)->in(0)) {
+    MergeMemNode* m = NULL;
+    for(uint i=1; i<phi->req(); ++i) {
+      Node *ii = phi->in(i);
+
+      if (ii && ii->is_MergeMem() && in(i)->outcnt() == 1) {
+        m = ii->as_MergeMem();
+        
+        bool ok = true;
+        for(uint i=1; i<phi->req(); ++i) {
+          Node *ii = phi->in(i);
+          if (ii == NULL || ii == m) continue;
+          if (ii != m->base_memory() || (ii->is_MergeMem() && in(i)->outcnt() > 1)) {
+            ok = false;
+            break;
+          }
+        }
+        if (ok) {
+          phase->is_IterGVN()->replace_node(phi, m);
+          return false;
+        }
+      }
+    }
+  }
+  return true;
+}
+
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Must preserve
 // the CFG, but we can still strip out dead paths.
 Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
   if( !can_reshape && !in(0) ) return NULL;     // Already degraded to a Copy

@@ -373,10 +431,14 @@
   // Check for RegionNode with no Phi users and both inputs come from either
   // arm of the same IF.  If found, then the control-flow split is useless.
   bool has_phis = false;
   if (can_reshape) {            // Need DU info to check for Phi users
     has_phis = (has_phi() != NULL);       // Cache result
+    if (has_phis) {
+      has_phis = try_clean_mem_phi(phase);
+    }
+
     if (!has_phis) {            // No Phi users?  Nothing merging?
       for (uint i = 1; i < req()-1; i++) {
         Node *if1 = in(i);
         if( !if1 ) continue;
         Node *iff = if1->in(0);