提交 77a3acc8 编写于 作者: A aeriksso

6869327: Add new C2 flag to keep safepoints in counted loops.

Reviewed-by: kvn
上级 3e3610d3
...@@ -205,6 +205,9 @@ ...@@ -205,6 +205,9 @@
notproduct(bool, TraceProfileTripCount, false, \ notproduct(bool, TraceProfileTripCount, false, \
"Trace profile loop trip count information") \ "Trace profile loop trip count information") \
\ \
product(bool, UseCountedLoopSafepoints, false, \
"Force counted loops to keep a safepoint") \
\
product(bool, UseLoopPredicate, true, \ product(bool, UseLoopPredicate, true, \
"Generate a predicate to select fast/slow loop versions") \ "Generate a predicate to select fast/slow loop versions") \
\ \
......
...@@ -685,14 +685,16 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { ...@@ -685,14 +685,16 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
} // LoopLimitCheck } // LoopLimitCheck
// Check for SafePoint on backedge and remove if (!UseCountedLoopSafepoints) {
Node *sfpt = x->in(LoopNode::LoopBackControl); // Check for SafePoint on backedge and remove
if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) { Node *sfpt = x->in(LoopNode::LoopBackControl);
lazy_replace( sfpt, iftrue ); if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) {
if (loop->_safepts != NULL) { lazy_replace( sfpt, iftrue );
loop->_safepts->yank(sfpt); if (loop->_safepts != NULL) {
loop->_safepts->yank(sfpt);
}
loop->_tail = iftrue;
} }
loop->_tail = iftrue;
} }
// Build a canonical trip test. // Build a canonical trip test.
...@@ -781,12 +783,14 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { ...@@ -781,12 +783,14 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
lazy_replace( x, l ); lazy_replace( x, l );
set_idom(l, init_control, dom_depth(x)); set_idom(l, init_control, dom_depth(x));
// Check for immediately preceding SafePoint and remove if (!UseCountedLoopSafepoints) {
Node *sfpt2 = le->in(0); // Check for immediately preceding SafePoint and remove
if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2)) { Node *sfpt2 = le->in(0);
lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control)); if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2)) {
if (loop->_safepts != NULL) { lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control));
loop->_safepts->yank(sfpt2); if (loop->_safepts != NULL) {
loop->_safepts->yank(sfpt2);
}
} }
} }
...@@ -1806,6 +1810,33 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { ...@@ -1806,6 +1810,33 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) {
} }
} }
void IdealLoopTree::remove_safepoints(PhaseIdealLoop* phase, bool keep_one) {
// Look for a safepoint on the idom-path.
Node* keep = NULL;
if (keep_one) {
// Keep one if possible
for (Node* i = tail(); i != _head; i = phase->idom(i)) {
if (i->Opcode() == Op_SafePoint && phase->get_loop(i) == this) {
keep = i;
break; // Found one
}
}
}
// Delete other safepoints in this loop.
Node_List* sfpts = _safepts;
if (sfpts != NULL) {
assert(keep == NULL || keep->Opcode() == Op_SafePoint, "not safepoint");
for (uint i = 0; i < sfpts->size(); i++) {
Node* n = sfpts->at(i);
assert(phase->get_loop(n) == this, "");
if (n != keep && phase->is_deleteable_safept(n)) {
phase->lazy_replace(n, n->in(TypeFunc::Control));
}
}
}
}
//------------------------------counted_loop----------------------------------- //------------------------------counted_loop-----------------------------------
// Convert to counted loops where possible // Convert to counted loops where possible
void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) {
...@@ -1817,42 +1848,23 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { ...@@ -1817,42 +1848,23 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) {
if (_head->is_CountedLoop() || if (_head->is_CountedLoop() ||
phase->is_counted_loop(_head, this)) { phase->is_counted_loop(_head, this)) {
_has_sfpt = 1; // Indicate we do not need a safepoint here
// Look for safepoints to remove. if (!UseCountedLoopSafepoints) {
Node_List* sfpts = _safepts; // Indicate we do not need a safepoint here
if (sfpts != NULL) { _has_sfpt = 1;
for (uint i = 0; i < sfpts->size(); i++) {
Node* n = sfpts->at(i);
assert(phase->get_loop(n) == this, "");
if (phase->is_deleteable_safept(n)) {
phase->lazy_replace(n, n->in(TypeFunc::Control));
}
}
} }
// Remove safepoints
bool keep_one_sfpt = !(_has_call || _has_sfpt);
remove_safepoints(phase, keep_one_sfpt);
// Look for induction variables // Look for induction variables
phase->replace_parallel_iv(this); phase->replace_parallel_iv(this);
} else if (_parent != NULL && !_irreducible) { } else if (_parent != NULL && !_irreducible) {
// Not a counted loop. // Not a counted loop. Keep one safepoint.
// Look for a safepoint on the idom-path. bool keep_one_sfpt = true;
Node* sfpt = tail(); remove_safepoints(phase, keep_one_sfpt);
for (; sfpt != _head; sfpt = phase->idom(sfpt)) {
if (sfpt->Opcode() == Op_SafePoint && phase->get_loop(sfpt) == this)
break; // Found one
}
// Delete other safepoints in this loop.
Node_List* sfpts = _safepts;
if (sfpts != NULL && sfpt != _head && sfpt->Opcode() == Op_SafePoint) {
for (uint i = 0; i < sfpts->size(); i++) {
Node* n = sfpts->at(i);
assert(phase->get_loop(n) == this, "");
if (n != sfpt && phase->is_deleteable_safept(n)) {
phase->lazy_replace(n, n->in(TypeFunc::Control));
}
}
}
} }
// Recursively // Recursively
......
/* /*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -403,6 +403,9 @@ public: ...@@ -403,6 +403,9 @@ public:
// encountered. // encountered.
void allpaths_check_safepts(VectorSet &visited, Node_List &stack); void allpaths_check_safepts(VectorSet &visited, Node_List &stack);
// Remove safepoints from loop. Optionally keeping one.
void remove_safepoints(PhaseIdealLoop* phase, bool keep_one);
// Convert to counted loops where possible // Convert to counted loops where possible
void counted_loop( PhaseIdealLoop *phase ); void counted_loop( PhaseIdealLoop *phase );
......
/*
* Copyright (c) 2015, 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @bug 6869327
* @summary Test that C2 flag UseCountedLoopSafepoints ensures a safepoint is kept in a CountedLoop
* @library /testlibrary
* @run main UseCountedLoopSafepoints
*/
import java.util.concurrent.atomic.AtomicLong;
import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
public class UseCountedLoopSafepoints {
private static final AtomicLong _num = new AtomicLong(0);
// Uses the fact that an EnableBiasedLocking vmop will be started
// after 500ms, while we are still in the loop. If there is a
// safepoint in the counted loop, then we will reach safepoint
// very quickly. Otherwise SafepointTimeout will be hit.
public static void main (String args[]) throws Exception {
if (args.length == 1) {
final int loops = Integer.parseInt(args[0]);
for (int i = 0; i < loops; i++) {
_num.addAndGet(1);
}
} else {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+IgnoreUnrecognizedVMOptions",
"-XX:-TieredCompilation",
"-XX:+UseBiasedLocking",
"-XX:BiasedLockingStartupDelay=500",
"-XX:+SafepointTimeout",
"-XX:SafepointTimeoutDelay=2000",
"-XX:+UseCountedLoopSafepoints",
"UseCountedLoopSafepoints",
"2000000000"
);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Timeout detected");
output.shouldHaveExitValue(0);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册