jdk/test/hotspot/jtreg/compiler/loopopts/TestStressLongCountedLoopLimitChecks.java
Kangcheng Xu e0fa3d2f81 8353290: C2: Refactor PhaseIdealLoop::is_counted_loop()
Reviewed-by: chagedorn, roland
2026-03-16 14:11:27 +00:00

118 lines
4.2 KiB
Java

/*
* Copyright (c) 2026 IBM 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.
*/
package compiler.loopopts;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Stream;
/**
* @test
* @bug 8353290
* @summary test loop limit checks are inserted when stressing int counted loops to long counted loops
* @library /test/lib
* @requires vm.debug == true
* @run driver compiler.loopopts.TestStressLongCountedLoopLimitChecks
*/
public class TestStressLongCountedLoopLimitChecks {
public static void main(String[] args) throws Exception {
test(BasicLauncher.class, 1, "-XX:StressLongCountedLoop=0");
test(BasicLauncher.class, 1, "-XX:StressLongCountedLoop=2000000");
test(LargeStrideLauncher.class, 2, "-XX:StressLongCountedLoop=0");
test(LargeStrideLauncher.class, 2, "-XX:StressLongCountedLoop=2000000");
}
private static void test(Class launcher, int limitChecks, String... flags) throws IOException {
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
Stream.concat(Arrays.stream(flags), Stream.of(
"-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+TraceLoopLimitCheck",
"-XX:CompileOnly=" + launcher.getName() + "::test*",
"-Xcomp",
launcher.getName()
)).toList()
);
OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
analyzer.shouldHaveExitValue(0);
analyzer.outputTo(System.out);
analyzer.errorTo(System.err);
Asserts.assertEQ(
limitChecks,
(int) analyzer.asLines().stream().filter(
l -> l.trim().matches("Counted Loop Limit Check generated:")
).count(),
"wrong numbers of loop limit checks"
);
}
public static class BasicLauncher {
static int x, y, z;
public static void main(String[] args) throws Exception {
test();
}
static void test() {
int i = x; // Any int
do {
x += y;
i++; // Could overflow and thus we need a Loop Limit Check Predicate "i < z"
} while (i < z);
}
}
public static class LargeStrideLauncher {
static final int STRIDE = 100_000;
public static void main(String[] args) throws Exception {
Asserts.assertEQ(10_000_000L / STRIDE, test(0, 10_000_000), "loop not stopped");
Asserts.assertEQ(-1L, test(0, Integer.MAX_VALUE), "loop stopped prematurely");
}
static long ONE = 1; // Just so the compiler doesn't try to IV replace the whole thing
public static long test(int init, int limit) {
final int stride = 100_000;
long iterations = 0;
for (int i = init; i < limit; i += 100000) {
iterations += ONE;
if (iterations > (limit / stride) + 1) { // No it's not stopping, as we should expect.
return -1;
}
}
return iterations; // Possibly stopping prematurely.
}
}
}