| /* |
| * Copyright (c) 2023, 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 8280126 |
| * @compile TestDeadIrreducibleLoops.jasm |
| * @summary Irreducible loops have many entries, only when the last entry loses |
| * control from the outside does the loop die, and have to disappear. |
| * @run main/othervm |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoopsMain::test* |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoops::test* |
| * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN |
| * TestDeadIrreducibleLoopsMain |
| */ |
| |
| /* |
| * @test |
| * @bug 8280126 |
| * @compile TestDeadIrreducibleLoops.jasm |
| * @summary Irreducible loops have many entries, only when the last entry loses |
| * control from the outside does the loop die, and have to disappear. |
| * @run main/othervm |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoopsMain::test* |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoops::test* |
| * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN |
| * -XX:PerMethodTrapLimit=0 |
| * TestDeadIrreducibleLoopsMain |
| */ |
| |
| /* |
| * @test |
| * @bug 8280126 |
| * @compile TestDeadIrreducibleLoops.jasm |
| * @summary Irreducible loops have many entries, only when the last entry loses |
| * control from the outside does the loop die, and have to disappear. |
| * @run main/othervm |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoopsMain::test* |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoops::test* |
| * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN |
| * -Xcomp -XX:-TieredCompilation |
| * TestDeadIrreducibleLoopsMain |
| */ |
| |
| /* |
| * @test |
| * @bug 8280126 |
| * @compile TestDeadIrreducibleLoops.jasm |
| * @summary Irreducible loops have many entries, only when the last entry loses |
| * control from the outside does the loop die, and have to disappear. |
| * @run main/othervm |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoopsMain::test* |
| * -XX:CompileCommand=compileonly,TestDeadIrreducibleLoops::test* |
| * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN |
| * -Xcomp -XX:-TieredCompilation |
| * -XX:PerMethodTrapLimit=0 |
| * TestDeadIrreducibleLoopsMain |
| */ |
| |
| // Note: if this test fails intermittently, then use -XX:RepeatCompilation=1000 |
| // The tests are run in no particular order. If an earlier test fails, a later one |
| // may fail too and be easier to debug. |
| |
| public class TestDeadIrreducibleLoopsMain { |
| static public void main(String[] args) { |
| TestDeadIrreducibleLoops t = new TestDeadIrreducibleLoops(); |
| test_000(false, false); |
| t.test_001(0, 0, 0, 0); |
| t.test_002(-1); |
| t.test_003(255); |
| t.test_004("I am an object\n"); |
| t.test_005(0, 0); |
| t.test_006(0); |
| t.test_007(0, 0, 0); |
| t.test_008(0, 0, 0); |
| t.test_009(0, 0, 0, 0, 0, 0, 0); |
| t.test_010(0, 0, 0, 0, 0); |
| t.test_011(0, 0, 0, 0, 0); |
| t.test_012a(0, 0, 0, 0, 0, 0, 0, 0); |
| t.test_012b(0, 0, 0, 0, 0); |
| t.test_013(0, 0, 0, 0, 0, 0, 0, 0, 0); |
| t.test_014a(0, 0, 0); |
| t.test_014b(0, 0, 0); |
| int x = t.test_015a(123); |
| int y = t.test_015b(123); |
| assert x == y: "pow(3,x)"; |
| t.test_016(0, 0, 0); |
| t.test_017(0, 0, 0); |
| t.test_018(0); |
| t.test_019(0, 0, 0, 0); |
| t.test_020(0, 0, 0, 0, 0); |
| t.test_021(0, 0, 0, 0, 0, 0); |
| t.test_022a(0, 0, 0, 0); |
| t.test_022b(0, 0); |
| t.test_023(0); |
| t.test_024(); |
| test_025a(false); |
| test_025b(false, false); |
| } |
| |
| public static float test_000(boolean flag1, boolean flag2) { |
| float ret = 1.0f; |
| int x = 0; |
| LOOP1: |
| for (int i = 1; i < 1000000; i *= 2) { // about 20 iterations |
| if (i % 5 != 0) { // SKIP1 |
| LOOP2: |
| for (int j = 1; j < 1000000; j *= 2) { // about 20 iterations |
| if (j % 5 != 0) { // SKIP2 |
| if (x == 0) { // eventually always false -> continue statements float out of loop |
| ret *= 1.0001; |
| if (j > 100) { |
| LOOP3: |
| for (float m = 1.0f; m < 30000.0f; m *= 1.0001f) { |
| // OSR starts here - should do more than 100k iterations |
| ret *= 0.99999f; |
| } |
| x = 1; |
| } |
| int y = 77; |
| for (int e = 0; e < 77; e++) { |
| y -= x; // empty_loop, once we know that x == 1 |
| } |
| if (y == 0) { |
| // always true after OSR -> cut off ENTRY1 and ENTRY2 |
| return ret; |
| } |
| ret += 0.01; |
| if (ret > 20000) { |
| ret = 7.0f; |
| continue LOOP1; // ENTRY1 |
| } |
| // back to LOOP2 -> ENTRY2 |
| } // end if (x == 0) |
| } // end SKIP2 |
| } // end LOOP2 |
| } // end SKIP1 |
| } // end LOOP1 |
| return ret; |
| } |
| |
| static float test_025a(boolean flag) { |
| // Based on test_000, but much simplified. |
| // Irreducible loop with OSR. Inlining in irreducible loop. |
| float ret = 3.0f; |
| LOOP1: |
| for (long i = 1; i < 1000_000_000_000L; i *= 2) { |
| ret = test_025_inline(ret); // inline region |
| LOOP2: |
| for (long j = 1; j < 1000_000_000_000L; j *= 2) { |
| for (int e = 0; e < 77; e++) {} |
| if (flag) { |
| continue LOOP1; // ENTRY1 |
| } |
| // back to LOOP2 -> ENTRY2 |
| } // end LOOP2 |
| } // end LOOP1 |
| return ret; |
| } |
| |
| static float test_025b(boolean flag1, boolean flag2) { |
| // Based on test_000. |
| // Irreducible loop with OSR. Inlining in irreducible loop. |
| float ret = 1.0f; |
| int x = 0; |
| LOOP1: |
| for (long i = 1; i < 1000_000_000_000L; i *= 2) { |
| ret = test_025_inline(ret); |
| if (i % 5 != 0) { // SKIP1 |
| LOOP2: |
| for (long j = 1; j < 1000_000_000_000L; j *= 2) { |
| if (j % 5 != 0) { // SKIP2 |
| if (x == 0) { // eventually always false -> continue statements float out of loop |
| ret *= 1.0001; |
| if (i > 1000_000_000L) { |
| LOOP3: |
| for (float m = 1.0f; m < 30000.0f; m *= 1.0001f) { |
| // OSR starts here - should do more than 100k iterations |
| ret *= 0.99999f; |
| } |
| x = 1; |
| } |
| int y = 77; |
| for (int e = 0; e < 77; e++) { |
| y -= x; // empty_loop, once we know that x == 1 |
| } |
| if (y == 0) { |
| // always true after OSR -> cut off ENTRY1 and ENTRY2 |
| return ret; |
| } |
| ret += 0.01; |
| if (ret > 20000) { |
| ret = 7.0f; |
| continue LOOP1; // ENTRY1 |
| } |
| // back to LOOP2 -> ENTRY2 |
| } // end if (x == 0) |
| } // end SKIP2 |
| } // end LOOP2 |
| } // end SKIP1 |
| } // end LOOP1 |
| return ret; |
| } |
| |
| static float test_025_inline(float x) { |
| if (x >= 1.0f) { |
| x *= 0.5f; |
| } else { |
| x *= 2.0f; |
| } |
| // Region to merge the if |
| return x; |
| } |
| } |