< prev index next >

src/hotspot/share/opto/cfgnode.cpp

Print this page
*** 31,10 ***
--- 31,11 ---
  #include "opto/addnode.hpp"
  #include "opto/castnode.hpp"
  #include "opto/cfgnode.hpp"
  #include "opto/connode.hpp"
  #include "opto/convertnode.hpp"
+ #include "opto/inlinetypenode.hpp"
  #include "opto/loopnode.hpp"
  #include "opto/machnode.hpp"
  #include "opto/movenode.hpp"
  #include "opto/narrowptrnode.hpp"
  #include "opto/mulnode.hpp"

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

*** 411,31 ***
    // 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)) {
      MergeMemNode* m = NULL;
!     assert(phi->req() == 3, "same as region");
      for (uint i = 1; i < 3; ++i) {
!       Node *mem = phi->in(i);
!       if (mem && mem->is_MergeMem() && 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);
          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 false;
  }
  
  //------------------------------Ideal------------------------------------------
  // Return a node which is more "ideal" than the current node.  Must preserve
  // the CFG, but we can still strip out dead paths.
--- 412,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.
  
!   if (type() == Type::MEMORY && is_diamond_phi(true)) {
      MergeMemNode* m = NULL;
!     assert(req() == 3, "same as region");
+     Node* r = in(0);
      for (uint i = 1; i < 3; ++i) {
!       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 = 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.
!           return m;
          }
        }
      }
    }
!   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.

*** 446,12 ***
    // 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) {            // No Phi users?  Nothing merging?
        for (uint i = 1; i < req()-1; i++) {
          Node *if1 = in(i);
--- 446,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) {
!       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);

*** 849,11 ***
      return false; // No comparison
    } else if (cmp1->Opcode() == Op_CmpF || cmp1->Opcode() == Op_CmpD ||
               cmp2->Opcode() == Op_CmpF || cmp2->Opcode() == Op_CmpD ||
               cmp1->Opcode() == Op_CmpP || cmp1->Opcode() == Op_CmpN ||
               cmp2->Opcode() == Op_CmpP || cmp2->Opcode() == Op_CmpN ||
!              cmp1->is_SubTypeCheck() || cmp2->is_SubTypeCheck()) {
      // Floats and pointers don't exactly obey trichotomy. To be on the safe side, don't transform their tests.
      // SubTypeCheck is not commutative
      return false;
    } else if (cmp1 != cmp2) {
      if (cmp1->in(1) == cmp2->in(2) &&
--- 856,12 ---
      return false; // No comparison
    } else if (cmp1->Opcode() == Op_CmpF || cmp1->Opcode() == Op_CmpD ||
               cmp2->Opcode() == Op_CmpF || cmp2->Opcode() == Op_CmpD ||
               cmp1->Opcode() == Op_CmpP || cmp1->Opcode() == Op_CmpN ||
               cmp2->Opcode() == Op_CmpP || cmp2->Opcode() == Op_CmpN ||
!              cmp1->is_SubTypeCheck() || cmp2->is_SubTypeCheck() ||
+              cmp1->is_FlatArrayCheck() || cmp2->is_FlatArrayCheck()) {
      // Floats and pointers don't exactly obey trichotomy. To be on the safe side, don't transform their tests.
      // SubTypeCheck is not commutative
      return false;
    } else if (cmp1 != cmp2) {
      if (cmp1->in(1) == cmp2->in(2) &&

*** 930,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");
    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);
--- 938,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_phi_adr_type(at) == TypeAryPtr::INLINES && 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);

*** 1067,10 ***
--- 1075,18 ---
  void PhiNode::verify_adr_type(bool recursive) const {
    if (VMError::is_error_reported())  return;  // muzzle asserts when debugging an error
    if (Node::in_dump())               return;  // muzzle asserts when printing
  
    assert((_type == Type::MEMORY) == (_adr_type != NULL), "adr_type for memory phis only");
+   // Flat array element shouldn't get their own memory slice until flattened_accesses_share_alias is cleared.
+   // It could be the graph has no loads/stores and flattened_accesses_share_alias is never cleared. EA could still
+   // creates per element Phis but that wouldn't be a problem as there are no memory accesses for that array.
+   assert(_adr_type == NULL || _adr_type->isa_aryptr() == NULL ||
+          _adr_type->is_aryptr()->is_known_instance() ||
+          !_adr_type->is_aryptr()->is_flat() ||
+          !Compile::current()->flattened_accesses_share_alias() ||
+          _adr_type == TypeAryPtr::INLINES, "flat array element shouldn't get its own slice yet");
  
    if (!VerifyAliases)       return;  // verify thoroughly only if requested
  
    assert(_adr_type == flatten_phi_adr_type(_adr_type),
           "Phi::adr_type must be pre-normalized");

*** 1140,19 ***
    // 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_instklassptr() : 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;
    }
  
    // 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
--- 1156,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_instklassptr() : NULL;
    bool is_intf = false;
!   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

*** 1205,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()) {
        assert(ft == _type, ""); // Uplift to interface
!     } else if (!t->empty() && ttkp && 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()) {
--- 1216,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 != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) {
        assert(ft == _type, ""); // Uplift to 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()) {

*** 1369,10 ***
--- 1380,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;
+     }
+   }
+ 
+ 
    // Looking for phis with identical inputs.  If we find one that has
    // type TypePtr::BOTTOM, replace the current phi with the bottom phi.
    if (phase->is_IterGVN() && type() == Type::MEMORY && adr_type() !=
        TypePtr::BOTTOM && !adr_type()->is_known_instance()) {
      uint phi_len = req();

*** 1891,10 ***
--- 1910,58 ---
      worklist.push(this);
    }
    return delay;
  }
  
