Skip to content

Commit

Permalink
[GR-52844] Add NI compiler configuration Os.
Browse files Browse the repository at this point in the history
PullRequest: graal/17340
  • Loading branch information
davleopo committed May 31, 2024
2 parents 3c803f6 + a057947 commit ee1c3a3
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ public AMD64Assembler(TargetDescription target) {

public AMD64Assembler(TargetDescription target, OptionValues optionValues) {
super(target);
useBranchesWithin32ByteBoundary = Options.UseBranchesWithin32ByteBoundary.getValue(optionValues);
useBranchesWithin32ByteBoundary = !GraalOptions.ReduceCodeSize.getValue(optionValues) && Options.UseBranchesWithin32ByteBoundary.getValue(optionValues);
optimizeLongJumps = GraalOptions.OptimizeLongJumps.getValue(optionValues);
}

public AMD64Assembler(TargetDescription target, OptionValues optionValues, boolean hasIntelJccErratum) {
super(target);
if (Options.UseBranchesWithin32ByteBoundary.hasBeenSet(optionValues)) {
useBranchesWithin32ByteBoundary = Options.UseBranchesWithin32ByteBoundary.getValue(optionValues);
useBranchesWithin32ByteBoundary = !GraalOptions.ReduceCodeSize.getValue(optionValues) && Options.UseBranchesWithin32ByteBoundary.getValue(optionValues);
} else {
useBranchesWithin32ByteBoundary = hasIntelJccErratum;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public final class GraalOptions {
@Option(help = "Uses compiler intrinsifications.", type = OptionType.Expert)
public static final OptionKey<Boolean> Intrinsify = new OptionKey<>(true);


@Option(help = "", type = OptionType.Debug)
public static final OptionKey<Boolean> ReduceCodeSize = new OptionKey<>(true);

@Option(help = "Rewrite signed comparisons to unsigned ones if the result is equal.", type = OptionType.Debug)
public static final OptionKey<Boolean> PreferUnsignedComparison = new OptionKey<>(true);

Expand Down Expand Up @@ -317,4 +321,8 @@ public final class GraalOptions {

@Option(help = "AMD64 only: Replace forward jumps (jmp, jcc) with equivalent but smaller instructions if the actual jump displacement fits in one byte.", type = OptionType.Expert)
public static final OptionKey<Boolean> OptimizeLongJumps = new OptionKey<>(false);

@Option(help = "Optimize integer division operation by using various mathematical foundations to "
+ " express it in faster, equivalent, arithmetic.", type = OptionType.Expert)
public static final OptionKey<Boolean> OptimizeDiv = new OptionKey<>(true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ public HighTier(OptionValues options) {
}

LoopPolicies loopPolicies = createLoopPolicies(options);
appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies));

if (GraalOptions.FullUnroll.getValue(options)) {
appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies));
}

if (GraalOptions.LoopPeeling.getValue(options)) {
appendPhase(new LoopPeelingPhase(loopPolicies, canonicalizer));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ public MidTier(OptionValues options) {
appendPhase(new VerifyHeapAtReturnPhase());
}

appendPhase(new LoopFullUnrollPhase(canonicalizer, createLoopPolicies(options)));
if (GraalOptions.FullUnroll.getValue(options)) {
appendPhase(new LoopFullUnrollPhase(canonicalizer, createLoopPolicies(options)));
}

appendPhase(new RemoveValueProxyPhase(canonicalizer));

appendPhase(new LoopSafepointInsertionPhase());
Expand All @@ -99,7 +102,9 @@ public MidTier(OptionValues options) {
appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false));
}

appendPhase(new OptimizeDivPhase(canonicalizer));
if (GraalOptions.OptimizeDiv.getValue(options)) {
appendPhase(new OptimizeDivPhase(canonicalizer));
}

appendPhase(new FrameStateAssignmentPhase());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_2;
import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_2;

import jdk.graal.compiler.core.common.GraalOptions;
import jdk.graal.compiler.core.common.type.StampFactory;
import jdk.graal.compiler.graph.NodeClass;
import jdk.graal.compiler.nodeinfo.NodeInfo;
Expand All @@ -50,7 +51,9 @@ public PrefetchAllocateNode(ValueNode address) {

@Override
public void generate(NodeLIRBuilderTool gen) {
gen.getLIRGeneratorTool().emitPrefetchAllocate(gen.operand(address));
if (!GraalOptions.ReduceCodeSize.getValue(this.getOptions())) {
gen.getLIRGeneratorTool().emitPrefetchAllocate(gen.operand(address));
}
}

@NodeIntrinsic
Expand Down
2 changes: 1 addition & 1 deletion docs/reference-manual/native-image/BuildOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Run `native-image --help` for help on build options.
* `--target`: select the compilation target for `native-image` (in the `<OS>-<architecture>` format). It defaults to host's OS-architecture pair.
* `--trace-class-initialization`: provide a comma-separated list of fully-qualified class names that a class initialization is traced for
* `--trace-object-instantiation`: provide a comma-separated list of fully-qualified class names that an object instantiation is traced for
* `-O<level>`: control code optimizations where available variants are: `b` - optimize for fastest build time, `0` - no optimizations, `1` - basic optimizations, `2` - aggressive optimizations, `3` - all optimizations for best performance (enabled automatically with the Profile-guided optimization)
* `-O<level>`: control code optimizations where available variants are: `b` - optimize for fastest build time, `s` - optimize for size, `0` - no optimizations, `1` - basic optimizations, `2` - aggressive optimizations, `3` - all optimizations for best performance (enabled automatically with Profile-Guided Optimizations)
* `-da`, `-da[:[packagename]|:[classname]`, `disableassertions[:[packagename]|:[classname]`: disable assertions with specified granularity at run time
* `-dsa`, `-disablesystemassertions`: disable assertions in all system classes at run time
* `-ea`, `-ea[:[packagename]|:[classname]`, `enableassertions[:[packagename]|:[classname]`: enable assertions with specified granularity at run time
Expand Down
3 changes: 2 additions & 1 deletion docs/reference-manual/native-image/BuildOutput.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ Please report version and vendor when you [file issues](https://github.com/oracl
The selected optimization level and targeted machine type used by the Graal compiler.
The optimization level can be controlled with the `-O` option and defaults to `2`, which enables aggressive optimizations.
Use `-Ob` to enable quick build mode, which speeds up the [compilation stage](#stage-compiling).
This is useful during development, or when peak throughput is less important and you would like to optimize for size.
This is useful during development to reduce image build time.
Use `-Os` to optimize for size.
The targeted machine type can be selected with the `-march` option and defaults to `x86-64-v3` on AMD64 and `armv8-a` on AArch64.
See [here](#recommendation-cpu) for recommendations on how to use this option.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The following table provides an overview of the different optimization levels an
| Level | Optimizations | Use Cases |
|:---:|:---:|---|
| `-Ob` | Reduced | Quick build mode: Speeds up builds during development by avoiding time-consuming optimizations. This can also reduce file size sometimes. |
| `-Os` | Reduced | Optimize for size: `-Os` enables all `-O2` optimizations except those that can increase code or image size significantly. Typically creates the smallest possible images at the cost of reduced performance. |
| `-O0` | None | Typically used together with `-g` to improve the debugging experience. |
| `-O1` | Basic | Trades performance for reduced file size and build time. Oracle GraalVM's `-O1` is somewhat comparable to `-O2` in GraalVM Community Edition. |
| `-O2` | Advanced | **Default:** Aims for good performance at a reasonable file size. |
Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-53359) Provide the `.debug_gdb_scripts` section that triggers auto-loading of `svmhelpers.py` in GDB. Remove single and double quotes from `ClassLoader.nameAndId` in the debuginfo.
* (GR-47365) Include dynamic proxy metadata in the reflection metadata with the syntax `"type": { "proxy": [<interface list>] }`. This allows members of proxy classes to be accessed reflectively. `proxy-config.json` is now deprecated but will still be honored.
* (GR-18214) In-place compacting garbage collection for the Serial GC old generation with `-H:+CompactingOldGen`.
* (GR-52844) Add `Os` a new optimization mode to configure the optimizer in a way to get the smallest code size.

## GraalVM for JDK 22 (Internal Version 24.0.0)
* (GR-48304) Red Hat added support for the JFR event ThreadAllocationStatistics.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public static void llvmCompile(DebugContext debug, String outputPath, String inp

private static int optimizationLevel() {
return switch (SubstrateOptions.optimizationLevel()) {
case O0, BUILD_TIME -> 0;
case O0, BUILD_TIME, SIZE -> 0;
case O1 -> 1;
case O2 -> 2;
case O3 -> 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import jdk.graal.compiler.options.OptionStability;
import jdk.graal.compiler.options.OptionType;
import jdk.graal.compiler.options.OptionValues;
import jdk.graal.compiler.phases.common.DeadCodeEliminationPhase;
import jdk.internal.misc.Unsafe;

public class SubstrateOptions {
Expand Down Expand Up @@ -233,7 +234,8 @@ public enum OptimizationLevel {
O1("Basic optimizations", "1"),
O2("Advanced optimizations", "2"),
O3("All optimizations for best performance", "3"),
BUILD_TIME("Optimize for fastest build time", "b");
BUILD_TIME("Optimize for fastest build time", "b"),
SIZE("Optimize for size", "s");

private final String description;
private final String optionSwitch;
Expand Down Expand Up @@ -268,7 +270,7 @@ public boolean isOneOf(OptimizationLevel... levels) {
}

@APIOption(name = "-O", valueSeparator = APIOption.NO_SEPARATOR)//
@Option(help = "Control code optimizations: b - optimize for fastest build time, " +
@Option(help = "Control code optimizations: b - optimize for fastest build time, s - optimize for size, " +
"0 - no optimizations, 1 - basic optimizations, 2 - advanced optimizations, 3 - all optimizations for best performance.", type = OptionType.User)//
public static final HostedOptionKey<String> Optimize = new HostedOptionKey<>("2") {

Expand All @@ -290,20 +292,77 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String ol
SubstrateOptions.ReduceImplicitExceptionStackTraceInformation.update(values, newLevel == OptimizationLevel.O3);

GraalOptions.OptimizeLongJumps.update(values, !newLevel.isOneOf(OptimizationLevel.O0, OptimizationLevel.BUILD_TIME));

if (newLevel == OptimizationLevel.SIZE) {
configureOs(values);
}

if (optimizeValueUpdateHandler != null) {
optimizeValueUpdateHandler.onValueUpdate(values, newLevel);
}

}
};

public static void configureOs(EconomicMap<OptionKey<?>, Object> values) {
enable(GraalOptions.ReduceCodeSize, values);
enable(ReduceImplicitExceptionStackTraceInformation, values);
enable(GraalOptions.OptimizeLongJumps, values);

/*
* Remove all loop optimizations that can increase code size, i.e., duplicate a loop body
* somehow.
*/
disable(GraalOptions.LoopPeeling, values);
disable(GraalOptions.LoopUnswitch, values);
disable(GraalOptions.FullUnroll, values);
disable(GraalOptions.PartialUnroll, values);

/*
* Do not align loop headers to further reduce code size.
*/
GraalOptions.LoopHeaderAlignment.update(values, 0);
GraalOptions.IsolatedLoopHeaderAlignment.update(values, 0);

/*
* Do not run PEA - it can fan out allocations too much.
*/
disable(GraalOptions.PartialEscapeAnalysis, values);

/*
* Do not fan out division.
*/
disable(GraalOptions.OptimizeDiv, values);

/*
* Do more conditional elimination.
*/
GraalOptions.ConditionalEliminationMaxIterations.update(values, 10);

/*
* Every dead code elimination should be non-optional
*/
disable(DeadCodeEliminationPhase.Options.ReduceDCE, values);
}

public static void disable(OptionKey<Boolean> key, EconomicMap<OptionKey<?>, Object> values) {
key.update(values, false);
}

public static void enable(OptionKey<Boolean> key, EconomicMap<OptionKey<?>, Object> values) {
key.update(values, true);
}

/**
* Only allows 'b' or positive numeric optimization levels, throws a user error otherwise.
*/
private static OptimizationLevel parseOptimizationLevel(String value) {
if (value.equals("b")) {
return OptimizationLevel.BUILD_TIME;
}
if (value.equals("s")) {
return OptimizationLevel.SIZE;
}

int intLevel;
try {
Expand Down Expand Up @@ -335,11 +394,20 @@ public static boolean useEconomyCompilerConfig(OptionValues options) {
return "b".equals(Optimize.getValue(options));
}

public static boolean useCodeSizeCompilerConfig(OptionValues options) {
return "s".equals(Optimize.getValue(options));
}

@Fold
public static boolean useEconomyCompilerConfig() {
return useEconomyCompilerConfig(HostedOptionValues.singleton());
}

@Fold
public static boolean useCodeSizeCompilerConfig() {
return useCodeSizeCompilerConfig(HostedOptionValues.singleton());
}

@Fold
public static boolean isMaximumOptimizationLevel() {
return optimizationLevel() == OptimizationLevel.O3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1581,17 +1581,21 @@ private static boolean checkInvocationPluginMethods(SubstrateReplacements replac
return true;
}

public static Suites createSuites(FeatureHandler featureHandler, RuntimeConfiguration runtimeConfig, boolean hosted) {
public static Suites createSuites(FeatureHandler featureHandler, RuntimeConfiguration runtimeConfig, boolean hosted, OptionValues optionsToUse) {
SubstrateBackend backend = runtimeConfig.getBackendForNormalMethod();
Suites suites;
if (hosted) {
suites = GraalConfiguration.hostedInstance().createSuites(HostedOptionValues.singleton(), hosted, ConfigurationValues.getTarget().arch);
suites = GraalConfiguration.hostedInstance().createSuites(optionsToUse == null ? HostedOptionValues.singleton() : optionsToUse, hosted, ConfigurationValues.getTarget().arch);
} else {
suites = GraalConfiguration.runtimeInstance().createSuites(RuntimeOptionValues.singleton(), hosted, ConfigurationValues.getTarget().arch);
suites = GraalConfiguration.runtimeInstance().createSuites(optionsToUse == null ? RuntimeOptionValues.singleton() : optionsToUse, hosted, ConfigurationValues.getTarget().arch);
}
return modifySuites(backend, suites, featureHandler, hosted, false);
}

public static Suites createSuites(FeatureHandler featureHandler, RuntimeConfiguration runtimeConfig, boolean hosted) {
return createSuites(featureHandler, runtimeConfig, hosted, null);
}

public static Suites createFirstTierSuites(FeatureHandler featureHandler, RuntimeConfiguration runtimeConfig, boolean hosted) {
SubstrateBackend backend = runtimeConfig.getBackendForNormalMethod();
Suites suites;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.util.InterruptImageBuilding;
import com.oracle.svm.hosted.DeadlockWatchdog;
import com.oracle.svm.hosted.FeatureImpl.BeforeImageWriteAccessImpl;
import com.oracle.svm.hosted.NativeImageOptions;
import com.oracle.svm.hosted.c.NativeLibraries;
Expand Down Expand Up @@ -138,6 +139,11 @@ private void runLinkerCommand(String imageName, LinkerInvocation inv, List<Strin

List<String> lines;
try (InputStream inputStream = linkerProcess.getInputStream()) {
/*
* The linker can be slow, record activity just before so that we have the full
* watchdog interval available.
*/
DeadlockWatchdog.singleton().recordActivity();
lines = FileUtils.readAllLines(inputStream);
FileUtils.traceCommandOutput(lines);
}
Expand Down
6 changes: 3 additions & 3 deletions vm/mx.vm/mx_vm_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ def _configure_from_name(self, config_name):
# This defines the allowed config names for NativeImageVM. The ones registered will be available via --jvm-config
rule = r'^(?P<native_architecture>native-architecture-)?(?P<string_inlining>string-inlining-)?(?P<gate>gate-)?(?P<upx>upx-)?(?P<quickbuild>quickbuild-)?(?P<gc>g1gc-)?(?P<llvm>llvm-)?(?P<pgo>pgo-|pgo-ctx-insens-|pgo-sampler-)?(?P<inliner>inline-)?' \
r'(?P<analysis_context_sensitivity>insens-|allocsens-|1obj-|2obj1h-|3obj2h-|4obj3h-)?(?P<no_inlining_before_analysis>no-inline-)?(?P<jdk_profiles>jdk-profiles-collect-|adopted-jdk-pgo-)?' \
r'(?P<profile_inference>profile-inference-feature-extraction-|profile-inference-pgo-)?(?P<sampler>safepoint-sampler-|async-sampler-)?(?P<optimization_level>O0-|O1-|O2-|O3-)?(?P<edition>ce-|ee-)?$'
r'(?P<profile_inference>profile-inference-feature-extraction-|profile-inference-pgo-)?(?P<sampler>safepoint-sampler-|async-sampler-)?(?P<optimization_level>O0-|O1-|O2-|O3-|Os-)?(?P<edition>ce-|ee-)?$'

mx.logv(f"== Registering configuration: {config_name}")
match_name = f"{config_name}-" # adding trailing dash to simplify the regex
Expand Down Expand Up @@ -679,7 +679,7 @@ def generate_profiling_package_prefixes():
if matching.group("optimization_level") is not None:
olevel = matching.group("optimization_level")[:-1]
mx.logv(f"GraalVM optimization level is set to: {olevel}")
if olevel in ["O0", "O1", "O2", "O3"]:
if olevel in ["O0", "O1", "O2", "O3", "Os"]:
self.optimization_level = olevel
else:
mx.abort(f"Unknown configuration for optimization level: {olevel}")
Expand Down Expand Up @@ -1801,7 +1801,7 @@ def register_graalvm_vms():
mx_polybenchmarks_benchmark.polybenchmark_vm_registry.add_vm(PolyBenchVm(host_vm_name, "native", [], ["--native"]))
mx_polybenchmarks_benchmark.rules = polybenchmark_rules

optimization_levels = ['O0', 'O1', 'O2', 'O3']
optimization_levels = ['O0', 'O1', 'O2', 'O3', 'Os']

# Inlining before analysis is done by default
analysis_context_sensitivity = ['insens', 'allocsens', '1obj', '2obj1h', '3obj2h', '4obj3h']
Expand Down

0 comments on commit ee1c3a3

Please sign in to comment.