Skip to content

Commit 1d6db44

Browse files
committed
8297642: PhaseIdealLoop::only_has_infinite_loops must detect all loops that never lead to termination
Backport-of: d562d3fcbe22a0443037c5b447e1a41401275814
1 parent b5c7a6f commit 1d6db44

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
@@ -3693,45 +3693,40 @@ bool PhaseIdealLoop::process_expensive_nodes() {
36933693
}
36943694

36953695
#ifdef ASSERT
3696-
// Goes over all children of the root of the loop tree, collects all controls for the loop and its inner loops then
3697-
// checks whether any control is a branch out of the loop and if it is, whether it's not a NeverBranch.
3696+
// Goes over all children of the root of the loop tree. Check if any of them have a path
3697+
// down to Root, that does not go via a NeverBranch exit.
36983698
bool PhaseIdealLoop::only_has_infinite_loops() {
3699+
ResourceMark rm;
3700+
Unique_Node_List worklist;
3701+
// start traversal at all loop heads of first-level loops
36993702
for (IdealLoopTree* l = _ltree_root->_child; l != NULL; l = l->_next) {
3700-
Unique_Node_List wq;
37013703
Node* head = l->_head;
37023704
assert(head->is_Region(), "");
3703-
for (uint i = 1; i < head->req(); ++i) {
3704-
Node* in = head->in(i);
3705-
if (get_loop(in) != _ltree_root) {
3706-
wq.push(in);
3707-
}
3708-
}
3709-
for (uint i = 0; i < wq.size(); ++i) {
3710-
Node* c = wq.at(i);
3711-
if (c == head) {
3712-
continue;
3713-
} else if (c->is_Region()) {
3714-
for (uint j = 1; j < c->req(); ++j) {
3715-
wq.push(c->in(j));
3716-
}
3717-
} else {
3718-
wq.push(c->in(0));
3719-
}
3720-
}
3721-
assert(wq.member(head), "");
3722-
for (uint i = 0; i < wq.size(); ++i) {
3723-
Node* c = wq.at(i);
3724-
if (c->is_MultiBranch()) {
3725-
for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax; j++) {
3726-
Node* u = c->fast_out(j);
3727-
assert(u->is_CFG(), "");
3728-
if (!wq.member(u) && c->Opcode() != Op_NeverBranch) {
3729-
return false;
3730-
}
3705+
worklist.push(head);
3706+
}
3707+
// BFS traversal down the CFG, except through NeverBranch exits
3708+
for (uint i = 0; i < worklist.size(); ++i) {
3709+
Node* n = worklist.at(i);
3710+
assert(n->is_CFG(), "only traverse CFG");
3711+
if (n->is_Root()) {
3712+
// Found root -> there was an exit!
3713+
return false;
3714+
} else if (n->Opcode() == Op_NeverBranch) {
3715+
// Only follow the loop-internal projection, not the NeverBranch exit
3716+
ProjNode* proj = n->as_Multi()->proj_out_or_null(0);
3717+
assert(proj != nullptr, "must find loop-internal projection of NeverBranch");
3718+
worklist.push(proj);
3719+
} else {
3720+
// Traverse all CFG outputs
3721+
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
3722+
Node* use = n->fast_out(i);
3723+
if (use->is_CFG()) {
3724+
worklist.push(use);
37313725
}
37323726
}
37333727
}
37343728
}
3729+
// No exit found for any loop -> all are infinite
37353730
return true;
37363731
}
37373732
#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)