+ // Push inline type input nodes (and null) down through the phi recursively (can handle data loops).
+ InlineTypeBaseNode* PhiNode::push_inline_types_through(PhaseGVN* phase, bool can_reshape, ciInlineKlass* vk, bool is_init) {
+   InlineTypeBaseNode* vt = NULL;
+   if (_type->isa_ptr()) {
+     vt = InlineTypePtrNode::make_null(*phase, vk)->clone_with_phis(phase, in(0), is_init);
+   } else {
+     vt = InlineTypeNode::make_null(*phase, vk)->clone_with_phis(phase, in(0), is_init);
+   }
+   if (can_reshape) {
+     // Replace phi right away to be able to use the inline
+     // type node when reaching the phi again through data loops.
+     PhaseIterGVN* igvn = phase->is_IterGVN();
+     for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+       Node* u = fast_out(i);
+       igvn->rehash_node_delayed(u);
+       imax -= u->replace_edge(this, vt);
+       --i;
+     }
+     assert(outcnt() == 0, "should be dead now");
+   }
+   ResourceMark rm;
+   Node_List casts;
+   for (uint i = 1; i < req(); ++i) {
+     Node* n = in(i);
+     while (n->is_ConstraintCast()) {
+       casts.push(n);
+       n = n->in(1);
+     }
+     if (phase->type(n)->is_zero_type()) {
+       n = InlineTypePtrNode::make_null(*phase, vk);
+     } else if (n->is_Phi()) {
+       assert(can_reshape, "can only handle phis during IGVN");
+       n = phase->transform(n->as_Phi()->push_inline_types_through(phase, can_reshape, vk, is_init));
+     }
+     while (casts.size() != 0) {
+       // Update the cast input and let ConstraintCastNode::Ideal push it through the InlineTypePtrNode
+       Node* cast = casts.pop();
+       phase->hash_delete(cast);
+       cast->set_req(1, n);
+       n = phase->transform(cast);
+       assert(n->is_InlineTypePtr(), "Failed to push cast through InlineTypePtr");
+     }
+     bool transform = !can_reshape && (i == (req()-1)); // Transform phis on last merge
+     vt->merge_with(phase, n->as_InlineTypeBase(), i, transform);
+   }
+   return vt;
+ }
+ 
  //------------------------------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 *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
    Node *r = in(0);              // RegionNode

*** 2192,10 ***
--- 2259,12 ---
    // (MergeMemNode is not dead_loop_safe - need to check for dead loop.)
    if (progress == NULL && can_reshape && type() == Type::MEMORY) {
      // see if this phi should be sliced
      uint merge_width = 0;
      bool saw_self = false;
+     // TODO revisit this with JDK-8247216
+     bool mergemem_only = true;
      for( uint i=1; i<req(); ++i ) {// For all paths in
        Node *ii = in(i);
        // TOP inputs should not be counted as safe inputs because if the
        // Phi references itself through all other inputs then splitting the
        // Phi through memory merges would create dead loop at later stage.

*** 2204,15 ***
        }
        if (ii->is_MergeMem()) {
          MergeMemNode* n = ii->as_MergeMem();
          merge_width = MAX2(merge_width, n->req());
          saw_self = saw_self || (n->base_memory() == this);
        }
      }
  
      // This restriction is temporarily necessary to ensure termination:
