8307927: C2: "malformed control flow" with irreducible loop
Reviewed-by: thartmann, epeter
This commit is contained in:
parent
be64d3ac3c
commit
690d626995
@ -3531,13 +3531,13 @@ bool IdealLoopTree::beautify_loops( PhaseIdealLoop *phase ) {
|
||||
}
|
||||
|
||||
//------------------------------allpaths_check_safepts----------------------------
|
||||
// Allpaths backwards scan from loop tail, terminating each path at first safepoint
|
||||
// encountered. Helper for check_safepts.
|
||||
// Allpaths backwards scan. Starting at the head, traversing all backedges, and the body. Terminating each path at first
|
||||
// safepoint encountered. Helper for check_safepts.
|
||||
void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack) {
|
||||
assert(stack.size() == 0, "empty stack");
|
||||
stack.push(_tail);
|
||||
stack.push(_head);
|
||||
visited.clear();
|
||||
visited.set(_tail->_idx);
|
||||
visited.set(_head->_idx);
|
||||
while (stack.size() > 0) {
|
||||
Node* n = stack.pop();
|
||||
if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) {
|
||||
@ -3545,12 +3545,13 @@ void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack)
|
||||
} else if (n->Opcode() == Op_SafePoint) {
|
||||
if (_phase->get_loop(n) != this) {
|
||||
if (_required_safept == nullptr) _required_safept = new Node_List();
|
||||
_required_safept->push(n); // save the one closest to the tail
|
||||
// save the first we run into on that path: closest to the tail if the head has a single backedge
|
||||
_required_safept->push(n);
|
||||
}
|
||||
// Terminate this path
|
||||
} else {
|
||||
uint start = n->is_Region() ? 1 : 0;
|
||||
uint end = n->is_Region() && !n->is_Loop() ? n->req() : start + 1;
|
||||
uint end = n->is_Region() && (!n->is_Loop() || n == _head) ? n->req() : start + 1;
|
||||
for (uint i = start; i < end; i++) {
|
||||
Node* in = n->in(i);
|
||||
assert(in->is_CFG(), "must be");
|
||||
@ -3622,53 +3623,55 @@ void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) {
|
||||
if (_child) _child->check_safepts(visited, stack);
|
||||
if (_next) _next ->check_safepts(visited, stack);
|
||||
|
||||
if (!_head->is_CountedLoop() && !_has_sfpt && _parent != nullptr && !_irreducible) {
|
||||
if (!_head->is_CountedLoop() && !_has_sfpt && _parent != nullptr) {
|
||||
bool has_call = false; // call on dom-path
|
||||
bool has_local_ncsfpt = false; // ncsfpt on dom-path at this loop depth
|
||||
Node* nonlocal_ncsfpt = nullptr; // ncsfpt on dom-path at a deeper depth
|
||||
// Scan the dom-path nodes from tail to head
|
||||
for (Node* n = tail(); n != _head; n = _phase->idom(n)) {
|
||||
if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) {
|
||||
has_call = true;
|
||||
_has_sfpt = 1; // Then no need for a safept!
|
||||
break;
|
||||
} else if (n->Opcode() == Op_SafePoint) {
|
||||
if (_phase->get_loop(n) == this) {
|
||||
has_local_ncsfpt = true;
|
||||
if (!_irreducible) {
|
||||
// Scan the dom-path nodes from tail to head
|
||||
for (Node* n = tail(); n != _head; n = _phase->idom(n)) {
|
||||
if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) {
|
||||
has_call = true;
|
||||
_has_sfpt = 1; // Then no need for a safept!
|
||||
break;
|
||||
}
|
||||
if (nonlocal_ncsfpt == nullptr) {
|
||||
nonlocal_ncsfpt = n; // save the one closest to the tail
|
||||
}
|
||||
} else {
|
||||
IdealLoopTree* nlpt = _phase->get_loop(n);
|
||||
if (this != nlpt) {
|
||||
// If at an inner loop tail, see if the inner loop has already
|
||||
// recorded seeing a call on the dom-path (and stop.) If not,
|
||||
// jump to the head of the inner loop.
|
||||
assert(is_member(nlpt), "nested loop");
|
||||
Node* tail = nlpt->_tail;
|
||||
if (tail->in(0)->is_If()) tail = tail->in(0);
|
||||
if (n == tail) {
|
||||
// If inner loop has call on dom-path, so does outer loop
|
||||
if (nlpt->_has_sfpt) {
|
||||
has_call = true;
|
||||
_has_sfpt = 1;
|
||||
break;
|
||||
}
|
||||
// Skip to head of inner loop
|
||||
assert(_phase->is_dominator(_head, nlpt->_head), "inner head dominated by outer head");
|
||||
n = nlpt->_head;
|
||||
if (_head == n) {
|
||||
// this and nlpt (inner loop) have the same loop head. This should not happen because
|
||||
// during beautify_loops we call merge_many_backedges. However, infinite loops may not
|
||||
// have been attached to the loop-tree during build_loop_tree before beautify_loops,
|
||||
// but then attached in the build_loop_tree afterwards, and so still have unmerged
|
||||
// backedges. Check if we are indeed in an infinite subgraph, and terminate the scan,
|
||||
// since we have reached the loop head of this.
|
||||
assert(_head->as_Region()->is_in_infinite_subgraph(),
|
||||
"only expect unmerged backedges in infinite loops");
|
||||
break;
|
||||
} else if (n->Opcode() == Op_SafePoint) {
|
||||
if (_phase->get_loop(n) == this) {
|
||||
has_local_ncsfpt = true;
|
||||
break;
|
||||
}
|
||||
if (nonlocal_ncsfpt == nullptr) {
|
||||
nonlocal_ncsfpt = n; // save the one closest to the tail
|
||||
}
|
||||
} else {
|
||||
IdealLoopTree* nlpt = _phase->get_loop(n);
|
||||
if (this != nlpt) {
|
||||
// If at an inner loop tail, see if the inner loop has already
|
||||
// recorded seeing a call on the dom-path (and stop.) If not,
|
||||
// jump to the head of the inner loop.
|
||||
assert(is_member(nlpt), "nested loop");
|
||||
Node* tail = nlpt->_tail;
|
||||
if (tail->in(0)->is_If()) tail = tail->in(0);
|
||||
if (n == tail) {
|
||||
// If inner loop has call on dom-path, so does outer loop
|
||||
if (nlpt->_has_sfpt) {
|
||||
has_call = true;
|
||||
_has_sfpt = 1;
|
||||
break;
|
||||
}
|
||||
// Skip to head of inner loop
|
||||
assert(_phase->is_dominator(_head, nlpt->_head), "inner head dominated by outer head");
|
||||
n = nlpt->_head;
|
||||
if (_head == n) {
|
||||
// this and nlpt (inner loop) have the same loop head. This should not happen because
|
||||
// during beautify_loops we call merge_many_backedges. However, infinite loops may not
|
||||
// have been attached to the loop-tree during build_loop_tree before beautify_loops,
|
||||
// but then attached in the build_loop_tree afterwards, and so still have unmerged
|
||||
// backedges. Check if we are indeed in an infinite subgraph, and terminate the scan,
|
||||
// since we have reached the loop head of this.
|
||||
assert(_head->as_Region()->is_in_infinite_subgraph(),
|
||||
"only expect unmerged backedges in infinite loops");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Red Hat, Inc. 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.
|
||||
*/
|
||||
|
||||
super public class MalformedControlIrreducibleLoop
|
||||
version 52:0
|
||||
{
|
||||
public Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
/* same as:
|
||||
public static void actualTest(int flag) {
|
||||
int i = 1;
|
||||
int j = 1;
|
||||
if (flag == 2) {
|
||||
// goto second_entry;
|
||||
}
|
||||
loop:
|
||||
for (;;) {
|
||||
i = 1;
|
||||
// second_entry:
|
||||
do {
|
||||
if (i == 1) {
|
||||
continue loop; // goto loop
|
||||
}
|
||||
i *= 2;
|
||||
j *= 2;
|
||||
} while (j < 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
public static Method actualTest:"(I)V"
|
||||
stack 2 locals 3
|
||||
{
|
||||
iconst_1;
|
||||
istore_1;
|
||||
iconst_1;
|
||||
istore_2;
|
||||
iload_0;
|
||||
iconst_2;
|
||||
if_icmpne L11;
|
||||
L9: stack_frame_type append;
|
||||
locals_map int, int;
|
||||
iconst_1;
|
||||
istore_1;
|
||||
L11: stack_frame_type same;
|
||||
iload_1;
|
||||
iconst_1;
|
||||
if_icmpeq L9;
|
||||
L19: stack_frame_type same;
|
||||
iload_1;
|
||||
iconst_2;
|
||||
imul;
|
||||
istore_1;
|
||||
iload_2;
|
||||
iconst_2;
|
||||
imul;
|
||||
istore_2;
|
||||
iload_2;
|
||||
iconst_2;
|
||||
if_icmplt L11;
|
||||
goto L35;
|
||||
L35: stack_frame_type same;
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class TestMalformedControlIrreducibleLoop
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Red Hat, Inc. 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 8307927
|
||||
* @summary C2: "malformed control flow" with irreducible loop
|
||||
* @compile MalformedControlIrreducibleLoop.jasm
|
||||
* @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=TestMalformedControlIrreducibleLoop::test TestMalformedControlIrreducibleLoop
|
||||
*/
|
||||
|
||||
public class TestMalformedControlIrreducibleLoop {
|
||||
public static void main(String[] args) {
|
||||
new MalformedControlIrreducibleLoop();
|
||||
test(false);
|
||||
}
|
||||
|
||||
private static void test(boolean flag) {
|
||||
int i;
|
||||
for (i = 1; i < 2; i *= 2) {
|
||||
}
|
||||
if (flag) {
|
||||
MalformedControlIrreducibleLoop.actualTest(i);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user