--- old/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp 2018-11-27 09:44:01.885430375 +0100 +++ new/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp 2018-11-27 09:43:57.207469254 +0100 @@ -60,6 +60,7 @@ class GraphKit; class IdealKit; class Node; +class PhaseIdealLoop; class PhaseGVN; class PhaseMacroExpand; class Type; @@ -277,10 +278,13 @@ // Allow barrier sets to have shared state that is preserved across a compilation unit. // This could for example comprise macro nodes to be expanded during macro expansion. virtual void* create_barrier_state(Arena* comp_arena) const { return NULL; } - // If the BarrierSetC2 state has kept macro nodes in its compilation unit state to be - // expanded later, then now is the time to do so. - virtual bool expand_macro_nodes(PhaseMacroExpand* macro) const { return false; } - + // If the BarrierSetC2 state has barrier nodes in its compilation + // unit state to be expanded later, then now is the time to do so. + virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const { return false; } + virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const { return false; } + virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return false; } + virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return false; } + virtual bool has_special_unique_user(const Node* node) const { return false; } enum CompilePhase { --- old/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp 2018-11-27 09:44:06.642390840 +0100 +++ new/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp 2018-11-27 09:44:01.975429627 +0100 @@ -996,9 +996,8 @@ return; } -bool ZBarrierSetC2::expand_macro_nodes(PhaseMacroExpand* macro) const { - Compile* C = Compile::current(); - PhaseIterGVN &igvn = macro->igvn(); +bool ZBarrierSetC2::expand_barriers(Compile* C, PhaseIterGVN& igvn) const { + PhaseMacroExpand macro(igvn); ZBarrierSetC2State* s = state(); if (s->load_barrier_count() > 0) { #ifdef ASSERT @@ -1018,7 +1017,7 @@ skipped++; continue; } - expand_loadbarrier_node(macro, n); + expand_loadbarrier_node(¯o, n); assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list"); if (C->failing()) return true; } @@ -1027,7 +1026,7 @@ LoadBarrierNode* n = s->load_barrier_node(load_barrier_count - 1); assert(!(igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())), "should have been processed already"); assert(!n->can_be_eliminated(), "should have been processed already"); - expand_loadbarrier_node(macro, n); + expand_loadbarrier_node(¯o, n); assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list"); if (C->failing()) return true; } @@ -1623,4 +1622,4 @@ break; } return false; -} \ No newline at end of file +} --- old/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp 2018-11-27 09:44:11.472350696 +0100 +++ new/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp 2018-11-27 09:44:06.793389584 +0100 @@ -200,9 +200,9 @@ virtual void unregister_potential_barrier_node(Node* node) const; virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const; virtual Node* step_over_gc_barrier(Node* c) const; - // If the BarrierSetC2 state has kept macro nodes in its compilation unit state to be + // If the BarrierSetC2 state has kept barrier nodes in its compilation unit state to be // expanded later, then now is the time to do so. - virtual bool expand_macro_nodes(PhaseMacroExpand* macro) const; + virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const; static void find_dominating_barriers(PhaseIterGVN& igvn); static void loop_optimize_gc_barrier(PhaseIdealLoop* phase, Node* node, bool last_round); --- old/src/hotspot/share/opto/compile.cpp 2018-11-27 09:44:16.386309857 +0100 +++ new/src/hotspot/share/opto/compile.cpp 2018-11-27 09:44:11.539350140 +0100 @@ -1122,7 +1122,7 @@ set_decompile_count(0); set_do_freq_based_layout(_directive->BlockLayoutByFrequencyOption); - set_num_loop_opts(LoopOptsCount); + _loop_opts_cnt = LoopOptsCount; set_do_inlining(Inline); set_max_inline_size(MaxInlineSize); set_freq_inline_size(FreqInlineSize); @@ -2169,14 +2169,14 @@ } -bool Compile::optimize_loops(int& loop_opts_cnt, PhaseIterGVN& igvn, LoopOptsMode mode) { - if(loop_opts_cnt > 0) { +bool Compile::optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode) { + if(_loop_opts_cnt > 0) { debug_only( int cnt = 0; ); - while(major_progress() && (loop_opts_cnt > 0)) { + while(major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); assert( cnt++ < 40, "infinite cycle in loop optimization" ); PhaseIdealLoop ideal_loop(igvn, mode); - loop_opts_cnt--; + _loop_opts_cnt--; if (failing()) return false; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP_ITERATIONS, 2); } @@ -2202,7 +2202,6 @@ #endif ResourceMark rm; - int loop_opts_cnt; print_inlining_reinit(); @@ -2305,28 +2304,27 @@ // peeling, unrolling, etc. // Set loop opts counter - loop_opts_cnt = num_loop_opts(); - if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) { + if((_loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) { { TracePhase tp("idealLoop", &timers[_t_idealLoop]); PhaseIdealLoop ideal_loop(igvn, LoopOptsDefault); - loop_opts_cnt--; + _loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP1, 2); if (failing()) return; } // Loop opts pass if partial peeling occurred in previous pass - if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) { + if(PartialPeelLoop && major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf); - loop_opts_cnt--; + _loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP2, 2); if (failing()) return; } // Loop opts pass for loop-unrolling before CCP - if(major_progress() && (loop_opts_cnt > 0)) { + if(major_progress() && (_loop_opts_cnt > 0)) { TracePhase tp("idealLoop", &timers[_t_idealLoop]); PhaseIdealLoop ideal_loop(igvn, LoopOptsSkipSplitIf); - loop_opts_cnt--; + _loop_opts_cnt--; if (major_progress()) print_method(PHASE_PHASEIDEALLOOP3, 2); } if (!failing()) { @@ -2361,7 +2359,7 @@ // Loop transforms on the ideal graph. Range Check Elimination, // peeling, unrolling, etc. - if (!optimize_loops(loop_opts_cnt, igvn, LoopOptsDefault)) { + if (!optimize_loops(igvn, LoopOptsDefault)) { return; } @@ -2404,6 +2402,16 @@ } } + { + TracePhase tp("barrierExpand", &timers[_t_barrierExpand]); + print_method(PHASE_BEFORE_BARRIER_EXPAND, 2); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + if (bs->expand_barriers(this, igvn)) { + assert(failing(), "must bail out w/ explicit message"); + return; + } + } + if (opaque4_count() > 0) { C->remove_opaque4_nodes(igvn); igvn.optimize(); --- old/src/hotspot/share/opto/compile.hpp 2018-11-27 09:44:21.042271158 +0100 +++ new/src/hotspot/share/opto/compile.hpp 2018-11-27 09:44:16.489309001 +0100 @@ -369,7 +369,6 @@ address _stub_entry_point; // Compile code entry for generated stub, or NULL // Control of this compilation. - int _num_loop_opts; // Number of iterations for doing loop optimiztions int _max_inline_size; // Max inline size for this compilation int _freq_inline_size; // Max hot method inline size for this compilation int _fixed_slots; // count of frame slots not allocated by the register @@ -413,6 +412,7 @@ // JSR 292 bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. RTMState _rtm_state; // State of Restricted Transactional Memory usage + int _loop_opts_cnt; // loop opts round // Compilation environment. Arena _comp_arena; // Arena with lifetime equivalent to Compile @@ -653,8 +653,6 @@ int inlining_incrementally() const { return _inlining_incrementally; } void set_major_progress() { _major_progress++; } void clear_major_progress() { _major_progress = 0; } - int num_loop_opts() const { return _num_loop_opts; } - void set_num_loop_opts(int n) { _num_loop_opts = n; } int max_inline_size() const { return _max_inline_size; } void set_freq_inline_size(int n) { _freq_inline_size = n; } int freq_inline_size() const { return _freq_inline_size; } @@ -1087,7 +1085,7 @@ void inline_incrementally(PhaseIterGVN& igvn); void inline_string_calls(bool parse_time); void inline_boxing_calls(PhaseIterGVN& igvn); - bool optimize_loops(int& loop_opts_cnt, PhaseIterGVN& igvn, LoopOptsMode mode); + bool optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode); // Matching, CFG layout, allocation, code generation PhaseCFG* cfg() { return _cfg; } --- old/src/hotspot/share/opto/loopnode.cpp 2018-11-27 09:44:25.541233765 +0100 +++ new/src/hotspot/share/opto/loopnode.cpp 2018-11-27 09:44:21.119270518 +0100 @@ -2774,9 +2774,12 @@ return; } + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); // Nothing to do, so get out - bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only; + bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only && + !bs->is_gc_specific_loop_opts_pass(mode); bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn); + bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(mode); if (stop_early && !do_expensive_nodes) { _igvn.optimize(); // Cleanup NeverBranches return; @@ -2854,8 +2857,9 @@ // Given early legal placement, try finding counted loops. This placement // is good enough to discover most loop invariants. - if( !_verify_me && !_verify_only ) + if (!_verify_me && !_verify_only && !strip_mined_loops_expanded) { _ltree_root->counted_loop( this ); + } // Find latest loop placement. Find ideal loop placement. visited.Clear(); @@ -2926,6 +2930,14 @@ return; } + if (bs->optimize_loops(this, mode, visited, nstack, worklist)) { + _igvn.optimize(); + if (C->log() != NULL) { + log_loop_tree(_ltree_root, _ltree_root, C->log()); + } + return; + } + if (ReassociateInvariants) { // Reassociate invariants and prep for split_thru_phi for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { @@ -4136,7 +4148,7 @@ } } -// Verify that no data node is schedules in the outer loop of a strip +// Verify that no data node is scheduled in the outer loop of a strip // mined loop. void PhaseIdealLoop::verify_strip_mined_scheduling(Node *n, Node* least) { #ifdef ASSERT @@ -4145,7 +4157,9 @@ } IdealLoopTree* loop = get_loop(least); Node* head = loop->_head; - if (head->is_OuterStripMinedLoop()) { + if (head->is_OuterStripMinedLoop() && + // Verification can't be applied to fully built strip mined loops + head->as_Loop()->outer_loop_end()->in(1)->find_int_con(-1) == 0) { Node* sfpt = head->as_Loop()->outer_safepoint(); ResourceMark rm; Unique_Node_List wq; --- old/src/hotspot/share/opto/macro.cpp 2018-11-27 09:44:30.265194502 +0100 +++ new/src/hotspot/share/opto/macro.cpp 2018-11-27 09:44:25.651232851 +0100 @@ -2600,6 +2600,5 @@ _igvn.set_delay_transform(false); _igvn.optimize(); if (C->failing()) return true; - BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); - return bs->expand_macro_nodes(this); + return false; } --- old/src/hotspot/share/opto/phase.cpp 2018-11-27 09:44:35.197153509 +0100 +++ new/src/hotspot/share/opto/phase.cpp 2018-11-27 09:44:30.378193563 +0100 @@ -83,6 +83,7 @@ tty->print_cr (" Cond Const Prop: %7.3f s", timers[_t_ccp].seconds()); tty->print_cr (" GVN 2: %7.3f s", timers[_t_iterGVN2].seconds()); tty->print_cr (" Macro Expand: %7.3f s", timers[_t_macroExpand].seconds()); + tty->print_cr (" Barrier Expand: %7.3f s", timers[_t_barrierExpand].seconds()); tty->print_cr (" Graph Reshape: %7.3f s", timers[_t_graphReshaping].seconds()); double other = timers[_t_optimizer].seconds() - @@ -95,6 +96,7 @@ timers[_t_ccp].seconds() + timers[_t_iterGVN2].seconds() + timers[_t_macroExpand].seconds() + + timers[_t_barrierExpand].seconds() + timers[_t_graphReshaping].seconds()); if (other > 0) { tty->print_cr(" Other: %7.3f s", other); --- old/src/hotspot/share/opto/phase.hpp 2018-11-27 09:44:39.880114586 +0100 +++ new/src/hotspot/share/opto/phase.hpp 2018-11-27 09:44:35.268152919 +0100 @@ -80,6 +80,7 @@ _t_ccp, _t_iterGVN2, _t_macroExpand, + _t_barrierExpand, _t_graphReshaping, _t_matcher, _t_scheduler, --- old/src/hotspot/share/opto/phasetype.hpp 2018-11-27 09:44:44.881073020 +0100 +++ new/src/hotspot/share/opto/phasetype.hpp 2018-11-27 09:44:40.032113323 +0100 @@ -52,6 +52,7 @@ PHASE_MATCHING, PHASE_INCREMENTAL_INLINE, PHASE_INCREMENTAL_BOXING_INLINE, + PHASE_BEFORE_BARRIER_EXPAND, PHASE_BEFORE_MACRO_EXPANSION, PHASE_END, PHASE_FAILURE, @@ -89,6 +90,7 @@ case PHASE_MATCHING: return "After matching"; case PHASE_INCREMENTAL_INLINE: return "Incremental Inline"; case PHASE_INCREMENTAL_BOXING_INLINE: return "Incremental Boxing Inline"; + case PHASE_BEFORE_BARRIER_EXPAND: return "Before Barrier Expand"; case PHASE_BEFORE_MACRO_EXPANSION: return "Before macro expansion"; case PHASE_END: return "End"; case PHASE_FAILURE: return "Failure";