Skip to content

Commit b4039c6

Browse files
committed
[GR-65900] Add ReportHotCodePhase to report hot parts in the IR.
PullRequest: graal/21272
2 parents 7dd4293 + f570c5e commit b4039c6

File tree

11 files changed

+616
-5
lines changed

11 files changed

+616
-5
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.core.test;
26+
27+
import java.io.ByteArrayOutputStream;
28+
29+
import org.junit.Test;
30+
31+
import jdk.graal.compiler.api.directives.GraalDirectives;
32+
import jdk.graal.compiler.debug.LogStream;
33+
import jdk.graal.compiler.debug.TTY;
34+
import jdk.graal.compiler.options.OptionValues;
35+
import jdk.graal.compiler.phases.BasePhase;
36+
37+
public class ReportHotMetricsTest extends GraalCompilerTest {
38+
39+
public static final boolean PRINT_STDOUT = false;
40+
41+
static int sideEffect;
42+
43+
public static int snippet01(int limit1) {
44+
int result = 0;
45+
for (int i = 0; GraalDirectives.injectIterationCount(100000, i < limit1); i++) {
46+
// this if is missing a profile and should be reported
47+
if (i > sideEffect) {
48+
// this kill should be reported
49+
GraalDirectives.sideEffect(123);
50+
} else {
51+
result += i;
52+
}
53+
}
54+
return result;
55+
}
56+
57+
@SuppressWarnings("try")
58+
@Test
59+
public void testAbsNegate() {
60+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
61+
try (TTY.Filter ttyFilter = new TTY.Filter(new LogStream(bos))) {
62+
OptionValues opt = new OptionValues(getInitialOptions(), BasePhase.PhaseOptions.ReportHotMetrics, "*.snippet01", BasePhase.PhaseOptions.ReportHotMetricsAfterPhases,
63+
"BoxNodeIdentity=*.snippet01");
64+
test(opt, "snippet01", 100);
65+
}
66+
// the missing profile
67+
assertTrue(bos.toString().contains("[Hot Code Warning] Unknown profile for"));
68+
// the killing of any
69+
assertTrue(bos.toString().contains(" kills any and has relative"));
70+
71+
if (PRINT_STDOUT) {
72+
TTY.println("%s%n", bos.toString());
73+
}
74+
}
75+
}

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyDebugUsage.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.List;
3030
import java.util.Set;
3131

