Skip to content

Commit 690d626

Browse files
committed
8307927: C2: "malformed control flow" with irreducible loop
Reviewed-by: thartmann, epeter
1 parent be64d3a commit 690d626

File tree

3 files changed

+189
-49
lines changed

3 files changed

+189
-49
lines changed

src/hotspot/share/opto/loopnode.cpp

+52-49
Original file line numberDiff line numberDiff line change
@@ -3531,26 +3531,27 @@ bool IdealLoopTree::beautify_loops( PhaseIdealLoop *phase ) {
35313531
}
35323532

35333533
//------------------------------allpaths_check_safepts----------------------------
3534-
// Allpaths backwards scan from loop tail, terminating each path at first safepoint
3535-
// encountered. Helper for check_safepts.
3534+
// Allpaths backwards scan. Starting at the head, traversing all backedges, and the body. Terminating each path at first
3535+
// safepoint encountered. Helper for check_safepts.
35363536
void IdealLoopTree::allpaths_check_safepts(VectorSet &visited, Node_List &stack) {
35373537
assert(stack.size() == 0, "empty stack");
3538-
stack.push(_tail);
3538+
stack.push(_head);
35393539
visited.clear();
3540-
visited.set(_tail->_idx);
3540+
visited.set(_head->_idx);
35413541
while (stack.size() > 0) {
35423542
Node* n = stack.pop();
35433543
if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) {
35443544
// Terminate this path
35453545
} else if (n->Opcode() == Op_SafePoint) {
35463546
if (_phase->get_loop(n) != this) {
35473547
if (_required_safept == nullptr) _required_safept = new Node_List();
3548-
_required_safept->push(n); // save the one closest to the tail
3548+
// save the first we run into on that path: closest to the tail if the head has a single backedge
3549+
_required_safept->push(n);
35493550
}
35503551
// Terminate this path
35513552
} else {
35523553
uint start = n->is_Region() ? 1 : 0;
3553-
uint end = n->is_Region() && !n->is_Loop() ? n->req() : start + 1;
3554+
uint end = n->is_Region() && (!n->is_Loop() || n == _head) ? n->req() : start + 1;
35543555
for (uint i = start; i < end; i++) {
35553556
Node* in = n->in(i);
35563557
assert(in->is_CFG(), "must be");
@@ -3622,53 +3623,55 @@ void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) {
36223623
if (_child) _child->check_safepts(visited, stack);
36233624
if (_next) _next ->check_safepts(visited, stack);
36243625

3625-
if (!_head->is_CountedLoop() && !_has_sfpt && _parent != nullptr && !_irreducible) {
3626+
if (!_head->is_CountedLoop() && !_has_sfpt && _parent != nullptr) {
36263627
bool has_call = false; // call on dom-path
36273628
bool has_local_ncsfpt = false; // ncsfpt on dom-path at this loop depth
36283629
Node* nonlocal_ncsfpt = nullptr; // ncsfpt on dom-path at a deeper depth
3629-
// Scan the dom-path nodes from tail to head
3630-
for (Node* n = tail(); n != _head; n = _phase->idom(n)) {
3631-
if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) {
3632-
has_call = true;
3633-
_has_sfpt = 1; // Then no need for a safept!
3634-
break;
3635-
} else if (n->Opcode() == Op_SafePoint) {
3636-
if (_phase->get_loop(n) == this) {
3637-
has_local_ncsfpt = true;
3630+
if (!_irreducible) {
3631+
// Scan the dom-path nodes from tail to head
3632+
for (Node* n = tail(); n != _head; n = _phase->idom(n)) {
3633+
if (n->is_Call() && n->as_Call()->guaranteed_safepoint()) {
3634+
has_call = true;
3635+
_has_sfpt = 1; // Then no need for a safept!
36383636
break;
3639-
}
3640-
if (nonlocal_ncsfpt == nullptr) {
3641-
nonlocal_ncsfpt = n; // save the one closest to the tail
3642-
}
3643-
} else {
3644-
IdealLoopTree* nlpt = _phase->get_loop(n);
3645-
if (this != nlpt) {
3646-
// If at an inner loop tail, see if the inner loop has already
3647-
// recorded seeing a call on the dom-path (and stop.) If not,
3648-
// jump to the head of the inner loop.
3649-
assert(is_member(nlpt), "nested loop");
3650-
Node* tail = nlpt->_tail;
3651-
if (tail->in(0)->is_If()) tail = tail->in(0);
3652-
if (n == tail) {
3653-
// If inner loop has call on dom-path, so does outer loop
3654-
if (nlpt->_has_sfpt) {
3655-
has_call = true;
3656-
_has_sfpt = 1;
3657-
break;
3658-
}
3659-
// Skip to head of inner loop
3660-
assert(_phase->is_dominator(_head, nlpt->_head), "inner head dominated by outer head");
3661-
n = nlpt->_head;
3662-
if (_head == n) {
3663-
// this and nlpt (inner loop) have the same loop head. This should not happen because
3664-
// during beautify_loops we call merge_many_backedges. However, infinite loops may not
3665-
// have been attached to the loop-tree during build_loop_tree before beautify_loops,
3666-
// but then attached in the build_loop_tree afterwards, and so still have unmerged
3667-
// backedges. Check if we are indeed in an infinite subgraph, and terminate the scan,
3668-
// since we have reached the loop head of this.
3669-
assert(_head->as_Region()->is_in_infinite_subgraph(),
3670-
"only expect unmerged backedges in infinite loops");
3671-
break;
3637+
} else if (n->Opcode() == Op_SafePoint) {
3638+
if (_phase->get_loop(n) == this) {
3639+
has_local_ncsfpt = true;
3640+
break;
3641+
}
3642+
if (nonlocal_ncsfpt == nullptr) {
3643+
nonlocal_ncsfpt = n; // save the one closest to the tail
3644+
}
3645+
} else {
3646+
IdealLoopTree* nlpt = _phase->get_loop(n);
3647+
if (this != nlpt) {
3648+
// If at an inner loop tail, see if the inner loop has already
3649+
// recorded seeing a call on the dom-path (and stop.) If not,
3650+
// jump to the head of the inner loop.
3651+
assert(is_member(nlpt), "nested loop");
3652+
Node* tail = nlpt->_tail;
3653+
if (tail->in(0)->is_If()) tail = tail->in(0);
3654+
if (n == tail) {
3655+
// If inner loop has call on dom-path, so does outer loop
3656+
if (nlpt->_has_sfpt) {
3657+
has_call = true;
3658+
_has_sfpt = 1;
3659+
break;
3660+
}
3661+
// Skip to head of inner loop
3662+
assert(_phase->is_dominator(_head, nlpt->_head), "inner head dominated by outer head");
3663+
n = nlpt->_head;
3664+
if (_head == n) {
3665+
// this and nlpt (inner loop) have the same loop head. This should not happen because
3666+
// during beautify_loops we call merge_many_backedges. However, infinite loops may not
3667+
// have been attached to the loop-tree during build_loop_tree before beautify_loops,
3668+
// but then attached in the build_loop_tree afterwards, and so still have unmerged
3669+
// backedges. Check if we are indeed in an infinite subgraph, and terminate the scan,
3670+
// since we have reached the loop head of this.
3671+
assert(_head->as_Region()->is_in_infinite_subgraph(),
3672+
"only expect unmerged backedges in infinite loops");
3673+
break;
3674+
}
36723675
}
36733676
}
36743677
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
super public class MalformedControlIrreducibleLoop
25+
version 52:0
26+
{
27+
public Method "<init>":"()V"
28+
stack 1 locals 1
29+
{
30+
aload_0;
31+
invokespecial Method java/lang/Object."<init>":"()V";
32+
return;
33+
}
34+
/* same as:
35+
public static void actualTest(int flag) {
36+
int i = 1;
37+
int j = 1;
38+
if (flag == 2) {
39+
// goto second_entry;
40+
}
41+
loop:
42+
for (;;) {
43+
i = 1;
44+
// second_entry:
45+
do {
46+
if (i == 1) {
47+
continue loop; // goto loop
48+
}
49+
i *= 2;
50+
j *= 2;
51+
} while (j < 2);
52+
break;
53+
}
54+
}
55+
*/
56+
public static Method actualTest:"(I)V"
57+
stack 2 locals 3
58+
{
59+
iconst_1;
60+
istore_1;
61+
iconst_1;
62+
istore_2;
63+
iload_0;
64+
iconst_2;
65+
if_icmpne L11;
66+
L9: stack_frame_type append;
67+
locals_map int, int;
68+
iconst_1;
69+
istore_1;
70+
L11: stack_frame_type same;
71+
iload_1;
72+
iconst_1;
73+
if_icmpeq L9;
74+
L19: stack_frame_type same;
75+
iload_1;
76+
iconst_2;
77+
imul;
78+
istore_1;
79+
iload_2;
80+
iconst_2;
81+
imul;
82+
istore_2;
83+
iload_2;
84+
iconst_2;
85+
if_icmplt L11;
86+
goto L35;
87+
L35: stack_frame_type same;
88+
return;
89+
}
90+
91+
} // end Class TestMalformedControlIrreducibleLoop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8307927
27+
* @summary C2: "malformed control flow" with irreducible loop
28+
* @compile MalformedControlIrreducibleLoop.jasm
29+
* @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=TestMalformedControlIrreducibleLoop::test TestMalformedControlIrreducibleLoop
30+
*/
31+
32+
public class TestMalformedControlIrreducibleLoop {
33+
public static void main(String[] args) {
34+
new MalformedControlIrreducibleLoop();
35+
test(false);
36+
}
37+
38+
private static void test(boolean flag) {
39+
int i;
40+
for (i = 1; i < 2; i *= 2) {
41+
}
42+
if (flag) {
43+
MalformedControlIrreducibleLoop.actualTest(i);
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)