8139771: Eliminating CastPP nodes at Phis when they all come from a unique input may cause crash
authorroland
Fri, 11 Dec 2015 16:57:08 +0100
changeset 35545 a8f29dfd62b2
parent 35544 c7ec868d0923
child 35546 b75e269c0922
8139771: Eliminating CastPP nodes at Phis when they all come from a unique input may cause crash Summary: Lost dependency when CastPP at Phis are eliminate Reviewed-by: kvn
hotspot/src/share/vm/opto/block.hpp
hotspot/src/share/vm/opto/castnode.cpp
hotspot/src/share/vm/opto/castnode.hpp
hotspot/src/share/vm/opto/cfgnode.cpp
hotspot/src/share/vm/opto/cfgnode.hpp
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/gcm.cpp
hotspot/src/share/vm/opto/loopopts.cpp
hotspot/src/share/vm/opto/node.cpp
hotspot/src/share/vm/opto/phaseX.cpp
hotspot/src/share/vm/opto/phaseX.hpp
hotspot/test/compiler/controldependency/TestEliminatedCastPPAtPhi.java
--- a/hotspot/src/share/vm/opto/block.hpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/block.hpp	Fri Dec 11 16:57:08 2015 +0100
@@ -499,6 +499,7 @@
   void convert_NeverBranch_to_Goto(Block *b);
 
   CFGLoop* create_loop_tree();
+  bool is_dominator(Node* dom_node, Node* node);
 
   #ifndef PRODUCT
   bool _trace_opto_pipelining;  // tracing flag
--- a/hotspot/src/share/vm/opto/castnode.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/castnode.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "opto/addnode.hpp"
+#include "opto/callnode.hpp"
 #include "opto/castnode.hpp"
 #include "opto/connode.hpp"
 #include "opto/matcher.hpp"
@@ -33,14 +34,22 @@
 
 //=============================================================================
 // If input is already higher or equal to cast type, then this is an identity.
