# HG changeset patch # User roland # Date 1564385412 -7200 # Mon Jul 29 09:30:12 2019 +0200 # Node ID d1136da8b6929e34af262daa6fe89352803f8d3b # Parent d7e4f2cab1920776b1b904083f718668125742a4 no safepoint between LRB and load diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Mon Jul 29 09:30:12 2019 +0200 @@ -916,6 +916,14 @@ if (node->Opcode() == Op_AddP && ShenandoahBarrierSetC2::has_only_shenandoah_wb_pre_uses(node)) { igvn->add_users_to_worklist(node); } + if (node->Opcode() == Op_DecodeN) { + for (DUIterator_Fast imax, i = node->fast_outs(imax); i < imax; i++) { + Node* u = node->fast_out(i); + if (u->Opcode() == Op_ShenandoahLoadReferenceBarrier) { + igvn->_worklist.push(u); + } + } + } } void ShenandoahBarrierSetC2::eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const { @@ -1257,3 +1265,14 @@ xop == Op_ShenandoahCompareAndSwapN || xop == Op_ShenandoahCompareAndSwapP; } + +void ShenandoahBarrierSetC2::igvn_add_users_to_worklist(PhaseIterGVN* igvn, Node* use) const { + if (use->Opcode() == Op_DecodeN) { + for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { + Node* u = use->fast_out(i); + if (u->Opcode() == Op_ShenandoahLoadReferenceBarrier) { + igvn->_worklist.push(u); + } + } + } +} diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp Mon Jul 29 09:30:12 2019 +0200 @@ -148,6 +148,8 @@ virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const; virtual bool matcher_is_store_load_barrier(Node* x, uint xop) const; + + virtual void igvn_add_users_to_worklist(PhaseIterGVN* igvn, Node* use) const; }; #endif // SHARE_GC_SHENANDOAH_C2_SHENANDOAHBARRIERSETC2_HPP diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Mon Jul 29 09:30:12 2019 +0200 @@ -1213,6 +1213,42 @@ } } + for (int i = 0; i < state->load_reference_barriers_count(); i++) { + ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); + if (lrb->get_barrier_strength() == ShenandoahLoadReferenceBarrierNode::NONE) { + continue; + } + assert(lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn)->is_Load() || lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn)->is_LoadStore() || + (lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn)->Opcode() == Op_DecodeN && (lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn)->in(1)->is_Load() || lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn)->in(1)->is_LoadStore())), ""); + Node* lrb_c = phase->get_ctrl(lrb); + Node* load_c = phase->get_ctrl(lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn)); + if (has_safepoint_between(lrb_c, load_c, phase)) { + Node* c = lrb_c; + Node* latest = NULL; + while (c != load_c) { + Node* next = phase->idom(c); + if (has_safepoint_between(c, next, phase)) { + latest = next; + } + c = next; + } + assert(latest != NULL, "should have found a safepoint"); + IdealLoopTree* latest_loop = phase->get_loop(latest); + c = latest; + while (latest_loop->_nest > 0 && c != load_c) { + IdealLoopTree* loop = phase->get_loop(c); + if (loop->_nest < latest_loop->_nest) { + latest = c; + latest_loop = phase->get_loop(latest); + } + c = phase->idom(c); + } + latest = phase->find_non_split_ctrl(latest); + assert(!has_safepoint_between(latest, load_c, phase), "new location should above all safepoints"); + phase->set_ctrl(lrb, latest); + } + } + Node_Stack stack(0); Node_List clones; for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) { @@ -2329,7 +2365,7 @@ for (uint j = 1; j < wq.size(); j++) { Node* c = wq.at(j); assert(!c->is_Root(), "shouldn't leave loop"); - if (c->is_SafePoint()) { + if (c->Opcode() == Op_SafePoint) { assert(mem == NULL, "only one safepoint"); mem = c->in(TypeFunc::Memory); } @@ -3106,6 +3142,46 @@ return this; } +Node* ShenandoahLoadReferenceBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) { + if (can_reshape) { + PhaseIterGVN* igvn = phase->is_IterGVN(); + Node* value = in(ValueIn); + + if (value != NULL && value->is_ConstraintCast() && value->in(1) != NULL && phase->type(value->in(1))->isa_oopptr()) { + set_req(ValueIn, value->in(1)); + igvn->replace_input_of(value, 1, this); + return this; + } + + if (value != NULL && value->is_Phi() && value->in(0) != NULL) { + Node* phi = new PhiNode(value->in(0), bottom_type()); + for (uint i = 1; i < value->req(); i++) { + Node* in = value->in(i); + if (in == NULL) continue; + Node* lrb = clone(); + lrb->set_req(ValueIn, in); + igvn->register_new_node_with_optimizer(lrb); + phi->set_req(i, lrb); + } + return phi; + } if (value != NULL && value->Opcode() == Op_DecodeN && value->in(1)->is_Phi()) { + Node* phi = new PhiNode(value->in(1)->in(0), bottom_type()); + for (uint i = 1; i < value->in(1)->req(); i++) { + Node* in = value->in(1)->in(i); + Node* lrb = clone(); + Node* decoden = value->clone(); + decoden->set_req(1, in); + decoden = igvn->transform(decoden); + lrb->set_req(ShenandoahLoadReferenceBarrierNode::ValueIn, decoden); + igvn->register_new_node_with_optimizer(lrb); + phi->set_req(i, lrb); + } + return phi; + } + } + return NULL; +} + bool ShenandoahLoadReferenceBarrierNode::needs_barrier(PhaseGVN* phase, Node* n) { Unique_Node_List visited; return needs_barrier_impl(phase, n, visited); @@ -3178,6 +3254,8 @@ needs_barrier_impl(phase, n->in(3), visited); case Op_ShenandoahEnqueueBarrier: return needs_barrier_impl(phase, n->in(1), visited); + case Op_CreateEx: + return false; default: break; } @@ -3279,6 +3357,7 @@ case Op_CastP2X: case Op_SafePoint: case Op_EncodeISOArray: + case Op_HasNegatives: strength = STRONG; break; case Op_LoadB: diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp Mon Jul 29 09:30:12 2019 +0200 @@ -247,6 +247,7 @@ virtual uint ideal_reg() const { return Op_RegP; } virtual Node* Identity(PhaseGVN* phase); + virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); uint size_of() const { return sizeof(*this); diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/opto/macro.cpp --- a/src/hotspot/share/opto/macro.cpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/opto/macro.cpp Mon Jul 29 09:30:12 2019 +0200 @@ -2572,15 +2572,33 @@ if (_igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())) { // node is unreachable, so don't try to expand it C->remove_macro_node(n); - } else if (n->is_ArrayCopy()){ - int macro_count = C->macro_count(); + continue; + } + int macro_count = C->macro_count(); + switch (n->class_id()) { + case Node::Class_Lock: + expand_lock_node(n->as_Lock()); + assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + break; + case Node::Class_Unlock: + expand_unlock_node(n->as_Unlock()); + assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + break; + case Node::Class_ArrayCopy: expand_arraycopy_node(n->as_ArrayCopy()); assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + break; } if (C->failing()) return true; macro_idx --; } + _igvn.set_delay_transform(false); + _igvn.optimize(); + if (C->failing()) return true; + + _igvn.set_delay_transform(true); + // expand "macro" nodes // nodes are removed from the macro list as they are processed while (C->macro_count() > 0) { @@ -2599,12 +2617,6 @@ case Node::Class_AllocateArray: expand_allocate_array(n->as_AllocateArray()); break; - case Node::Class_Lock: - expand_lock_node(n->as_Lock()); - break; - case Node::Class_Unlock: - expand_unlock_node(n->as_Unlock()); - break; default: assert(false, "unknown node type in macro list"); } diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/opto/phaseX.cpp --- a/src/hotspot/share/opto/phaseX.cpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/opto/phaseX.cpp Mon Jul 29 09:30:12 2019 +0200 @@ -2161,7 +2161,7 @@ BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, old); } - + BarrierSet::barrier_set()->barrier_set_c2()->enqueue_useful_gc_barrier(igvn, this); } //-------------------------------replace_by----------------------------------- diff -r d7e4f2cab192 -r d1136da8b692 src/hotspot/share/opto/phaseX.hpp --- a/src/hotspot/share/opto/phaseX.hpp Mon Jul 22 16:32:58 2019 -0400 +++ b/src/hotspot/share/opto/phaseX.hpp Mon Jul 29 09:30:12 2019 +0200 @@ -544,7 +544,7 @@ // Replace ith edge of "n" with "in" void replace_input_of(Node* n, int i, Node* in) { rehash_node_delayed(n); - n->set_req(i, in); + n->set_req_X(i, in, this); } // Delete ith edge of "n"