Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8252219: C2: Randomize IGVN worklist for stress testing #242

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/hotspot/share/opto/c2_globals.hpp
Expand Up @@ -49,6 +49,14 @@
product(bool, StressGCM, false, DIAGNOSTIC, \
"Randomize instruction scheduling in GCM") \
\
product(bool, StressIGVN, false, DIAGNOSTIC, \
"Randomize worklist traversal in IGVN") \
\
product(uint, StressSeed, 0, DIAGNOSTIC, \
"Seed for IGVN stress testing (if unset, a random one is " \
"generated") \
range(0, max_juint) \
\
develop(bool, StressMethodHandleLinkerInlining, false, \
"Stress inlining through method handle linkers") \
\
Expand Down
24 changes: 22 additions & 2 deletions src/hotspot/share/opto/compile.cpp
Expand Up @@ -70,6 +70,7 @@
#include "opto/type.hpp"
#include "opto/vectornode.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
Expand Down Expand Up @@ -523,6 +524,7 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
#endif
_has_method_handle_invokes(false),
_clinit_barrier_on_entry(false),
_stress_seed(0),
_comp_arena(mtCompiler),
_barrier_set_state(BarrierSet::barrier_set()->barrier_set_c2()->create_barrier_state(comp_arena())),
_env(ci_env),
Expand Down Expand Up @@ -727,6 +729,18 @@ 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) {
_stress_seed = FLAG_IS_DEFAULT(StressSeed) ?
static_cast<uint>(Ticks::now().nanoseconds()) : StressSeed;
if (_log != NULL) {
_log->elem("stress_test seed='%u'", _stress_seed);
} else if (FLAG_IS_DEFAULT(StressSeed)) {
tty->print_cr("Warning: set +LogCompilation to log the seed.");
}
}

// Now optimize
Optimize();
if (failing()) return;
Expand Down Expand Up @@ -809,6 +823,7 @@ Compile::Compile( ciEnv* ci_env,
#endif
_has_method_handle_invokes(false),
_clinit_barrier_on_entry(false),
_stress_seed(0),
_comp_arena(mtCompiler),
_barrier_set_state(BarrierSet::barrier_set()->barrier_set_c2()->create_barrier_state(comp_arena())),
_env(ci_env),
Expand Down Expand Up @@ -4436,8 +4451,13 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) {
}
}

// Auxiliary method to support randomized stressing/fuzzing.
//
// Auxiliary methods to support randomized stressing/fuzzing.

int Compile::random() {
_stress_seed = os::next_random(_stress_seed);
robcasloz marked this conversation as resolved.
Show resolved Hide resolved
return static_cast<int>(_stress_seed);
}

// This method can be called the arbitrary number of times, with current count
// as the argument. The logic allows selecting a single candidate from the
// running list of candidates as follows:
Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/share/opto/compile.hpp
Expand Up @@ -300,6 +300,7 @@ class Compile : public Phase {
RTMState _rtm_state; // State of Restricted Transactional Memory usage
int _loop_opts_cnt; // loop opts round
bool _clinit_barrier_on_entry; // True if clinit barrier is needed on nmethod entry
uint _stress_seed; // Seed for stress testing

// Compilation environment.
Arena _comp_arena; // Arena with lifetime equivalent to Compile
Expand Down Expand Up @@ -1136,7 +1137,8 @@ class Compile : public Phase {
// Convert integer value to a narrowed long type dependent on ctrl (for example, a range check)
static Node* constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl);

// Auxiliary method for randomized fuzzing/stressing
// Auxiliary methods for randomized fuzzing/stressing
int random();
static bool randomized_select(int count);

// supporting clone_map
Expand Down
11 changes: 11 additions & 0 deletions src/hotspot/share/opto/phaseX.cpp
Expand Up @@ -975,6 +975,14 @@ PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
}
}

void PhaseIterGVN::shuffle_worklist() {
if (_worklist.size() < 2) return;
for (uint i = _worklist.size() - 1; i >= 1; i--) {
uint j = C->random() % (i + 1);
swap(_worklist.adr()[i], _worklist.adr()[j]);
}
}