-Node *ConstraintCastNode::Identity( PhaseTransform *phase ) {
+Node *ConstraintCastNode::Identity(PhaseTransform *phase) {
+  Node* dom = dominating_cast(phase);
+  if (dom != NULL) {
+    assert(_carry_dependency, "only for casts that carry a dependency");
+    return dom;
+  }
+  if (_carry_dependency) {
+    return this;
+  }
   return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this;
 }
 
 //------------------------------Value------------------------------------------
 // Take 'join' of input and cast-up type
-const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
-  if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
+const Type *ConstraintCastNode::Value(PhaseTransform *phase) const {
+  if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
   const Type* ft = phase->type(in(1))->filter_speculative(_type);
 
 #ifdef ASSERT
@@ -69,24 +78,76 @@
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Strip out
 // control copies
-Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape){
+Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape) {
   return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
 }
 
-uint CastIINode::size_of() const {
+uint ConstraintCastNode::cmp(const Node &n) const {
+  return TypeNode::cmp(n) && ((ConstraintCastNode&)n)._carry_dependency == _carry_dependency;
+}
+
+uint ConstraintCastNode::size_of() const {
   return sizeof(*this);
 }
 
-uint CastIINode::cmp(const Node &n) const {
-  return TypeNode::cmp(n) && ((CastIINode&)n)._carry_dependency == _carry_dependency;
+Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t, bool carry_dependency) {
+  switch(opcode) {
+  case Op_CastII: {
+    Node* cast = new CastIINode(n, t, carry_dependency);
+    cast->set_req(0, c);
+    return cast;
+  }
+  case Op_CastPP: {
+    Node* cast = new CastPPNode(n, t, carry_dependency);
+    cast->set_req(0, c);
+    return cast;
+  }
+  case Op_CheckCastPP: return new CheckCastPPNode(c, n, t, carry_dependency);
+  default:
+    fatal("Bad opcode %d", opcode);
+  }
+  return NULL;
 }
 
-Node *CastIINode::Identity(PhaseTransform *phase) {
+TypeNode* ConstraintCastNode::dominating_cast(PhaseTransform *phase) const {
+  if (!carry_dependency()) {
+    return NULL;
+  }
+  Node* val = in(1);
+  Node* ctl = in(0);
+  int opc = Opcode();
+  if (ctl == NULL) {
+    return NULL;
+  }
+  for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
+    Node* u = val->fast_out(i);
+    if (u != this &&
+        u->Opcode() == opc &&
+        u->in(0) != NULL &&
+        u->bottom_type()->higher_equal(type())) {
+      if (phase->is_dominator(u->in(0), ctl)) {
+        return u->as_Type();
+      }
+      if (is_CheckCastPP() && u->in(1)->is_Proj() && u->in(1)->in(0)->is_Allocate() &&
+          u->in(0)->is_Proj() && u->in(0)->in(0)->is_Initialize() &&
+          u->in(1)->in(0)->as_Allocate()->initialization() == u->in(0)->in(0)) {
+        // CheckCastPP following an allocation always dominates all
+        // use of the allocation result
+        return u->as_Type();
+      }
+    }
+  }
+  return NULL;
+}
+
+#ifndef PRODUCT
+void ConstraintCastNode::dump_spec(outputStream *st) const {
+  TypeNode::dump_spec(st);
   if (_carry_dependency) {
-    return this;
+    st->print(" carry dependency");
   }
-  return ConstraintCastNode::Identity(phase);
 }
+#endif
 
 const Type *CastIINode::Value(PhaseTransform *phase) const {
   const Type *res = ConstraintCastNode::Value(phase);
@@ -154,19 +215,18 @@
   return res;
 }
 
-#ifndef PRODUCT
-void CastIINode::dump_spec(outputStream *st) const {
-  TypeNode::dump_spec(st);
-  if (_carry_dependency) {
-    st->print(" carry dependency");
-  }
-}
-#endif
-
 //=============================================================================
 //------------------------------Identity---------------------------------------
 // If input is already higher or equal to cast type, then this is an identity.
 Node *CheckCastPPNode::Identity( PhaseTransform *phase ) {
+  Node* dom = dominating_cast(phase);
+  if (dom != NULL) {
+    assert(_carry_dependency, "only for casts that carry a dependency");
+    return dom;
+  }
+  if (_carry_dependency) {
+    return this;
+  }
   // Toned down to rescue meeting at a Phi 3 different oops all implementing
   // the same interface.  CompileTheWorld starting at 502, kd12rc1.zip.
   return (phase->type(in(1)) == phase->type(this)) ? in(1) : this;
@@ -255,13 +315,6 @@
   // return join;
 }
 
-//------------------------------Ideal------------------------------------------
-// Return a node which is more "ideal" than the current node.  Strip out
-// control copies
-Node *CheckCastPPNode::Ideal(PhaseGVN *phase, bool can_reshape){
-  return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL;
-}
-
 //=============================================================================
 //------------------------------Value------------------------------------------
 const Type *CastX2PNode::Value( PhaseTransform *phase ) const {
--- a/hotspot/src/share/vm/opto/castnode.hpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/castnode.hpp	Fri Dec 11 16:57:08 2015 +0100
@@ -32,8 +32,15 @@
 //------------------------------ConstraintCastNode-----------------------------
 // cast to a different range
 class ConstraintCastNode: public TypeNode {
+  protected:
+  // Can this node be removed post CCP or does it carry a required dependency?
+  const bool _carry_dependency;
+  virtual uint cmp( const Node &n ) const;
+  virtual uint size_of() const;
+
   public:
-  ConstraintCastNode (Node *n, const Type *t ): TypeNode(t,2) {
+  ConstraintCastNode(Node *n, const Type *t, bool carry_dependency)
+    : TypeNode(t,2), _carry_dependency(carry_dependency) {
     init_class_id(Class_ConstraintCast);
     init_req(1, n);
   }
@@ -42,53 +49,50 @@
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
   virtual int Opcode() const;
   virtual uint ideal_reg() const = 0;
+  virtual bool depends_only_on_test() const { return !_carry_dependency; }
+  bool carry_dependency() const { return _carry_dependency; }
+  TypeNode* dominating_cast(PhaseTransform *phase) const;
+  static Node* make_cast(int opcode,  Node* c, Node *n, const Type *t, bool carry_dependency);
+
+#ifndef PRODUCT
+  virtual void dump_spec(outputStream *st) const;
+#endif
 };
 
 //------------------------------CastIINode-------------------------------------
 // cast integer to integer (different range)
 class CastIINode: public ConstraintCastNode {
-  private:
-  // Can this node be removed post CCP or does it carry a required dependency?
-  const bool _carry_dependency;
-
-  protected:
-  virtual uint cmp( const Node &n ) const;
-  virtual uint size_of() const;
-
   public:
   CastIINode(Node *n, const Type *t, bool carry_dependency = false)
-    : ConstraintCastNode(n,t), _carry_dependency(carry_dependency) {}
+    : ConstraintCastNode(n, t, carry_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
-  virtual Node *Identity( PhaseTransform *phase );
   virtual const Type *Value( PhaseTransform *phase ) const;
-#ifndef PRODUCT
-  virtual void dump_spec(outputStream *st) const;
-#endif
 };
 
 //------------------------------CastPPNode-------------------------------------
 // cast pointer to pointer (different type)
 class CastPPNode: public ConstraintCastNode {
   public:
-  CastPPNode (Node *n, const Type *t ): ConstraintCastNode(n, t) {}
+  CastPPNode (Node *n, const Type *t, bool carry_dependency = false)
+    : ConstraintCastNode(n, t, carry_dependency) {
+  }
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegP; }
 };
 
 //------------------------------CheckCastPPNode--------------------------------
 // for _checkcast, cast pointer to pointer (different type), without JOIN,
-class CheckCastPPNode: public TypeNode {
+class CheckCastPPNode: public ConstraintCastNode {
   public:
-  CheckCastPPNode( Node *c, Node *n, const Type *t ) : TypeNode(t,2) {
+  CheckCastPPNode(Node *c, Node *n, const Type *t, bool carry_dependency = false)
+    : ConstraintCastNode(n, t, carry_dependency) {
     init_class_id(Class_CheckCastPP);
     init_req(0, c);
-    init_req(1, n);
   }
 
-  virtual Node *Identity( PhaseTransform *phase );
-  virtual const Type *Value( PhaseTransform *phase ) const;
-  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+  virtual Node *Identity(PhaseTransform *phase);
+  virtual const Type *Value(PhaseTransform *phase) const;
   virtual int   Opcode() const;
   virtual uint  ideal_reg() const { return Op_RegP; }
 };
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -27,6 +27,7 @@
 #include "memory/allocation.inline.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "opto/addnode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/connode.hpp"
 #include "opto/convertnode.hpp"
@@ -1148,7 +1149,7 @@
   // It would check for a tributary phi on the backedge that the main phi
   // trivially, perhaps with a single cast.  The unique_input method
   // does all this and more, by reducing such tributaries to 'this'.)
-  Node* uin = unique_input(phase);
+  Node* uin = unique_input(phase, false);
   if (uin != NULL) {
     return uin;
   }
@@ -1165,8 +1166,9 @@
 //-----------------------------unique_input------------------------------------
 // Find the unique value, discounting top, self-loops, and casts.
 // Return top if there are no inputs, and self if there are multiple.
-Node* PhiNode::unique_input(PhaseTransform* phase) {
-  //  1) One unique direct input, or
+Node* PhiNode::unique_input(PhaseTransform* phase, bool uncast) {
+  //  1) One unique direct input,
+  // or if uncast is true:
   //  2) some of the inputs have an intervening ConstraintCast and
   //     the type of input is the same or sharper (more specific)
   //     than the phi's type.
@@ -1180,8 +1182,7 @@
 
   Node* r = in(0);                      // RegionNode
   if (r == NULL)  return in(1);         // Already degraded to a Copy
-  Node* uncasted_input = NULL; // The unique uncasted input (ConstraintCasts removed)
-  Node* direct_input   = NULL; // The unique direct input
+  Node* input = NULL; // The unique direct input (maybe uncasted = ConstraintCasts removed)
 
   for (uint i = 1, cnt = req(); i < cnt; ++i) {
     Node* rc = r->in(i);
@@ -1190,34 +1191,23 @@
     Node* n = in(i);
     if (n == NULL)
       continue;
-    Node* un = n->uncast();
+    Node* un = uncast ? n->uncast() : n;
     if (un == NULL || un == this || phase->type(un) == Type::TOP) {
       continue; // ignore if top, or in(i) and "this" are in a data cycle
     }
-    // Check for a unique uncasted input
-    if (uncasted_input == NULL) {
-      uncasted_input = un;
-    } else if (uncasted_input != un) {
-      uncasted_input = NodeSentinel; // no unique uncasted input
-    }
-    // Check for a unique direct input
-    if (direct_input == NULL) {
-      direct_input = n;
-    } else if (direct_input != n) {
-      direct_input = NodeSentinel; // no unique direct input
+    // Check for a unique input (maybe uncasted)
+    if (input == NULL) {
+      input = un;
+    } else if (input != un) {
+      input = NodeSentinel; // no unique input
     }
   }
-  if (direct_input == NULL) {
+  if (input == NULL) {
     return phase->C->top();        // no inputs
   }
-  assert(uncasted_input != NULL,"");
 
-  if (direct_input != NodeSentinel) {
-    return direct_input;           // one unique direct input
-  }
-  if (uncasted_input != NodeSentinel &&
-      phase->type(uncasted_input)->higher_equal(type())) {
-    return uncasted_input;         // one unique uncasted input
+  if (input != NodeSentinel) {
+    return input;           // one unique direct input
   }
 
   // Nothing.
@@ -1650,7 +1640,12 @@
     return top;
   }
 
-  Node* uin = unique_input(phase);
+  bool uncasted = false;
+  Node* uin = unique_input(phase, false);
+  if (uin == NULL) {
+    uncasted = true;
+    uin = unique_input(phase, true);
+  }
   if (uin == top) {             // Simplest case: no alive inputs.
     if (can_reshape)            // IGVN transformation
       return top;
@@ -1683,6 +1678,31 @@
       }
     }
 
+    if (uncasted) {
+      const Type* phi_type = bottom_type();
+      assert(phi_type->isa_int() || phi_type->isa_ptr(), "bad phi type");
+      int opcode;
+      if (phi_type->isa_int()) {
+        opcode = Op_CastII;
+      } else {
+        const Type* uin_type = phase->type(uin);
+        if (phi_type->join(TypePtr::NOTNULL) == uin_type->join(TypePtr::NOTNULL)) {
+          opcode = Op_CastPP;
+        } else {
+          opcode = Op_CheckCastPP;
+        }
+      }
+      // Add a cast to carry the control dependency of the Phi that is
+      // going away
+      Node* cast = ConstraintCastNode::make_cast(opcode, r, uin, phi_type, true);
+      cast = phase->transform(cast);
+      // set all inputs to the new cast so the Phi is removed by Identity
+      for (uint i = 1; i < req(); i++) {
+        set_req(i, cast);
+      }
+      uin = cast;
+    }
+
     // One unique input.
     debug_only(Node* ident = Identity(phase));
     // The unique input must eventually be detected by the Identity call.
@@ -1699,7 +1719,6 @@
     return NULL;
   }
 
-
   Node* opt = NULL;
   int true_path = is_diamond_phi();
   if( true_path != 0 ) {
--- a/hotspot/src/share/vm/opto/cfgnode.hpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/cfgnode.hpp	Fri Dec 11 16:57:08 2015 +0100
@@ -175,7 +175,14 @@
 
   // Determine a unique non-trivial input, if any.
   // Ignore casts if it helps.  Return NULL on failure.
-  Node* unique_input(PhaseTransform *phase);
+  Node* unique_input(PhaseTransform *phase, bool uncast);
+  Node* unique_input(PhaseTransform *phase) {
+    Node* uin = unique_input(phase, false);
+    if (uin == NULL) {
+      uin = unique_input(phase, true);
+    }
+    return uin;
+  }
 
   // Check for a simple dead loop.
   enum LoopSafety { Safe = 0, Unsafe, UnsafeLoop };
--- a/hotspot/src/share/vm/opto/compile.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/compile.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -2296,17 +2296,17 @@
   DEBUG_ONLY( _modified_nodes = NULL; )
  } // (End scope of igvn; run destructor if necessary for asserts.)
 
-  process_print_inlining();
-  // A method with only infinite loops has no edges entering loops from root
-  {
-    TracePhase tp("graphReshape", &timers[_t_graphReshaping]);
-    if (final_graph_reshaping()) {
-      assert(failing(), "must bail out w/ explicit message");
-      return;
-    }
-  }
-
-  print_method(PHASE_OPTIMIZE_FINISHED, 2);
+ process_print_inlining();
+ // A method with only infinite loops has no edges entering loops from root
+ {
+   TracePhase tp("graphReshape", &timers[_t_graphReshaping]);
+   if (final_graph_reshaping()) {
+     assert(failing(), "must bail out w/ explicit message");
+     return;
+   }
+ }
+
+ print_method(PHASE_OPTIMIZE_FINISHED, 2);
 }
 
 
@@ -2874,7 +2874,7 @@
           Node* use = m->fast_out(i);
           if (use->is_Mem() || use->is_EncodeNarrowPtr()) {
             use->ensure_control_or_add_prec(n->in(0));
-          } else if (use->in(0) == NULL) {
+          } else {
             switch(use->Opcode()) {
             case Op_AddP:
             case Op_DecodeN:
--- a/hotspot/src/share/vm/opto/gcm.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -101,7 +101,32 @@
   }
 }
 
-static bool is_dominator(Block* d, Block* n) {
+bool PhaseCFG::is_dominator(Node* dom_node, Node* node) {
+  if (dom_node == node) {
+    return true;
+  }
+  Block* d = get_block_for_node(dom_node);
+  Block* n = get_block_for_node(node);
+  if (d == n) {
+    if (dom_node->is_block_start()) {
+      return true;
+    }
+    if (node->is_block_start()) {
+      return false;
+    }
+    if (dom_node->is_block_proj()) {
+      return false;
+    }
+    if (node->is_block_proj()) {
+      return true;
+    }
+#ifdef ASSERT
+    node->dump();
+    dom_node->dump();
+#endif
+    fatal("unhandled");
+    return false;
+  }
   return d->dom_lca(n) == d;
 }
 
@@ -145,19 +170,15 @@
           if (n == NULL) {
             n = m;
           } else {
-            Block* bn = get_block_for_node(n);
-            Block* bm = get_block_for_node(m);
-            assert(is_dominator(bn, bm) || is_dominator(bm, bn), "one must dominate the other");
-            n = is_dominator(bn, bm) ? m : n;
+            assert(is_dominator(n, m) || is_dominator(m, n), "one must dominate the other");
+            n = is_dominator(n, m) ? m : n;
           }
         }
       }
       if (n != NULL) {
         assert(node->in(0), "control should have been set");
-        Block* bn = get_block_for_node(n);
-        Block* bnode = get_block_for_node(node->in(0));
-        assert(is_dominator(bn, bnode) || is_dominator(bnode, bn), "one must dominate the other");
-        if (!is_dominator(bn, bnode)) {
+        assert(is_dominator(n, node->in(0)) || is_dominator(node->in(0), n), "one must dominate the other");
+        if (!is_dominator(n, node->in(0))) {
           node->set_req(0, n);
         }
       }
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -26,6 +26,7 @@
 #include "memory/allocation.inline.hpp"
 #include "opto/addnode.hpp"
 #include "opto/connode.hpp"
+#include "opto/castnode.hpp"
 #include "opto/divnode.hpp"
 #include "opto/loopnode.hpp"
 #include "opto/matcher.hpp"
@@ -900,6 +901,14 @@
   Node *m = remix_address_expressions( n );
   if( m ) return m;
 
+  if (n->is_ConstraintCast()) {
+    Node* dom_cast = n->as_ConstraintCast()->dominating_cast(this);
+    if (dom_cast != NULL) {
+      _igvn.replace_node(n, dom_cast);
+      return dom_cast;
+    }
+  }
+
   // Determine if the Node has inputs from some local Phi.
   // Returns the block to clone thru.
   Node *n_blk = has_local_phi_input( n );
--- a/hotspot/src/share/vm/opto/node.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/node.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -911,7 +911,7 @@
 Node* Node::uncast() const {
   // Should be inline:
   //return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
-  if (is_ConstraintCast() || is_CheckCastPP())
+  if (is_ConstraintCast())
     return uncast_helper(this);
   else
     return (Node*) this;
@@ -965,8 +965,6 @@
       break;
     } else if (p->is_ConstraintCast()) {
       p = p->in(1);
-    } else if (p->is_CheckCastPP()) {
-      p = p->in(1);
     } else {
       break;
     }
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Fri Dec 11 16:57:08 2015 +0100
@@ -835,6 +835,22 @@
   return k;
 }
 
+bool PhaseGVN::is_dominator_helper(Node *d, Node *n, bool linear_only) {
+  if (d->is_top() || n->is_top()) {
+    return false;
+  }
+  assert(d->is_CFG() && n->is_CFG(), "must have CFG nodes");
+  int i = 0;
+  while (d != n) {
+    n = IfNode::up_one_dom(n, linear_only);
+    i++;
+    if (n == NULL || i >= 10) {
+      return false;
+    }
+  }
+  return true;
+}
+
 #ifdef ASSERT
 //------------------------------dead_loop_check--------------------------------
 // Check for a simple dead loop when a data node references itself directly
@@ -1525,7 +1541,7 @@
     }
 
     // If changed Cast input, check Phi users for simple cycles
-    if( use->is_ConstraintCast() || use->is_CheckCastPP() ) {
+    if (use->is_ConstraintCast()) {
       for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
         Node* u = use->fast_out(i2);
         if (u->is_Phi())
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Fri Dec 18 20:23:28 2015 +0300
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Fri Dec 11 16:57:08 2015 +0100
@@ -330,6 +330,9 @@
   // Delayed node rehash if this is an IGVN phase
   virtual void igvn_rehash_node_delayed(Node* n) {}
 
+  // true if CFG node d dominates CFG node n
+  virtual bool is_dominator(Node *d, Node *n) { fatal("unimplemented for this pass"); return false; };
+
 #ifndef PRODUCT
   void dump_old2new_map() const;
   void dump_new( uint new_lidx ) const;
@@ -397,6 +400,9 @@
 //------------------------------PhaseGVN---------------------------------------
 // Phase for performing local, pessimistic GVN-style optimizations.
 class PhaseGVN : public PhaseValues {
+protected:
+  bool is_dominator_helper(Node *d, Node *n, bool linear_only);
+
 public:
   PhaseGVN( Arena *arena, uint est_max_size ) : PhaseValues( arena, est_max_size ) {}
   PhaseGVN( PhaseGVN *gvn ) : PhaseValues( gvn ) {}
@@ -415,6 +421,8 @@
     _types = gvn->_types;
   }
 
+  bool is_dominator(Node *d, Node *n) { return is_dominator_helper(d, n, true); }
+
   // Check for a simple dead loop when a data node references itself.
   DEBUG_ONLY(void dead_loop_check(Node *n);)
 };
@@ -545,6 +553,8 @@
     _table.check_no_speculative_types();
   }
 
+  bool is_dominator(Node *d, Node *n) { return is_dominator_helper(d, n, false); }
+
 #ifndef PRODUCT
 protected:
   // Sub-quadratic implementation of VerifyIterativeGVN.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/controldependency/TestEliminatedCastPPAtPhi.java	Fri Dec 11 16:57:08 2015 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8139771
+ * @summary Eliminating CastPP nodes at Phis when they all come from a unique input may cause crash
+ * @requires vm.gc=="Serial" | vm.gc=="Parallel"
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+IgnoreUnrecognizedVMOptions -XX:+StressGCM TestEliminatedCastPPAtPhi
+ *
+ */
+
+public class TestEliminatedCastPPAtPhi {
+
+    static TestEliminatedCastPPAtPhi saved;
+    static TestEliminatedCastPPAtPhi saved_not_null;
+
+    int f;
+
+    static int test(TestEliminatedCastPPAtPhi obj, int[] array, boolean flag) {
+        int ret = array[0] + array[20];
+        saved = obj;
+        if (obj == null) {
+            return ret;
+        }
+        saved_not_null = obj;
+
+        // empty loop to be optimized out. Delays range check smearing
+        // for the array access below until the if diamond is
+        // optimized out
+        int i = 0;
+        for (; i < 10; i++);
+
+        ret += array[i];
+
+        TestEliminatedCastPPAtPhi res;
+        if (flag) {
+            // load is optimized out and res is obj here
+            res = saved;
+        } else {
+            // load is optimized out and res is non null CastPP of res here
+            res = saved_not_null;
+        }
+        // null check + CastPP here for res field load below
+
+        // 1) null check is pushed in the branches of the if above by
+        // split through phi because res is non null in the second
+        // branch and the null check can be optimized out in that
+        // branch. The Castpp stays here.
+
+        // 2) null check in the first branch is also optimized out
+        // because a dominating null check is found (the explicit null
+        // check at the beggining of the test)
+
+        // 3) the Phi for the if above merges a CastPP'ed value and
+        // the same value so it's optimized out and replaced by the
+        // uncasted value: obj
+
+        // 4) the if above has 2 empty branches so it's optimized
+        // out. The control of the CastPP that is still here is now
+        // the success branch of the range check for the array access
+        // above
+
+        // 5) the loop above is optimized out, i = 10, the range check
+        // for the array access above is optimized out and all its
+        // uses are replaced by the range check for the array accesses
+        // at the beginning of the method. The castPP here is one of
+        // the uses and so its control is now the range check at the
+        // beginning of the method: the control of the CastPP bypasses
+        // the explicit null check
+
+        return ret + res.f;
+    }
+
+    static public void main(String[] args) {
+        int[] array = new int[100];
+        TestEliminatedCastPPAtPhi obj = new TestEliminatedCastPPAtPhi();
+        for (int i = 0; i < 20000; i++) {
+            test(obj, array, (i%2) == 0);
+        }
+        test(null, array, true);
+    }
+
+}