32+
import org.graalvm.collections.EconomicSet;
33+
3234
import jdk.graal.compiler.core.GraalCompiler;
3335
import jdk.graal.compiler.core.common.type.ObjectStamp;
3436
import jdk.graal.compiler.debug.DebugContext;
@@ -44,6 +46,7 @@
4446
import jdk.graal.compiler.nodes.spi.CoreProviders;
4547
import jdk.graal.compiler.phases.BasePhase;
4648
import jdk.graal.compiler.phases.VerifyPhase;
49+
import jdk.graal.compiler.phases.common.ReportHotCodePhase;
4750
import jdk.graal.compiler.replacements.ReplacementsImpl;
4851
import jdk.graal.compiler.replacements.SnippetTemplate;
4952
import jdk.graal.compiler.test.GraalTest.MethodSource;
@@ -167,9 +170,11 @@ protected void verifyParameters(MetaAccessProvider metaAccess1, MethodCallTarget
167170
* The optimization log dumps at a parametrized level, but it must be at least
168171
* OptimizationLog.MINIMUM_LOG_LEVEL.
169172
*/
170-
String optimizationEntryClassName = OptimizationLogImpl.OptimizationEntryImpl.class.getName();
173+
EconomicSet<String> allowedClasses = EconomicSet.create();
174+
allowedClasses.add(OptimizationLogImpl.OptimizationEntryImpl.class.getName());
175+
allowedClasses.add(ReportHotCodePhase.class.getName());
171176
String callerClassName = debugCallTarget.graph().method().format("%H");
172-
if (!optimizationEntryClassName.equals(callerClassName)) {
177+
if (!allowedClasses.contains(callerClassName)) {
173178
int dumpLevel = verifyDumpLevelParameter(debugCallTarget, verifiedCallee, args.get(1));
174179
verifyDumpObjectParameter(debugCallTarget, args.get(2), verifiedCallee, dumpLevel);
175180
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/CompilationIdentifier.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package jdk.graal.compiler.core.common;
2626

2727
import jdk.vm.ci.code.CompilationRequest;
28+
import jdk.vm.ci.meta.JavaMethod;
2829

2930
/**
3031
* A unique identifier for a compilation. Compiled code can be mapped to a single compilation id.
@@ -77,4 +78,12 @@ public CompilationRequest getRequest() {
7778
* {@link Verbosity}.
7879
*/
7980
String toString(Verbosity verbosity);
81+
82+
/**
83+
* Get a JavaMethod representation of the current compilation.
84+
*/
85+
default JavaMethod asJavaMethod() {
86+
return null;
87+
}
88+
8089
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeSourcePosition.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import jdk.graal.compiler.bytecode.BytecodeDisassembler;
3535
import jdk.graal.compiler.bytecode.Bytecodes;
3636
import jdk.graal.compiler.debug.Assertions;
37-
3837
import jdk.graal.compiler.serviceprovider.GraalServices;
3938
import jdk.vm.ci.code.BytecodeFrame;
4039
import jdk.vm.ci.code.BytecodePosition;
@@ -219,9 +218,14 @@ public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosi
219218

220219
@Override
221220
public String toString() {
221+
return toString("");
222+
}
223+
224+
public String toString(String indent) {
222225
StringBuilder sb = new StringBuilder(100);
223226
NodeSourcePosition pos = this;
224227
while (pos != null) {
228+
sb.append(indent);
225229
format(sb, pos);
226230
if (pos.sourceLanguagePosition != null) {
227231
sb.append(" source=" + pos.sourceLanguagePosition.toShortString());

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotCompilationIdentifier.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
import jdk.graal.compiler.core.common.CompilationIdentifier;
2828
import jdk.graal.compiler.core.common.CompilationRequestIdentifier;
2929
import jdk.graal.compiler.debug.GraalError;
30-
3130
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
31+
import jdk.vm.ci.meta.JavaMethod;
3232
import jdk.vm.ci.runtime.JVMCICompiler;
3333

3434
/**
@@ -98,4 +98,8 @@ public HotSpotCompilationRequest getRequest() {
9898
return request;
9999
}
100100

101+
@Override
102+
public JavaMethod asJavaMethod() {
103+
return getRequest().getMethod();
104+
}
101105
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/BasePhase.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.graalvm.collections.EconomicMap;
3838

3939
import jdk.graal.compiler.core.GraalCompilerOptions;
40+
import jdk.graal.compiler.core.common.CompilationIdentifier;
4041
import jdk.graal.compiler.core.common.util.CompilationAlarm;
4142
import jdk.graal.compiler.debug.CounterKey;
4243
import jdk.graal.compiler.debug.DebugCloseable;
@@ -46,6 +47,7 @@
4647
import jdk.graal.compiler.debug.GraalError;
4748
import jdk.graal.compiler.debug.GraphFilter;
4849
import jdk.graal.compiler.debug.MemUseTrackerKey;
50+
import jdk.graal.compiler.debug.MethodFilter;
4951
import jdk.graal.compiler.debug.TTY;
5052
import jdk.graal.compiler.debug.TimerKey;
5153
import jdk.graal.compiler.graph.Graph;
@@ -62,9 +64,11 @@
6264
import jdk.graal.compiler.options.OptionKey;
6365
import jdk.graal.compiler.options.OptionType;
6466
import jdk.graal.compiler.options.OptionValues;
67+
import jdk.graal.compiler.phases.common.ReportHotCodePhase;
6568
import jdk.graal.compiler.phases.contract.NodeCostUtil;
6669
import jdk.graal.compiler.phases.contract.PhaseSizeContract;
6770
import jdk.graal.compiler.serviceprovider.GraalServices;
71+
import jdk.vm.ci.meta.JavaMethod;
6872
import jdk.vm.ci.meta.SpeculationLog;
6973

7074
/**
@@ -203,6 +207,12 @@ public static class PhaseOptions {
203207
public static final OptionKey<Integer> MinimalGraphNodeSizeCheckSize = new OptionKey<>(1000);
204208
@Option(help = "Exclude certain phases from compilation based on the given phase filter(s)." + PhaseFilterKey.HELP, type = OptionType.Debug)
205209
public static final PhaseFilterKey CompilationExcludePhases = new PhaseFilterKey(null, null);
210+
@Option(help = "Report hot metrics after each phase matching the given phase filter(s).", type = OptionType.Debug)
211+
public static final OptionKey<String> ReportHotMetricsAfterPhases = new OptionKey<>(null);
212+
@Option(help = "Report hot metrics before each phase matching the given phase filter(s).", type = OptionType.Debug)
213+
public static final OptionKey<String> ReportHotMetricsBeforePhases = new OptionKey<>("HighTierLoweringPhase");
214+
@Option(help = "Report hot metrics extracted from compiler IR.", type = OptionType.Debug)
215+
public static final OptionKey<String> ReportHotMetrics = new OptionKey<>(null);
206216
// @formatter:on
207217
}
208218

@@ -389,7 +399,7 @@ protected ApplyScope applyScope(StructuredGraph graph, C context) {
389399
return null;
390400
}
391401

392-
@SuppressWarnings("try")
402+
@SuppressWarnings({"try", "unchecked", "rawtypes"})
393403
public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) {
394404
DebugContext debug = graph.getDebug();
395405
OptionValues options = graph.getOptions();
@@ -449,6 +459,26 @@ public final void apply(final StructuredGraph graph, final C context, final bool
449459
dumpedBefore = dumpBefore(graph, context, isTopLevel, true);
450460
}
451461

462+
String reportHotMetricsMethodFilter = PhaseOptions.ReportHotMetrics.getValue(options);
463+
boolean logHotMetricsForGraph = false;
464+
if (reportHotMetricsMethodFilter != null) {
465+
MethodFilter hotMetricsMethodFilter = null;
466+
hotMetricsMethodFilter = MethodFilter.parse(reportHotMetricsMethodFilter);
467+
logHotMetricsForGraph = graph.method() != null && hotMetricsMethodFilter.matches(graph.method());
468+
if (!logHotMetricsForGraph) {
469+
CompilationIdentifier id = graph.compilationId();
470+
JavaMethod idMethod = id.asJavaMethod();
471+
logHotMetricsForGraph = idMethod != null && hotMetricsMethodFilter.matches(idMethod);
472+
}
473+
if (logHotMetricsForGraph) {
474+
if (PhaseOptions.ReportHotMetricsBeforePhases.getValue(graph.getOptions()).equals(getClass().getSimpleName())) {
475+
String label = graph.name != null ? graph.name : graph.method().format("%H.%n(%p)");
476+
TTY.println("Reporting hot metrics before " + getName() + " during compilation of " + label);
477+
new ReportHotCodePhase().apply(graph, context);
478+
}
479+
}
480+
}
481+
452482
// This is a manual version of a try/resource pattern since the close operation might
453483
// want to know whether the run call completed with an exception or not.
454484
ApplyScope applyScope = applyScope(graph, context);
@@ -495,6 +525,15 @@ public final void apply(final StructuredGraph graph, final C context, final bool
495525
}
496526
}
497527

528+
if (logHotMetricsForGraph) {
529+
String reportAfterPhase = PhaseOptions.ReportHotMetricsAfterPhases.getValue(graph.getOptions());
530+
if (reportAfterPhase != null && reportAfterPhase.equals(getClass().getSimpleName())) {
531+
String label = graph.name != null ? graph.name : graph.method().format("%H.%n(%p)");
532+
TTY.println("Reporting hot metrics after " + getName() + " during compilation of " + label);
533+
new ReportHotCodePhase().apply(graph, context);
534+
}
535+
}
536+
498537
} catch (Throwable t) {
499538
throw debug.handle(t);
500539
}

0 commit comments

Comments
 (0)