< prev index next >

src/hotspot/share/opto/cfgnode.cpp

Print this page

        

@@ -41,10 +41,11 @@
 #include "opto/mulnode.hpp"
 #include "opto/phaseX.hpp"
 #include "opto/regmask.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
+#include "opto/valuetypenode.hpp"
 #include "utilities/vmError.hpp"
 
 // Portions of code courtesy of Clifford Click
 
 // Optimization - Graph Style

@@ -370,11 +371,11 @@
   }
 
   return true; // The Region node is unreachable - it is dead.
 }
 
-bool RegionNode::try_clean_mem_phi(PhaseGVN *phase) {
+Node* PhiNode::try_clean_mem_phi(PhaseGVN *phase) {
   // Incremental inlining + PhaseStringOpts sometimes produce:
   //
   // cmpP with 1 top input
   //           |
   //          If

@@ -390,31 +391,30 @@
   // 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.
 
-  PhiNode* phi = has_unique_phi();
-  if (phi && phi->type() == Type::MEMORY && req() == 3 && phi->is_diamond_phi(true)) {
+  if (type() == Type::MEMORY && is_diamond_phi(true)) {
     MergeMemNode* m = NULL;
-    assert(phi->req() == 3, "same as region");
+    assert(req() == 3, "same as region");
+    Node* r = in(0);
     for (uint i = 1; i < 3; ++i) {
-      Node *mem = phi->in(i);
-      if (mem && mem->is_MergeMem() && in(i)->outcnt() == 1) {
+      Node *mem = in(i);
+      if (mem && mem->is_MergeMem() && r->in(i)->outcnt() == 1) {
         // Nothing is control-dependent on path #i except the region itself.
         m = mem->as_MergeMem();
         uint j = 3 - i;
-        Node* other = phi->in(j);
+        Node* other = in(j);
         if (other && other == m->base_memory()) {
           // m is a successor memory to other, and is not pinned inside the diamond, so push it out.
           // This will allow the diamond to collapse completely.
-          phase->is_IterGVN()->replace_node(phi, m);
-          return true;
+          return m;
         }
       }
     }
   }
-  return false;
+  return NULL;
 }
 
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Must preserve
 // the CFG, but we can still strip out dead paths.

@@ -425,12 +425,19 @@
   // 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 && try_clean_mem_phi(phase)) {
-      has_phis = false;
+    if (has_phis) {
+      PhiNode* phi = has_unique_phi();
+      if (phi != NULL) {
+        Node* m = phi->try_clean_mem_phi(phase);
+        if (m != NULL) {
+          phase->is_IterGVN()->replace_node(phi, m);
+          has_phis = false;
+        }
+      }
     }
 
     if (!has_phis) {            // No Phi users?  Nothing merging?
       for (uint i = 1; i < req()-1; i++) {
         Node *if1 = in(i);

@@ -894,11 +901,11 @@
 
 //----------------------------make---------------------------------------------
 // create a new phi with edges matching r and set (initially) to x
 PhiNode* PhiNode::make(Node* r, Node* x, const Type *t, const TypePtr* at) {
   uint preds = r->req();   // Number of predecessor paths
-  assert(t != Type::MEMORY || at == flatten_phi_adr_type(at), "flatten at");
+  assert(t != Type::MEMORY || at == flatten_phi_adr_type(at) || (flatten_phi_adr_type(at) == TypeAryPtr::VALUES && Compile::current()->flattened_accesses_share_alias()), "flatten at");
   PhiNode* p = new PhiNode(r, t, at);
   for (uint j = 1; j < preds; j++) {
     // Fill in all inputs, except those which the region does not yet have
     if (r->in(j) != NULL)
       p->init_req(j, x);

@@ -1104,19 +1111,14 @@
   // convert the one to the other.
   const TypePtr* ttp = _type->make_ptr();
   const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL;
   const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_klassptr() : NULL;
   bool is_intf = false;
-  if (ttip != NULL) {
-    ciKlass* k = ttip->klass();
-    if (k->is_loaded() && k->is_interface())
-      is_intf = true;
-  }
-  if (ttkp != NULL) {
-    ciKlass* k = ttkp->klass();
-    if (k->is_loaded() && k->is_interface())
-      is_intf = true;
+  if (ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
+    is_intf = true;
+  } else if (ttkp != NULL && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
+    is_intf = true;
   }
 
   // Default case: merge all inputs
   const Type *t = Type::TOP;        // Merged type starting value
   for (uint i = 1; i < req(); ++i) {// For all paths in

@@ -1169,13 +1171,13 @@
     // both implement interface I, but their meet is at 'j/l/O' which
     // doesn't implement I, we have no way to tell if the result should
     // be 'I' or 'j/l/O'.  Thus we'll pick 'j/l/O'.  If this then flows
     // into a Phi which "knows" it's an Interface type we'll have to
     // uplift the type.
-    if (!t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface()) {
+    if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
       assert(ft == _type, ""); // Uplift to interface
-    } else if (!t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
+    } else if (!t->empty() && ttkp != NULL && ttkp->is_loaded() && ttkp->klass()->is_interface()) {
       assert(ft == _type, ""); // Uplift to interface
     } else {
       // We also have to handle 'evil cases' of interface- vs. class-arrays
       Type::get_arrays_base_elements(jt, _type, NULL, &ttip);
       if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {

@@ -1333,10 +1335,18 @@
   if (true_path != 0) {
     Node* id = is_cmove_id(phase, true_path);
     if (id != NULL)  return id;
   }
 
+  if (phase->is_IterGVN()) {
+    Node* m = try_clean_mem_phi(phase);
+    if (m != NULL) {
+      return m;
+    }
+  }
+
+
   return this;                     // No identity
 }
 
 //-----------------------------unique_input------------------------------------
 // Find the unique value, discounting top, self-loops, and casts.

@@ -1794,10 +1804,28 @@
   // Note: During parsing, phis are often transformed before their regions.
   // This means we have to use type_or_null to defend against untyped regions.
   if( phase->type_or_null(r) == Type::TOP ) // Dead code?
     return NULL;                // No change
 
+  // If all inputs are value types of the same type, push the value type node down
+  // through the phi because value type nodes should be merged through their input values.
+  if (req() > 2 && in(1) != NULL && in(1)->is_ValueTypeBase() && (can_reshape || in(1)->is_ValueType())) {
+    int opcode = in(1)->Opcode();
+    uint i = 2;
+    // Check if inputs are values of the same type
+    for (; i < req() && in(i) && in(i)->is_ValueTypeBase() && in(i)->cmp(*in(1)); i++) {
+      assert(in(i)->Opcode() == opcode, "mixing pointers and values?");
+    }
+    if (i == req()) {
+      ValueTypeBaseNode* vt = in(1)->as_ValueTypeBase()->clone_with_phis(phase, in(0));
+      for (uint i = 2; i < req(); ++i) {
+        vt->merge_with(phase, in(i)->as_ValueTypeBase(), i, i == (req()-1));
+      }
+      return vt;
+    }
+  }
+
   Node *top = phase->C->top();
   bool new_phi = (outcnt() == 0); // transforming new Phi
   // No change for igvn if new phi is not hooked
   if (new_phi && can_reshape)
     return NULL;

@@ -2501,10 +2529,16 @@
   if( phase->type(in(1)) == Type::TOP ) return in(1);
   if( phase->type(in(0)) == Type::TOP ) return in(0);
   // We only come from CatchProj, unless the CatchProj goes away.
   // If the CatchProj is optimized away, then we just carry the
   // exception oop through.
+
+  // CheckCastPPNode::Ideal() for value types reuses the exception
+  // paths of a call to perform an allocation: we can see a Phi here.
+  if (in(1)->is_Phi()) {
+    return this;
+  }
   CallNode *call = in(1)->in(0)->as_Call();
 
   return ( in(0)->is_CatchProj() && in(0)->in(0)->in(1) == in(1) )
     ? this
     : call->in(TypeFunc::Parms);
< prev index next >