hotspot/src/share/vm/opto/castnode.cpp
changeset 35545 a8f29dfd62b2
parent 33105 294e48b4f704
child 35549 3415401a6b6e
--- 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 {