8253765: C2: Control randomization in StressLCM and StressGCM

Use the compilation-local seed in 'StressLCM' and 'StressGCM' rather than the
global one. As a consequence, these options use by default a fresh seed in every
compilation, unless 'StressSeed=N' is specified, in which case they behave
deterministically. Annotate tests that use 'StressLCM' and 'StressGCM' with the
'stress' and 'randomness' keys to reflect this change in default behavior.

Reviewed-by: kvn, thartmann
This commit is contained in:
Roberto Castañeda Lozano 2020-10-12 11:40:50 +00:00 committed by Tobias Hartmann
parent 6620b617a7
commit 05459df0c7
18 changed files with 105 additions and 15 deletions

@ -53,8 +53,8 @@
"Randomize worklist traversal in IGVN") \
\
product(uint, StressSeed, 0, DIAGNOSTIC, \
"Seed for IGVN stress testing (if unset, a random one is " \
"generated") \
"Seed for randomized stress testing (if unset, a random one is " \
"generated)") \
range(0, max_juint) \
\
develop(bool, StressMethodHandleLinkerInlining, false, \

@ -729,9 +729,9 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
if (failing()) return;
NOT_PRODUCT( verify_graph_edges(); )
// If IGVN is randomized for stress testing, seed random number
// generation and log the seed for repeatability.
if (StressIGVN) {
// If LCM, GCM, or IGVN are randomized for stress testing, seed
// random number generation and log the seed for repeatability.
if (StressLCM || StressGCM || StressIGVN) {
_stress_seed = FLAG_IS_DEFAULT(StressSeed) ?
static_cast<uint>(Ticks::now().nanoseconds()) : StressSeed;
if (_log != NULL) {
@ -4489,7 +4489,7 @@ int Compile::random() {
#define RANDOMIZED_DOMAIN_MASK ((1 << (RANDOMIZED_DOMAIN_POW + 1)) - 1)
bool Compile::randomized_select(int count) {
assert(count > 0, "only positive");
return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
return (random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
}
CloneMap& Compile::clone_map() { return _clone_map; }

@ -1140,7 +1140,7 @@ class Compile : public Phase {
// Auxiliary methods for randomized fuzzing/stressing
int random();
static bool randomized_select(int count);
bool randomized_select(int count);
// supporting clone_map
CloneMap& clone_map();

@ -1198,7 +1198,7 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) {
#endif
cand_cnt++;
if (LCA_freq < least_freq || // Better Frequency
(StressGCM && Compile::randomized_select(cand_cnt)) || // Should be randomly accepted in stress mode
(StressGCM && C->randomized_select(cand_cnt)) || // Should be randomly accepted in stress mode
(!StressGCM && // Otherwise, choose with latency
!in_latency && // No block containing latency
LCA_freq < least_freq * delta && // No worse frequency

@ -632,7 +632,7 @@ Node* PhaseCFG::select(
cand_cnt++;
if (choice < n_choice ||
(choice == n_choice &&
((StressLCM && Compile::randomized_select(cand_cnt)) ||
((StressLCM && C->randomized_select(cand_cnt)) ||
(!StressLCM &&
(latency < n_latency ||
(latency == n_latency &&

@ -23,6 +23,7 @@
/*
* @test
* @key stress randomness
* @bug 8235332 8248226
* @summary Test cloning with more than 8 (=ArrayCopyLoadStoreMaxElem) fields with StressGCM
* @library /

@ -23,6 +23,7 @@
/**
* @test
* @key stress randomness
* @bug 8182036
* @summary Load from initializing arraycopy uses wrong memory state
*

@ -23,6 +23,7 @@
/**
* @test
* @key stress randomness
* @bug 8181742
* @summary Loads that bypass arraycopy ends up with wrong memory state
*

@ -23,6 +23,7 @@
/**
* @test
* @key stress randomness
* @bug 8139771
* @summary Eliminating CastPP nodes at Phis when they all come from a unique input may cause crash
* @requires vm.gc=="Serial" | vm.gc=="Parallel"

@ -32,10 +32,12 @@ import jdk.test.lib.Asserts;
* @test
* @bug 8252219
* @requires vm.compiler2.enabled
* @summary Tests that using -XX:+StressIGVN without -XX:StressSeed=N generates
* @summary Tests that using a stress option without -XX:StressSeed=N generates
* and logs a random seed.
* @library /test/lib /
* @run driver compiler.debug.TestGenerateStressSeed
* @run driver compiler.debug.TestGenerateStressSeed StressLCM
* @run driver compiler.debug.TestGenerateStressSeed StressGCM
* @run driver compiler.debug.TestGenerateStressSeed StressIGVN
*/
public class TestGenerateStressSeed {
@ -47,17 +49,18 @@ public class TestGenerateStressSeed {
}
public static void main(String[] args) throws Exception {
if (args.length == 0) {
if (args[0].startsWith("Stress")) {
String className = TestGenerateStressSeed.class.getName();
String stressOpt = args[0];
String log = "test.log";
String[] procArgs = {
"-Xcomp", "-XX:-TieredCompilation", "-XX:+UnlockDiagnosticVMOptions",
"-XX:CompileOnly=" + className + "::sum", "-XX:+StressIGVN",
"-XX:CompileOnly=" + className + "::sum", "-XX:+" + stressOpt,
"-XX:+LogCompilation", "-XX:LogFile=" + log, className, "10"};
ProcessTools.createJavaProcessBuilder(procArgs).start().waitFor();
new OutputAnalyzer(Paths.get(log))
.shouldContain("stress_test seed");
} else if (args.length > 0) {
} else {
sum(Integer.parseInt(args[0]));
}
}

@ -0,0 +1,76 @@
/*
* Copyright (c) 2020, 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.
*/
package compiler.debug;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.Asserts;
/*
* @test
* @bug 8253765
* @requires vm.debug == true & vm.compiler2.enabled
* @summary Tests that, when compiling with StressLCM or StressGCM, using the
* same seed results in the same compilation, and using different seeds
* results in different compilations (the latter does not necessarily
* hold for all pairs of seeds). The output of PrintOptoStatistics is
* used to compare among compilations, instead of the more intuitive
* TraceOptoPipelining which prints non-deterministic memory addresses.
* @library /test/lib /
* @run driver compiler.debug.TestStressCM StressLCM
* @run driver compiler.debug.TestStressCM StressGCM
*/
public class TestStressCM {
static String optoStats(String stressOpt, int stressSeed) throws Exception {
String className = TestStressCM.class.getName();
String[] procArgs = {
"-Xcomp", "-XX:-TieredCompilation",
"-XX:CompileOnly=" + className + "::sum",
"-XX:+PrintOptoStatistics", "-XX:+" + stressOpt,
"-XX:StressSeed=" + stressSeed, className, "10"};
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs);
OutputAnalyzer out = new OutputAnalyzer(pb.start());
return out.getStdout();
}
static void sum(int n) {
int acc = 0;
for (int i = 0; i < n; i++) acc += i;
System.out.println(acc);
}
public static void main(String[] args) throws Exception {
if (args[0].startsWith("Stress")) {
String stressOpt = args[0];
Asserts.assertEQ(optoStats(stressOpt, 10), optoStats(stressOpt, 10),
"got different optimization stats for the same seed");
Asserts.assertNE(optoStats(stressOpt, 10), optoStats(stressOpt, 20),
"got the same optimization stats for different seeds");
} else if (args.length > 0) {
sum(Integer.parseInt(args[0]));
}
}
}

@ -33,7 +33,8 @@ import jdk.test.lib.Asserts;
* @requires vm.debug == true & vm.compiler2.enabled
* @summary Tests that compilations with the same seed yield the same IGVN
* trace, and compilations with different seeds yield different IGVN
* traces.
* traces (the latter does not necessarily hold for all pairs of
* seeds).
* @library /test/lib /
* @run driver compiler.debug.TestStressIGVN
*/

@ -23,6 +23,7 @@
/*
* @test
* @key stress randomness
* @bug 8241900
* @summary Loop unswitching may cause dependence on null check to be lost
*

@ -23,6 +23,7 @@
/**
* @test
* @key stress randomness
* @bug 8069191
* @summary predicate moved out of loops and CastPP removal causes dependency to be lost
*

@ -23,6 +23,7 @@
/*
* @test
* @key stress randomness
* @requires vm.gc.Z
* @bug 8237859
* @summary A LoadP node has a wrong control input (too early) which results in an out-of-bounds read of an object array with ZGC.

@ -23,6 +23,7 @@
/**
* @test
* @key stress randomness
* @bug 8007898
* @summary Incorrect optimization of Memory Barriers in Matcher::post_store_load_barrier().
* @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions

@ -23,6 +23,7 @@
/**
* @test TestExpandedWBLostNullCheckDep
* @key stress randomness
* @summary Logic that moves a null check in the expanded barrier may cause a memory access that doesn't depend on the barrier to bypass the null check
* @requires vm.gc.Shenandoah
* @requires vm.flavor == "server"

@ -23,6 +23,7 @@
/**
* @test TestWriteBarrierClearControl
* @key stress randomness
* @summary Clearing control during final graph reshape causes memory barrier to loose dependency on null check
* @requires vm.gc.Shenandoah
* @requires vm.flavor == "server"