8214172: GC interface entry points for loop opts

Reviewed-by: kvn, rkennke
This commit is contained in:
Roland Westrelin 2018-11-27 09:35:02 +01:00
parent bb50695ff9
commit 8849b1c7b7
10 changed files with 62 additions and 35 deletions

View File

@ -60,6 +60,7 @@ class ConnectionGraph;
class GraphKit;
class IdealKit;
class Node;
class PhaseIdealLoop;
class PhaseGVN;
class PhaseMacroExpand;
class Type;
@ -277,9 +278,12 @@ public:
// 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; }

View File

@ -996,9 +996,8 @@ void ZBarrierSetC2::expand_loadbarrier_optimized(PhaseMacroExpand* phase, LoadBa
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 @@ bool ZBarrierSetC2::expand_macro_nodes(PhaseMacroExpand* macro) const {
skipped++;
continue;
}
expand_loadbarrier_node(macro, n);
expand_loadbarrier_node(&macro, 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 @@ bool ZBarrierSetC2::expand_macro_nodes(PhaseMacroExpand* macro) const {
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(&macro, 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 @@ bool ZBarrierSetC2::escape_add_final_edges(ConnectionGraph* conn_graph, PhaseGVN
break;
}
return false;
}
}

View File

@ -200,9 +200,9 @@ public:
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);

View File

@ -1122,7 +1122,7 @@ void Compile::Init(int aliaslevel) {
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 @@ void Compile::inline_incrementally(PhaseIterGVN& igvn) {
}
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 @@ void Compile::Optimize() {
#endif
ResourceMark rm;
int loop_opts_cnt;
print_inlining_reinit();
@ -2305,28 +2304,27 @@ void Compile::Optimize() {
// 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 @@ void Compile::Optimize() {
// 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 @@ void Compile::Optimize() {
}
}
{
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();

View File

@ -369,7 +369,6 @@ class Compile : public Phase {
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 @@ class Compile : public Phase {
// 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 @@ class Compile : public Phase {
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 @@ class Compile : public Phase {
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; }

View File

@ -2774,9 +2774,12 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
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 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
// 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 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) {
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 @@ void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, N
}
}
// 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 @@ void PhaseIdealLoop::verify_strip_mined_scheduling(Node *n, Node* least) {
}
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;

View File

@ -2600,6 +2600,5 @@ bool PhaseMacroExpand::expand_macro_nodes() {
_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;
}

View File

@ -83,6 +83,7 @@ void Phase::print_timers() {
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 @@ void Phase::print_timers() {
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);

View File

@ -80,6 +80,7 @@ public:
_t_ccp,
_t_iterGVN2,
_t_macroExpand,
_t_barrierExpand,
_t_graphReshaping,
_t_matcher,
_t_scheduler,

View File

@ -52,6 +52,7 @@ enum CompilerPhaseType {
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 @@ class CompilerPhaseTypeHelper {
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";