!     if (!saw_self && adr_type() == TypePtr::BOTTOM)  merge_width = 0;
  
      if (merge_width > Compile::AliasIdxRaw) {
        // found at least one non-empty MergeMem
        const TypePtr* at = adr_type();
        if (at != TypePtr::BOTTOM) {
--- 2273,17 ---
        }
        if (ii->is_MergeMem()) {
          MergeMemNode* n = ii->as_MergeMem();
          merge_width = MAX2(merge_width, n->req());
          saw_self = saw_self || (n->base_memory() == this);
+       } else {
+         mergemem_only = false;
        }
      }
  
      // This restriction is temporarily necessary to ensure termination:
!     if (!mergemem_only && !saw_self && adr_type() == TypePtr::BOTTOM)  merge_width = 0;
  
      if (merge_width > Compile::AliasIdxRaw) {
        // found at least one non-empty MergeMem
        const TypePtr* at = adr_type();
        if (at != TypePtr::BOTTOM) {

*** 2279,10 ***
--- 2350,15 ---
          MergeMemNode* result = MergeMemNode::make(new_base);
          for (uint i = 1; i < req(); ++i) {
            Node *ii = in(i);
            if (ii->is_MergeMem()) {
              MergeMemNode* n = ii->as_MergeMem();
+             if (igvn) {
+               // TODO revisit this with JDK-8247216
+               // Put 'n' on the worklist because it might be modified by MergeMemStream::iteration_setup
+               igvn->_worklist.push(n);
+             }
              for (MergeMemStream mms(result, n); mms.next_non_empty2(); ) {
                // If we have not seen this slice yet, make a phi for it.
                bool made_new_phi = false;
                if (mms.is_empty()) {
                  Node* new_phi = new_base->slice_memory(mms.adr_type(phase->C));

*** 2433,10 ***
--- 2509,66 ---
        igvn->register_new_node_with_optimizer(new_vect_phi, this);
        progress = new VectorBoxNode(igvn->C, new_vbox_phi, new_vect_phi, vbox->box_type(), vbox->vec_type());
      }
    }
  
+   // Check recursively if inputs are either an inline type, constant null
+   // or another Phi (including self references through data loops). If so,
+   // push the inline types down through the phis to enable folding of loads.
+   if (EnableValhalla && (_type->isa_ptr() || _type->isa_inlinetype()) && req() > 2 && progress == NULL) {
+     ResourceMark rm;
+     Unique_Node_List worklist;
+     worklist.push(this);
+     bool can_optimize = true;
+     ciInlineKlass* vk = NULL;
+     // true if all IsInit inputs of all InlineType* nodes are true
+     bool is_init = true;
+     Node_List casts;
+ 
+     for (uint next = 0; next < worklist.size() && can_optimize; next++) {
+       Node* phi = worklist.at(next);
+       for (uint i = 1; i < phi->req() && can_optimize; i++) {
+         Node* n = phi->in(i);
+         if (n == NULL) {
+           can_optimize = false;
+           break;
+         }
+         while (n->is_ConstraintCast()) {
+           casts.push(n);
+           n = n->in(1);
+         }
+         const Type* t = phase->type(n);
+         if (n->is_InlineTypeBase() && n->as_InlineTypeBase()->can_merge() &&
+             (vk == NULL || vk == t->inline_klass())) {
+           vk = (vk == NULL) ? t->inline_klass() : vk;
+           if (phase->find_int_con(n->as_InlineTypeBase()->get_is_init(), 0) != 1) {
+             is_init = false;
+           }
+         } else if (n->is_Phi() && can_reshape && (n->bottom_type()->isa_ptr() || n->bottom_type()->isa_inlinetype())) {
+           worklist.push(n);
+         } else if (t->is_zero_type()) {
+           is_init = false;
+         } else {
+           can_optimize = false;
+         }
+       }
+     }
+     // Check if cast nodes can be pushed through
+     const Type* t = Type::get_const_type(vk);
+     while (casts.size() != 0 && can_optimize && t != NULL) {
+       Node* cast = casts.pop();
+       if (t->filter(cast->bottom_type()) == Type::TOP) {
+         can_optimize = false;
+       }
+     }
+     if (can_optimize && vk != NULL) {
+ // TODO 8275400
+ //      assert(!_type->isa_ptr() || _type->maybe_null() || is_init, "Phi not null but a possible null was seen");
+       progress = push_inline_types_through(phase, can_reshape, vk, is_init);
+     }
+   }
+ 
    return progress;              // Return any progress
  }
  
  bool PhiNode::is_data_loop(RegionNode* r, Node* uin, const PhaseGVN* phase) {
    // First, take the short cut when we know it is a loop and the EntryControl data path is dead.

*** 2697,10 ***
--- 2829,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 inline 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 >