< prev index next >
src/hotspot/share/opto/loopnode.cpp
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -2437,16 +2437,67 @@
assert(loop->_child != this || (loop->_child->_child == NULL && loop->_child->_next == NULL), "would miss some loops");
if (loop->_child && loop->_child != this) loop->_child->counted_loop(phase);
if (loop->_next) loop->_next ->counted_loop(phase);
}
+
+// The Estimated Loop Clone Size:
+// CloneFactor * (~112% * BodySize + BC) + CC + FanOutTerm,
+// where BC and CC are totally ad-hoc/magic "body" and "clone" constants,
+// respectively, used to ensure that the node usage estimates made are on the
+// safe side, for the most part. The FanOutTerm is an attempt to estimate the
+// possible additional/excessive nodes generated due to data and control flow
+// merging, for edges reaching outside the loop.
+uint IdealLoopTree::est_loop_clone_sz(uint factor) const {
+
+ precond(0 < factor && factor < 16);
+
+ uint const bc = 13;
+ uint const cc = 17;
+ uint const sz = _body.size() + (_body.size() + 7) / 8;
+ uint estimate = factor * (sz + bc) + cc;
+
+ assert((estimate - cc) / factor == sz + bc, "overflow");
+
+ uint ctrl_edge_out_cnt = 0;
+ uint data_edge_out_cnt = 0;
+
+ for (uint i = 0; i < _body.size(); i++) {
+ Node* node = _body.at(i);
+ uint outcnt = node->outcnt();
+
+ for (uint k = 0; k < outcnt; k++) {
+ Node* out = node->raw_out(k);
+
+ if (out->is_CFG()) {
+ if (!is_member(_phase->get_loop(out))) {
+ ctrl_edge_out_cnt++;
+ }
+ } else {
+ Node* ctrl = _phase->get_ctrl(out);
+ assert(ctrl->is_CFG(), "must be");
+ if (!is_member(_phase->get_loop(ctrl))) {
+ data_edge_out_cnt++;
+ }
+ }
+ }
+ }
+ // Add data (x1.5) and control (x1.0) count to estimate iff both are > 0.
+ if (ctrl_edge_out_cnt > 0 && data_edge_out_cnt > 0) {
+ estimate += ctrl_edge_out_cnt + data_edge_out_cnt + data_edge_out_cnt / 2;
+ }
+
+ return estimate;
+}
+
#ifndef PRODUCT
//------------------------------dump_head--------------------------------------
// Dump 1 liner for loop header info
-void IdealLoopTree::dump_head( ) const {
- for (uint i=0; i<_nest; i++)
+void IdealLoopTree::dump_head() const {
+ for (uint i = 0; i < _nest; i++) {
tty->print(" ");
+ }
tty->print("Loop: N%d/N%d ",_head->_idx,_tail->_idx);
if (_irreducible) tty->print(" IRREDUCIBLE");
Node* entry = _head->is_Loop() ? _head->as_Loop()->skip_strip_mined(-1)->in(LoopNode::EntryControl) : _head->in(LoopNode::EntryControl);
Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL ) {
@@ -2511,11 +2562,11 @@
tty->cr();
}
//------------------------------dump-------------------------------------------
// Dump loops by loop tree
-void IdealLoopTree::dump( ) const {
+void IdealLoopTree::dump() const {
dump_head();
if (_child) _child->dump();
if (_next) _next ->dump();
}
@@ -2906,12 +2957,12 @@
if (_verify_me) { // Nested verify pass?
// Check to see if the verify mode is broken
assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?");
return;
}
- if(VerifyLoopOptimizations) verify();
- if(TraceLoopOpts && C->has_loops()) {
+ if (VerifyLoopOptimizations) verify();
+ if (TraceLoopOpts && C->has_loops()) {
_ltree_root->dump();
}
#endif
if (skip_loop_opts) {
@@ -2936,26 +2987,28 @@
}
return;
}
if (ReassociateInvariants) {
- AutoNodeBudget node_budget(this, AutoNodeBudget::NO_BUDGET_CHECK);
// Reassociate invariants and prep for split_thru_phi
for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
IdealLoopTree* lpt = iter.current();
bool is_counted = lpt->is_counted();
if (!is_counted || !lpt->is_innermost()) continue;
// check for vectorized loops, any reassociation of invariants was already done
- if (is_counted && lpt->_head->as_CountedLoop()->is_unroll_only()) continue;
-
+ if (is_counted && lpt->_head->as_CountedLoop()->is_unroll_only()) {
+ continue;
+ } else {
+ AutoNodeBudget node_budget(this);
lpt->reassociate_invariants(this);
-
+ }
// Because RCE opportunities can be masked by split_thru_phi,
// look for RCE candidates and inhibit split_thru_phi
// on just their loop-phi's for this pass of loop opts
if (SplitIfBlocks && do_split_ifs) {
+ AutoNodeBudget node_budget(this, AutoNodeBudget::NO_BUDGET_CHECK);
if (lpt->policy_range_check(this)) {
lpt->_rce_candidate = 1; // = true
}
}
}
< prev index next >