Skip to content

Commit 4abb10e

Browse files
Daniel Lundénrobcasloz
authored andcommitted
8317349: Randomize order of macro node expansion in C2
Reviewed-by: chagedorn, rcastanedalo, thartmann
1 parent 3bffe22 commit 4abb10e

File tree

14 files changed

+74
-32
lines changed

14 files changed

+74
-32
lines changed

src/hotspot/share/opto/c2_globals.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
product(bool, StressIncrementalInlining, false, DIAGNOSTIC, \
5757
"Randomize the incremental inlining decision") \
5858
\
59+
product(bool, StressMacroExpansion, false, DIAGNOSTIC, \
60+
"Randomize macro node expansion order") \
61+
\
5962
product(uint, StressSeed, 0, DIAGNOSTIC, \
6063
"Seed for randomized stress testing (if unset, a random one is " \
6164
"generated). The seed is recorded in the compilation log, if " \

src/hotspot/share/opto/compile.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,8 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
844844

845845
// If any phase is randomized for stress testing, seed random number
846846
// generation and log the seed for repeatability.
847-
if (StressLCM || StressGCM || StressIGVN || StressCCP || StressIncrementalInlining) {
847+
if (StressLCM || StressGCM || StressIGVN || StressCCP ||
848+
StressIncrementalInlining || StressMacroExpansion) {
848849
if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) {
849850
_stress_seed = static_cast<uint>(Ticks::now().nanoseconds());
850851
FLAG_SET_ERGO(StressSeed, _stress_seed);
@@ -2451,12 +2452,13 @@ void Compile::Optimize() {
24512452

24522453
{
24532454
TracePhase tp("macroExpand", &timers[_t_macroExpand]);
2455+
print_method(PHASE_BEFORE_MACRO_EXPANSION, 3);
24542456
PhaseMacroExpand mex(igvn);
24552457
if (mex.expand_macro_nodes()) {
24562458
assert(failing(), "must bail out w/ explicit message");
24572459
return;
24582460
}
2459-
print_method(PHASE_MACRO_EXPANSION, 2);
2461+
print_method(PHASE_AFTER_MACRO_EXPANSION, 2);
24602462
}
24612463

24622464
{
@@ -5121,6 +5123,16 @@ void CloneMap::dump(node_idx_t key, outputStream* st) const {
51215123
}
51225124
}
51235125

5126+
void Compile::shuffle_macro_nodes() {
5127+
if (_macro_nodes.length() < 2) {
5128+
return;
5129+
}
5130+
for (uint i = _macro_nodes.length() - 1; i >= 1; i--) {
5131+
uint j = C->random() % (i + 1);
5132+
swap(_macro_nodes.at(i), _macro_nodes.at(j));
5133+
}
5134+
}
5135+
51245136
// Move Allocate nodes to the start of the list
51255137
void Compile::sort_macro_nodes() {
51265138
int count = macro_count();

src/hotspot/share/opto/compile.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -794,6 +794,7 @@ class Compile : public Phase {
794794
void remove_useless_unstable_if_traps(Unique_Node_List &useful);
795795
void process_for_unstable_if_traps(PhaseIterGVN& igvn);
796796

797+
void shuffle_macro_nodes();
797798
void sort_macro_nodes();
798799

799800
void mark_parse_predicate_nodes_useless(PhaseIterGVN& igvn);

src/hotspot/share/opto/macro.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,6 +2430,9 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
24302430
//------------------------------expand_macro_nodes----------------------
24312431
// Returns true if a failure occurred.
24322432
bool PhaseMacroExpand::expand_macro_nodes() {
2433+
if (StressMacroExpansion) {
2434+
C->shuffle_macro_nodes();
2435+
}
24332436
// Last attempt to eliminate macro nodes.
24342437
eliminate_macro_nodes();
24352438
if (C->failing()) return true;
@@ -2511,6 +2514,9 @@ bool PhaseMacroExpand::expand_macro_nodes() {
25112514
}
25122515
assert(!success || (C->macro_count() == (old_macro_count - 1)), "elimination must have deleted one node from macro list");
25132516
progress = progress || success;
2517+
if (success) {
2518+
C->print_method(PHASE_AFTER_MACRO_EXPANSION_STEP, 5, n);
2519+
}
25142520
}
25152521
}
25162522

@@ -2571,6 +2577,7 @@ bool PhaseMacroExpand::expand_macro_nodes() {
25712577
}
25722578
assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list");
25732579
if (C->failing()) return true;
2580+
C->print_method(PHASE_AFTER_MACRO_EXPANSION_STEP, 5, n);
25742581

25752582
// Clean up the graph so we're less likely to hit the maximum node
25762583
// limit
@@ -2613,6 +2620,7 @@ bool PhaseMacroExpand::expand_macro_nodes() {
26132620
}
26142621
assert(C->macro_count() < macro_count, "must have deleted a node from macro list");
26152622
if (C->failing()) return true;
2623+
C->print_method(PHASE_AFTER_MACRO_EXPANSION_STEP, 5, n);
26162624

26172625
// Clean up the graph so we're less likely to hit the maximum node
26182626
// limit

src/hotspot/share/opto/phasetype.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@
8484
flags(CCP1, "PhaseCCP 1") \
8585
flags(ITER_GVN2, "Iter GVN 2") \
8686
flags(PHASEIDEALLOOP_ITERATIONS, "PhaseIdealLoop iterations") \
87-
flags(MACRO_EXPANSION, "Macro expand") \
87+
flags(BEFORE_MACRO_EXPANSION , "Before Macro Expansion") \
88+
flags(AFTER_MACRO_EXPANSION_STEP, "After Macro Expansion Step") \
89+
flags(AFTER_MACRO_EXPANSION, "After Macro Expansion") \
8890
flags(BARRIER_EXPANSION, "Barrier expand") \
8991
flags(OPTIMIZE_FINISHED, "Optimize finished") \
9092
flags(BEFORE_MATCHING, "Before matching") \

src/utils/IdealGraphVisualizer/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Ideal graphs are dumped at the following points:
3131
* `N=2`: additionally, after every major phase
3232
* `N=3`: additionally, after every minor phase
3333
* `N=4`: additionally, after every loop optimization
34-
* `N=5`: additionally, after every effective IGVN step (slow)
34+
* `N=5`: additionally, after every effective IGVN and every macro expansion step (slow)
3535
* `N=6`: additionally, after parsing every bytecode (very slow)
3636

3737
By default the JVM expects that it will connect to a visualizer on the local

test/hotspot/jtreg/compiler/arguments/TestStressOptions.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
2424
/*
2525
* @test
2626
* @key stress randomness
27-
* @bug 8252219 8256535
27+
* @bug 8252219 8256535 8317349
2828
* @requires vm.compiler2.enabled
2929
* @summary Tests that different combinations of stress options and
3030
* -XX:StressSeed=N are accepted.
@@ -44,6 +44,10 @@
4444
* compiler.arguments.TestStressOptions
4545
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:StressSeed=42
4646
* compiler.arguments.TestStressOptions
47+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressMacroExpansion
48+
* compiler.arguments.TestStressOptions
49+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressMacroExpansion -XX:StressSeed=42
50+
* compiler.arguments.TestStressOptions
4751
*/
4852

4953
package compiler.arguments;

test/hotspot/jtreg/compiler/c2/irTests/ProfileAtTypeCheck.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static void dummyI(I i) {
7070

7171
@Test
7272
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
73-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "2", IRNode.LOAD_KLASS_OR_NKLASS, "2" })
73+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "2", IRNode.LOAD_KLASS_OR_NKLASS, "2" })
7474
public static void test1(Object o) {
7575
dummyA((A)o);
7676
}
@@ -103,7 +103,7 @@ private void test2Runner() {
103103

104104
@Test
105105
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
106-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "2", IRNode.LOAD_KLASS_OR_NKLASS, "1" })
106+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "2", IRNode.LOAD_KLASS_OR_NKLASS, "1" })
107107
public static void test3(Object o) {
108108
if (o instanceof B) {
109109
dummyB((B)o);
@@ -121,7 +121,7 @@ private void test3Runner() {
121121
// full subtype check
122122
@Test
123123
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
124-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "3", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
124+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "3", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
125125
public static void test4(Object o) {
126126
dummyI((I)o);
127127
}
@@ -138,7 +138,7 @@ private void test4Runner() {
138138
// full subtype check + profile use for success path
139139
@Test
140140
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
141-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
141+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
142142
public static void test5(Object o) {
143143
dummyI((I)o);
144144
}
@@ -153,7 +153,7 @@ private void test5Runner() {
153153
// Check primary super
154154
@Test
155155
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
156-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "2", IRNode.LOAD_KLASS_OR_NKLASS, "2" }, failOn = { IRNode.PARTIAL_SUBTYPE_CHECK })
156+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "2", IRNode.LOAD_KLASS_OR_NKLASS, "2" }, failOn = { IRNode.PARTIAL_SUBTYPE_CHECK })
157157
public static void test6(Object o) {
158158
dummyA((A)o);
159159
}
@@ -169,7 +169,7 @@ private void test6Runner() {
169169
// full subtype check + profile use for both success and failure paths
170170
@Test
171171
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
172-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
172+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
173173
public static boolean test7(Object o) {
174174
return o instanceof I;
175175
}
@@ -184,7 +184,7 @@ private void test7Runner() {
184184
// full subtype check + profile use for success path (profile has unrecorded entries)
185185
@Test
186186
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
187-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
187+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
188188
public static void test8(Object o) {
189189
dummyI((I)o);
190190
}
@@ -394,7 +394,7 @@ private void test14Runner() {
394394
// full subtype check + profile use for success path
395395
@Test
396396
@IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.SUBTYPE_CHECK, "1" })
397-
@IR(phase = { CompilePhase.MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
397+
@IR(phase = { CompilePhase.AFTER_MACRO_EXPANSION }, counts = { IRNode.CMP_P, "5", IRNode.LOAD_KLASS_OR_NKLASS, "2", IRNode.PARTIAL_SUBTYPE_CHECK, "1" })
398398
public static void test15(Object o) {
399399
array[0] = o;
400400
}

test/hotspot/jtreg/compiler/debug/TestGenerateStressSeed.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
3939
* @run driver compiler.debug.TestGenerateStressSeed StressGCM
4040
* @run driver compiler.debug.TestGenerateStressSeed StressIGVN
4141
* @run driver compiler.debug.TestGenerateStressSeed StressCCP
42+
* @run driver compiler.debug.TestGenerateStressSeed StressMacroExpansion
4243
*/
4344

4445
public class TestGenerateStressSeed {

test/hotspot/jtreg/compiler/debug/TestStressIGVNAndCCP.java renamed to test/hotspot/jtreg/compiler/debug/TestStress.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,22 +30,22 @@
3030
/*
3131
* @test
3232
* @key stress randomness
33-
* @bug 8252219 8256535
33+
* @bug 8252219 8256535 8317349
3434
* @requires vm.debug == true & vm.compiler2.enabled
3535
* @summary Tests that stress compilations with the same seed yield the same
36-
* IGVN and CCP traces.
36+
* IGVN, CCP, and macro expansion traces.
3737
* @library /test/lib /
38-
* @run driver compiler.debug.TestStressIGVNAndCCP
38+
* @run driver compiler.debug.TestStress
3939
*/
4040

41-
public class TestStressIGVNAndCCP {
41+
public class TestStress {
4242

4343
static String phaseTrace(String stressOption, String traceOption,
4444
int stressSeed) throws Exception {
45-
String className = TestStressIGVNAndCCP.class.getName();
45+
String className = TestStress.class.getName();
4646
String[] procArgs = {
4747
"-Xcomp", "-XX:-TieredCompilation", "-XX:-Inline", "-XX:+CICountNative",
48-
"-XX:CompileOnly=" + className + "::sum", "-XX:+" + traceOption,
48+
"-XX:CompileOnly=" + className + "::sum", "-XX:" + traceOption,
4949
"-XX:+" + stressOption, "-XX:StressSeed=" + stressSeed,
5050
className, "10"};
5151
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(procArgs);
@@ -55,11 +55,17 @@ static String phaseTrace(String stressOption, String traceOption,
5555
}
5656

5757
static String igvnTrace(int stressSeed) throws Exception {
58-
return phaseTrace("StressIGVN", "TraceIterativeGVN", stressSeed);
58+
return phaseTrace("StressIGVN", "+TraceIterativeGVN", stressSeed);
5959
}
6060

6161
static String ccpTrace(int stressSeed) throws Exception {
62-
return phaseTrace("StressCCP", "TracePhaseCCP", stressSeed);
62+
return phaseTrace("StressCCP", "+TracePhaseCCP", stressSeed);
63+
}
64+
65+
static String macroExpansionTrace(int stressSeed) throws Exception {
66+
return phaseTrace("StressMacroExpansion",
67+
"CompileCommand=PrintIdealPhase,*::*,AFTER_MACRO_EXPANSION_STEP",
68+
stressSeed);
6369
}
6470

6571
static void sum(int n) {
@@ -75,6 +81,8 @@ public static void main(String[] args) throws Exception {
7581
"got different IGVN traces for the same seed");
7682
Asserts.assertEQ(ccpTrace(s), ccpTrace(s),
7783
"got different CCP traces for the same seed");
84+
Asserts.assertEQ(macroExpansionTrace(s), macroExpansionTrace(s),
85+
"got different macro expansion traces for the same seed");
7886
}
7987
} else if (args.length > 0) {
8088
sum(Integer.parseInt(args[0]));

0 commit comments

Comments
 (0)