Skip to content

Commit d562d3f

Browse files
committed
8297642: PhaseIdealLoop::only_has_infinite_loops must detect all loops that never lead to termination
Reviewed-by: thartmann, roland
1 parent fc52f21 commit d562d3f

File tree

3 files changed

+175
-31
lines changed

3 files changed

+175
-31
lines changed

src/hotspot/share/opto/loopnode.cpp

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4190,45 +4190,40 @@ bool PhaseIdealLoop::process_expensive_nodes() {
41904190
}
41914191

41924192
#ifdef ASSERT
4193-
// Goes over all children of the root of the loop tree, collects all controls for the loop and its inner loops then
4194-
// checks whether any control is a branch out of the loop and if it is, whether it's not a NeverBranch.
4193+
// Goes over all children of the root of the loop tree. Check if any of them have a path
4194+
// down to Root, that does not go via a NeverBranch exit.
41954195
bool PhaseIdealLoop::only_has_infinite_loops() {
4196+
ResourceMark rm;
4197+
Unique_Node_List worklist;
4198+
// start traversal at all loop heads of first-level loops
41964199
for (IdealLoopTree* l = _ltree_root->_child; l != NULL; l = l->_next) {
4197-
Unique_Node_List wq;
41984200
Node* head = l->_head;
41994201
assert(head->is_Region(), "");
4200-
for (uint i = 1; i < head->req(); ++i) {
4201-
Node* in = head->in(i);
4202-
if (get_loop(in) != _ltree_root) {
4203-
wq.push(in);
4204-
}
4205-
}
4206-
for (uint i = 0; i < wq.size(); ++i) {
4207-
Node* c = wq.at(i);
4208-
if (c == head) {
4209-
continue;
4210-
} else if (c->is_Region()) {
4211-
for (uint j = 1; j < c->req(); ++j) {
4212-
wq.push(c->in(j));
4213-
}
4214-
} else {
4215-
wq.push(c->in(0));
4216-
}
4217-
}
4218-
assert(wq.member(head), "");
4219-
for (uint i = 0; i < wq.size(); ++i) {
4220-
Node* c = wq.at(i);
4221-
if (c->is_MultiBranch()) {
4222-
for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax; j++) {
4223-
Node* u = c->fast_out(j);
4224-
assert(u->is_CFG(), "");
4225-
if (!wq.member(u) && c->Opcode() != Op_NeverBranch) {
4226-
return false;
4227-
}
4202+
worklist.push(head);
4203+
}
4204+
// BFS traversal down the CFG, except through NeverBranch exits
4205+
for (uint i = 0; i < worklist.size(); ++i) {
4206+
Node* n = worklist.at(i);
4207+
assert(n->is_CFG(), "only traverse CFG");
4208+
if (n->is_Root()) {
4209+
// Found root -> there was an exit!
4210+
return false;
4211+
} else if (n->Opcode() == Op_NeverBranch) {
4212+
// Only follow the loop-internal projection, not the NeverBranch exit
4213+
ProjNode* proj = n->as_Multi()->proj_out_or_null(0);
4214+
assert(proj != nullptr, "must find loop-internal projection of NeverBranch");
4215+
worklist.push(proj);
4216+
} else {
4217+
// Traverse all CFG outputs
4218+
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
4219+
Node* use = n->fast_out(i);
4220+
if (use->is_CFG()) {
4221+
worklist.push(use);
42284222
}
42294223
}
42304224
}
42314225
}
4226+
// No exit found for any loop -> all are infinite
42324227
return true;
42334228
}
42344229
#endif
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. 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+
super public class TestOnlyInfiniteLoops
26+
{
27+
public Method "<init>":"()V"
28+
stack 2 locals 1
29+
{
30+
aload_0;
31+
invokespecial Method java/lang/Object."<init>":"()V";
32+
return;
33+
}
34+
35+
static Method test_simple:"(III)I"
36+
stack 200 locals 10
37+
{
38+
// Nested infinite loop, where inner loop eventually
39+
// looses exit to outer loop. Then, the inner loop
40+
// floats outside the inner loop. The entry from
41+
// outer to inner loop now becomes an exit for the
42+
// outer loop, where it now enters the next loop, that
43+
// used to be the inner loop.
44+
iconst_0;
45+
istore 9;
46+
47+
iload 0;
48+
ifeq LEND; // skip
49+
50+
LOOP1:
51+
iload 1;
52+
ifeq LOOP1; // dominates
53+
LOOP2:
54+
// SKIP: prevent loop-exit from becoming zero-trip guard
55+
iload 2;
56+
ifeq SKIP;
57+
iinc 9, 1;
58+
SKIP:
59+
iload 1;
60+
ifeq LOOP1; // is dominated
61+
goto LOOP2;
62+
63+
LEND:
64+
iload 9;
65+
ireturn;
66+
}
67+
static Method test_irreducible:"(IIII)V"
68+
stack 200 locals 200
69+
{
70+
iload_0;
71+
ifeq LEND; // skip
72+
73+
L1:
74+
iload 1;
75+
ifgt MERGE;
76+
L2:
77+
iload 2;
78+
ifge MERGE;
79+
goto L1;
80+
81+
MERGE:
82+
nop;
83+
LOOP:
84+
iload 3;
85+
ifle L2;
86+
iconst_0; // always true
87+
ifeq LOOP;
88+
iconst_0; // always true
89+
ifeq LOOP;
90+
INFTY:
91+
goto INFTY; // infinite loop
92+
93+
LEND:
94+
return;
95+
}
96+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. 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 8297642
27+
* @compile TestOnlyInfiniteLoops.jasm
28+
* @summary Nested irreducible loops, where the inner loop floats out of the outer
29+
* @run main/othervm
30+
* -XX:CompileCommand=compileonly,TestOnlyInfiniteLoops::test*
31+
* -XX:-TieredCompilation -Xcomp
32+
* TestOnlyInfiniteLoopsMain
33+
*
34+
* @test
35+
* @bug 8297642
36+
* @compile TestOnlyInfiniteLoops.jasm
37+
* @summary Nested irreducible loops, where the inner loop floats out of the outer
38+
* @run main/othervm
39+
* -XX:CompileCommand=compileonly,TestOnlyInfiniteLoops::test*
40+
* -XX:-TieredCompilation -Xcomp
41+
* -XX:PerMethodTrapLimit=0
42+
* TestOnlyInfiniteLoopsMain
43+
*/
44+
45+
public class TestOnlyInfiniteLoopsMain {
46+
public static void main(String[] args) {
47+
TestOnlyInfiniteLoops t = new TestOnlyInfiniteLoops();
48+
System.out.println("test_simple");
49+
t.test_simple(0, 0, 0);
50+
System.out.println("test_irreducible");
51+
t.test_irreducible(0, 0, 0, 0);
52+
}
53+
}

0 commit comments

Comments
 (0)