8297642: PhaseIdealLoop::only_has_infinite_loops must detect all loops that never lead to termination
Reviewed-by: thartmann, roland
This commit is contained in:
parent
fc52f21f9a
commit
d562d3fcbe
@ -4190,45 +4190,40 @@ bool PhaseIdealLoop::process_expensive_nodes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// Goes over all children of the root of the loop tree, collects all controls for the loop and its inner loops then
|
// Goes over all children of the root of the loop tree. Check if any of them have a path
|
||||||
// checks whether any control is a branch out of the loop and if it is, whether it's not a NeverBranch.
|
// down to Root, that does not go via a NeverBranch exit.
|
||||||
bool PhaseIdealLoop::only_has_infinite_loops() {
|
bool PhaseIdealLoop::only_has_infinite_loops() {
|
||||||
|
ResourceMark rm;
|
||||||
|
Unique_Node_List worklist;
|
||||||
|
// start traversal at all loop heads of first-level loops
|
||||||
for (IdealLoopTree* l = _ltree_root->_child; l != NULL; l = l->_next) {
|
for (IdealLoopTree* l = _ltree_root->_child; l != NULL; l = l->_next) {
|
||||||
Unique_Node_List wq;
|
|
||||||
Node* head = l->_head;
|
Node* head = l->_head;
|
||||||
assert(head->is_Region(), "");
|
assert(head->is_Region(), "");
|
||||||
for (uint i = 1; i < head->req(); ++i) {
|
worklist.push(head);
|
||||||
Node* in = head->in(i);
|
|
||||||
if (get_loop(in) != _ltree_root) {
|
|
||||||
wq.push(in);
|
|
||||||
}
|
}
|
||||||
}
|
// BFS traversal down the CFG, except through NeverBranch exits
|
||||||
for (uint i = 0; i < wq.size(); ++i) {
|
for (uint i = 0; i < worklist.size(); ++i) {
|
||||||
Node* c = wq.at(i);
|
Node* n = worklist.at(i);
|
||||||
if (c == head) {
|
assert(n->is_CFG(), "only traverse CFG");
|
||||||
continue;
|
if (n->is_Root()) {
|
||||||
} else if (c->is_Region()) {
|
// Found root -> there was an exit!
|
||||||
for (uint j = 1; j < c->req(); ++j) {
|
|
||||||
wq.push(c->in(j));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wq.push(c->in(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(wq.member(head), "");
|
|
||||||
for (uint i = 0; i < wq.size(); ++i) {
|
|
||||||
Node* c = wq.at(i);
|
|
||||||
if (c->is_MultiBranch()) {
|
|
||||||
for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax; j++) {
|
|
||||||
Node* u = c->fast_out(j);
|
|
||||||
assert(u->is_CFG(), "");
|
|
||||||
if (!wq.member(u) && c->Opcode() != Op_NeverBranch) {
|
|
||||||
return false;
|
return false;
|
||||||
|
} else if (n->Opcode() == Op_NeverBranch) {
|
||||||
|
// Only follow the loop-internal projection, not the NeverBranch exit
|
||||||
|
ProjNode* proj = n->as_Multi()->proj_out_or_null(0);
|
||||||
|
assert(proj != nullptr, "must find loop-internal projection of NeverBranch");
|
||||||
|
worklist.push(proj);
|
||||||
|
} else {
|
||||||
|
// Traverse all CFG outputs
|
||||||
|
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
|
||||||
|
Node* use = n->fast_out(i);
|
||||||
|
if (use->is_CFG()) {
|
||||||
|
worklist.push(use);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// No exit found for any loop -> all are infinite
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Oracle and/or its affiliates. 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 TestOnlyInfiniteLoops
|
||||||
|
{
|
||||||
|
public Method "<init>":"()V"
|
||||||
|
stack 2 locals 1
|
||||||
|
{
|
||||||
|
aload_0;
|
||||||
|
invokespecial Method java/lang/Object."<init>":"()V";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Method test_simple:"(III)I"
|
||||||
|
stack 200 locals 10
|
||||||
|
{
|
||||||
|
// Nested infinite loop, where inner loop eventually
|
||||||
|
// looses exit to outer loop. Then, the inner loop
|
||||||
|
// floats outside the inner loop. The entry from
|
||||||
|
// outer to inner loop now becomes an exit for the
|
||||||
|
// outer loop, where it now enters the next loop, that
|
||||||
|
// used to be the inner loop.
|
||||||
|
iconst_0;
|
||||||
|
istore 9;
|
||||||
|
|
||||||
|
iload 0;
|
||||||
|
ifeq LEND; // skip
|
||||||
|
|
||||||
|
LOOP1:
|
||||||
|
iload 1;
|
||||||
|
ifeq LOOP1; // dominates
|
||||||
|
LOOP2:
|
||||||
|
// SKIP: prevent loop-exit from becoming zero-trip guard
|
||||||
|
iload 2;
|
||||||
|
ifeq SKIP;
|
||||||
|
iinc 9, 1;
|
||||||
|
SKIP:
|
||||||
|
iload 1;
|
||||||
|
ifeq LOOP1; // is dominated
|
||||||
|
goto LOOP2;
|
||||||
|
|
||||||
|
LEND:
|
||||||
|
iload 9;
|
||||||
|
ireturn;
|
||||||
|
}
|
||||||
|
static Method test_irreducible:"(IIII)V"
|
||||||
|
stack 200 locals 200
|
||||||
|
{
|
||||||
|
iload_0;
|
||||||
|
ifeq LEND; // skip
|
||||||
|
|
||||||
|
L1:
|
||||||
|
iload 1;
|
||||||
|
ifgt MERGE;
|
||||||
|
L2:
|
||||||
|
iload 2;
|
||||||
|
ifge MERGE;
|
||||||
|
goto L1;
|
||||||
|
|
||||||
|
MERGE:
|
||||||
|
nop;
|
||||||
|
LOOP:
|
||||||
|
iload 3;
|
||||||
|
ifle L2;
|
||||||
|
iconst_0; // always true
|
||||||
|
ifeq LOOP;
|
||||||
|
iconst_0; // always true
|
||||||
|
ifeq LOOP;
|
||||||
|
INFTY:
|
||||||
|
goto INFTY; // infinite loop
|
||||||
|
|
||||||
|
LEND:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Oracle and/or its affiliates. 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 8297642
|
||||||
|
* @compile TestOnlyInfiniteLoops.jasm
|
||||||
|
* @summary Nested irreducible loops, where the inner loop floats out of the outer
|
||||||
|
* @run main/othervm
|
||||||
|
* -XX:CompileCommand=compileonly,TestOnlyInfiniteLoops::test*
|
||||||
|
* -XX:-TieredCompilation -Xcomp
|
||||||
|
* TestOnlyInfiniteLoopsMain
|
||||||
|
*
|
||||||
|
* @test
|
||||||
|
* @bug 8297642
|
||||||
|
* @compile TestOnlyInfiniteLoops.jasm
|
||||||
|
* @summary Nested irreducible loops, where the inner loop floats out of the outer
|
||||||
|
* @run main/othervm
|
||||||
|
* -XX:CompileCommand=compileonly,TestOnlyInfiniteLoops::test*
|
||||||
|
* -XX:-TieredCompilation -Xcomp
|
||||||
|
* -XX:PerMethodTrapLimit=0
|
||||||
|
* TestOnlyInfiniteLoopsMain
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestOnlyInfiniteLoopsMain {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestOnlyInfiniteLoops t = new TestOnlyInfiniteLoops();
|
||||||
|
System.out.println("test_simple");
|
||||||
|
t.test_simple(0, 0, 0);
|
||||||
|
System.out.println("test_irreducible");
|
||||||
|
t.test_irreducible(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user