#ifndef PRODUCT
void PhaseIterGVN::verify_step(Node* n) {
if (VerifyIterativeGVN) {
Expand Down Expand Up @@ -1127,6 +1135,9 @@ void PhaseIterGVN::trace_PhaseIterGVN_verbose(Node* n, int num_processed) {
void PhaseIterGVN::optimize() {
DEBUG_ONLY(uint num_processed = 0;)
NOT_PRODUCT(init_verifyPhaseIterGVN();)
if (StressIGVN) {
shuffle_worklist();
}

uint loop_count = 0;
// Pull from worklist and transform the node. If the node has changed,
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/opto/phaseX.hpp
Expand Up @@ -458,6 +458,9 @@ class PhaseIterGVN : public PhaseGVN {

protected:

// Shuffle worklist, for stress testing
void shuffle_worklist();

virtual const Type* saturate(const Type* new_type, const Type* old_type,
const Type* limit_type) const;
// Usually returns new_type. Returns old_type if new_type is only a slight
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/runtime/os.cpp
Expand Up @@ -815,7 +815,7 @@ void os::init_random(unsigned int initval) {
}


static int random_helper(unsigned int rand_seed) {
int os::next_random(unsigned int rand_seed) {
/* standard, well-known linear congruential random generator with
* next_rand = (16807*seed) mod (2**31-1)
* see
Expand Down Expand Up @@ -853,7 +853,7 @@ int os::random() {
// Make updating the random seed thread safe.
while (true) {
unsigned int seed = _rand_seed;
unsigned int rand = random_helper(seed);
unsigned int rand = next_random(seed);
if (Atomic::cmpxchg(&_rand_seed, seed, rand) == seed) {
return static_cast<int>(rand);
}
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/os.hpp
Expand Up @@ -756,6 +756,7 @@ class os: AllStatic {

// random number generation
static int random(); // return 32bit pseudorandom number
static int next_random(unsigned int rand_seed); // pure version of random()
static void init_random(unsigned int initval); // initialize random sequence

// Structured OS Exception support
Expand Down
44 changes: 44 additions & 0 deletions test/hotspot/jtreg/compiler/arguments/TestStressIGVNOptions.java
@@ -0,0 +1,44 @@
/*
* 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.
*/

/*
* @test
* @bug 8252219
* @requires vm.compiler2.enabled
* @summary Tests that different combinations of the options -XX:+StressIGVN and
* -XX:StressSeed=N are accepted.
* @run main/othervm -XX:+StressIGVN
* compiler.arguments.TestStressIGVNOptions
* @run main/othervm -XX:+StressIGVN -XX:StressSeed=42
* compiler.arguments.TestStressIGVNOptions
robcasloz marked this conversation as resolved.
Show resolved Hide resolved
*/

package compiler.arguments;

public class TestStressIGVNOptions {

static public void main(String[] args) {
System.out.println("Passed");
}
}

64 changes: 64 additions & 0 deletions test/hotspot/jtreg/compiler/debug/TestGenerateStressSeed.java
@@ -0,0 +1,64 @@
/*
* 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 java.nio.file.Paths;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.Asserts;

/*
* @test
* @bug 8252219
* @requires vm.compiler2.enabled
* @summary Tests that using -XX:+StressIGVN without -XX:StressSeed=N generates
* and logs a random seed.
* @library /test/lib /
* @run driver compiler.debug.TestGenerateStressSeed
*/

public class TestGenerateStressSeed {

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.length == 0) {
String className = TestGenerateStressSeed.class.getName();
String log = "test.log";
String[] procArgs = {
"-Xcomp", "-XX:-TieredCompilation",
"-XX:CompileOnly=" + className + "::sum", "-XX:+StressIGVN",
"-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) {
sum(Integer.parseInt(args[0]));
}
}
}
71 changes: 71 additions & 0 deletions test/hotspot/jtreg/compiler/debug/TestStressIGVN.java
@@ -0,0 +1,71 @@
/*
* 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 8252219
* @requires 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.
* @library /test/lib /
* @run driver compiler.debug.TestStressIGVN
*/

public class TestStressIGVN {

static String igvnTrace(int stressSeed) throws Exception {
String className = TestStressIGVN.class.getName();
String[] procArgs = {
"-Xcomp", "-XX:-TieredCompilation",
"-XX:CompileOnly=" + className + "::sum", "-XX:+TraceIterativeGVN",
"-XX:+StressIGVN", "-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.length == 0) {
Asserts.assertEQ(igvnTrace(10), igvnTrace(10),
"got different IGVN traces for the same seed");
Asserts.assertNE(igvnTrace(10), igvnTrace(20),
"got the same IGVN trace for different seeds");
} else if (args.length > 0) {
sum(Integer.parseInt(args[0]));
}
}
}