mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-16 17:14:41 +02:00
7160161: Missed safepoint in non-Counted loop
Do not remove safepoints during peeling optimization. Reviewed-by: twisti
This commit is contained in:
parent
373b8ccd27
commit
da65cc4532
3 changed files with 45 additions and 26 deletions
|
@ -547,11 +547,6 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
|
||||||
Node *nnn = old_new[old->_idx];
|
Node *nnn = old_new[old->_idx];
|
||||||
if (!has_ctrl(nnn))
|
if (!has_ctrl(nnn))
|
||||||
set_idom(nnn, idom(nnn), dd-1);
|
set_idom(nnn, idom(nnn), dd-1);
|
||||||
// While we're at it, remove any SafePoints from the peeled code
|
|
||||||
if (old->Opcode() == Op_SafePoint) {
|
|
||||||
Node *nnn = old_new[old->_idx];
|
|
||||||
lazy_replace(nnn,nnn->in(TypeFunc::Control));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now force out all loop-invariant dominating tests. The optimizer
|
// Now force out all loop-invariant dominating tests. The optimizer
|
||||||
|
|
|
@ -577,6 +577,9 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
|
||||||
Node *sfpt = x->in(LoopNode::LoopBackControl);
|
Node *sfpt = x->in(LoopNode::LoopBackControl);
|
||||||
if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) {
|
if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) {
|
||||||
lazy_replace( sfpt, iftrue );
|
lazy_replace( sfpt, iftrue );
|
||||||
|
if (loop->_safepts != NULL) {
|
||||||
|
loop->_safepts->yank(sfpt);
|
||||||
|
}
|
||||||
loop->_tail = iftrue;
|
loop->_tail = iftrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,8 +671,12 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
|
||||||
|
|
||||||
// Check for immediately preceding SafePoint and remove
|
// Check for immediately preceding SafePoint and remove
|
||||||
Node *sfpt2 = le->in(0);
|
Node *sfpt2 = le->in(0);
|
||||||
if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2))
|
if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2)) {
|
||||||
lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control));
|
lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control));
|
||||||
|
if (loop->_safepts != NULL) {
|
||||||
|
loop->_safepts->yank(sfpt2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Free up intermediate goo
|
// Free up intermediate goo
|
||||||
_igvn.remove_dead_node(hook);
|
_igvn.remove_dead_node(hook);
|
||||||
|
@ -1526,10 +1533,8 @@ void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack)
|
||||||
void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) {
|
void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) {
|
||||||
// Bottom up traversal
|
// Bottom up traversal
|
||||||
IdealLoopTree* ch = _child;
|
IdealLoopTree* ch = _child;
|
||||||
while (ch != NULL) {
|
if (_child) _child->check_safepts(visited, stack);
|
||||||
ch->check_safepts(visited, stack);
|
if (_next) _next ->check_safepts(visited, stack);
|
||||||
ch = ch->_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_head->is_CountedLoop() && !_has_sfpt && _parent != NULL && !_irreducible) {
|
if (!_head->is_CountedLoop() && !_has_sfpt && _parent != NULL && !_irreducible) {
|
||||||
bool has_call = false; // call on dom-path
|
bool has_call = false; // call on dom-path
|
||||||
|
@ -1702,29 +1707,39 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) {
|
||||||
phase->is_counted_loop(_head, this)) {
|
phase->is_counted_loop(_head, this)) {
|
||||||
_has_sfpt = 1; // Indicate we do not need a safepoint here
|
_has_sfpt = 1; // Indicate we do not need a safepoint here
|
||||||
|
|
||||||
// Look for a safepoint to remove
|
// Look for safepoints to remove.
|
||||||
for (Node* n = tail(); n != _head; n = phase->idom(n))
|
Node_List* sfpts = _safepts;
|
||||||
if (n->Opcode() == Op_SafePoint && phase->get_loop(n) == this &&
|
if (sfpts != NULL) {
|
||||||
phase->is_deleteable_safept(n))
|
for (uint i = 0; i < sfpts->size(); i++) {
|
||||||
phase->lazy_replace(n,n->in(TypeFunc::Control));
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
// Look for a safepoint on the idom-path to remove, preserving the first one
|
// Look for a safepoint on the idom-path.
|
||||||
bool found = false;
|
Node* sfpt = tail();
|
||||||
Node* n = tail();
|
for (; sfpt != _head; sfpt = phase->idom(sfpt)) {
|
||||||
for (; n != _head && !found; n = phase->idom(n)) {
|
if (sfpt->Opcode() == Op_SafePoint && phase->get_loop(sfpt) == this)
|
||||||
if (n->Opcode() == Op_SafePoint && phase->get_loop(n) == this)
|
break; // Found one
|
||||||
found = true; // Found one
|
|
||||||
}
|
}
|
||||||
// Skip past it and delete the others
|
// Delete other safepoints in this loop.
|
||||||
for (; n != _head; n = phase->idom(n)) {
|
Node_List* sfpts = _safepts;
|
||||||
if (n->Opcode() == Op_SafePoint && phase->get_loop(n) == this &&
|
if (sfpts != NULL && sfpt != _head && sfpt->Opcode() == Op_SafePoint) {
|
||||||
phase->is_deleteable_safept(n))
|
for (uint i = 0; i < sfpts->size(); i++) {
|
||||||
phase->lazy_replace(n,n->in(TypeFunc::Control));
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2766,6 +2781,10 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
|
||||||
// if the allocation is not eliminated for some reason.
|
// if the allocation is not eliminated for some reason.
|
||||||
innermost->_allow_optimizations = false;
|
innermost->_allow_optimizations = false;
|
||||||
innermost->_has_call = 1; // = true
|
innermost->_has_call = 1; // = true
|
||||||
|
} else if (n->Opcode() == Op_SafePoint) {
|
||||||
|
// Record all safepoints in this loop.
|
||||||
|
if (innermost->_safepts == NULL) innermost->_safepts = new Node_List();
|
||||||
|
innermost->_safepts->push(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2816,6 +2835,9 @@ void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist,
|
||||||
is_deleteable_safept(n)) {
|
is_deleteable_safept(n)) {
|
||||||
Node *in = n->in(TypeFunc::Control);
|
Node *in = n->in(TypeFunc::Control);
|
||||||
lazy_replace(n,in); // Pull safepoint now
|
lazy_replace(n,in); // Pull safepoint now
|
||||||
|
if (ilt->_safepts != NULL) {
|
||||||
|
ilt->_safepts->yank(n);
|
||||||
|
}
|
||||||
// Carry on with the recursion "as if" we are walking
|
// Carry on with the recursion "as if" we are walking
|
||||||
// only the control input
|
// only the control input
|
||||||
if( !visited.test_set( in->_idx ) ) {
|
if( !visited.test_set( in->_idx ) ) {
|
||||||
|
|
|
@ -336,6 +336,7 @@ public:
|
||||||
_has_sfpt:1, // True if has non-call safepoint
|
_has_sfpt:1, // True if has non-call safepoint
|
||||||
_rce_candidate:1; // True if candidate for range check elimination
|
_rce_candidate:1; // True if candidate for range check elimination
|
||||||
|
|
||||||
|
Node_List* _safepts; // List of safepoints in this loop
|
||||||
Node_List* _required_safept; // A inner loop cannot delete these safepts;
|
Node_List* _required_safept; // A inner loop cannot delete these safepts;
|
||||||
bool _allow_optimizations; // Allow loop optimizations
|
bool _allow_optimizations; // Allow loop optimizations
|
||||||
|
|
||||||
|
@ -343,6 +344,7 @@ public:
|
||||||
: _parent(0), _next(0), _child(0),
|
: _parent(0), _next(0), _child(0),
|
||||||
_head(head), _tail(tail),
|
_head(head), _tail(tail),
|
||||||
_phase(phase),
|
_phase(phase),
|
||||||
|
_safepts(NULL),
|
||||||
_required_safept(NULL),
|
_required_safept(NULL),
|
||||||
_allow_optimizations(true),
|
_allow_optimizations(true),
|
||||||
_nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0)
|
_nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue