--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp Tue Nov 27 09:35:02 2018 +0100
@@ -60,6 +60,7 @@
class GraphKit;
class IdealKit;
class Node;
+class PhaseIdealLoop;
class PhaseGVN;
class PhaseMacroExpand;
class Type;
@@ -277,9 +278,12 @@
// 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; }
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Tue Nov 27 09:35:02 2018 +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
+}
--- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.hpp Tue Nov 27 09:35:02 2018 +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);
--- a/src/hotspot/share/opto/compile.cpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/compile.cpp Tue Nov 27 09:35:02 2018 +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();
--- a/src/hotspot/share/opto/compile.hpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/compile.hpp Tue Nov 27 09:35:02 2018 +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; }
--- a/src/hotspot/share/opto/loopnode.cpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/loopnode.cpp Tue Nov 27 09:35:02 2018 +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;
--- a/src/hotspot/share/opto/macro.cpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/macro.cpp Tue Nov 27 09:35:02 2018 +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;
}
--- a/src/hotspot/share/opto/phase.cpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/phase.cpp Tue Nov 27 09:35:02 2018 +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);
--- a/src/hotspot/share/opto/phase.hpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/phase.hpp Tue Nov 27 09:35:02 2018 +0100
@@ -80,6 +80,7 @@
_t_ccp,
_t_iterGVN2,
_t_macroExpand,
+ _t_barrierExpand,
_t_graphReshaping,
_t_matcher,
_t_scheduler,
--- a/src/hotspot/share/opto/phasetype.hpp Wed Nov 28 15:34:43 2018 +0800
+++ b/src/hotspot/share/opto/phasetype.hpp Tue Nov 27 09:35:02 2018 +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";