Skip to content

Commit 9377add

Browse files
committed
[GR-44110] Add -march option and target x86-64-v3 by default.
PullRequest: graal/13876
2 parents e1c63a1 + 2f728fc commit 9377add

File tree

10 files changed

+501
-54
lines changed

10 files changed

+501
-54
lines changed

sdk/mx.sdk/mx_sdk_vm_impl.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,7 @@ def contents(self):
12551255
image_config = self.subject.image_config
12561256
build_args = [
12571257
'--no-fallback',
1258+
'-march=compatibility', # Target maximum portability of all GraalVM images.
12581259
'-H:+AssertInitializationSpecifiedForAllClasses',
12591260
'-H:+EnforceMaxRuntimeCompileMethods',
12601261
'-Dorg.graalvm.version={}'.format(_suite.release_version()),

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This changelog summarizes major changes to GraalVM Native Image.
2525
* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs.
2626
* (GR-40641) Dynamic linking of AWT libraries on Linux.
2727
* (GR-40463) Red Hat added experimental support for JMX, which can be enabled with the `--enable-monitoring` option (e.g. `--enable-monitoring=jmxclient,jmxserver`).
28+
* (GR-44110) Native Image now targets `x86-64-v3` by default on AMD64 and supports a new `-march` option. Use `-march=compatibility` for best compatibility (previous default) or `-march=native` for best performance if the native executable is deployed on the same machine or on a machine with the same CPU features. To list all available machine types, use `-march=list`.
2829

2930
## Version 22.3.0
3031
* (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option.

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,15 +1008,15 @@ private int completeImageBuild() {
10081008
.collect(Collectors.joining(",", oHCLibraryPath, ""));
10091009
imageBuilderArgs.add(0, clibrariesBuilderArg);
10101010

1011-
String printFlagsDummyImage = "dummy-image-";
1011+
boolean printFlags = false;
10121012
if (printFlagsOptionQuery != null) {
1013+
printFlags = true;
10131014
addPlainImageBuilderArg(NativeImage.oH + enablePrintFlags + "=" + printFlagsOptionQuery);
10141015
addPlainImageBuilderArg(NativeImage.oR + enablePrintFlags + "=" + printFlagsOptionQuery);
1015-
addPlainImageBuilderArg(oHName + printFlagsDummyImage + "printFlagsOptionQuery");
10161016
} else if (printFlagsWithExtraHelpOptionQuery != null) {
1017+
printFlags = true;
10171018
addPlainImageBuilderArg(NativeImage.oH + enablePrintFlagsWithExtraHelp + "=" + printFlagsWithExtraHelpOptionQuery);
10181019
addPlainImageBuilderArg(NativeImage.oR + enablePrintFlagsWithExtraHelp + "=" + printFlagsWithExtraHelpOptionQuery);
1019-
addPlainImageBuilderArg(oHName + printFlagsDummyImage + "printFlagsWithExtraHelpOptionQuery");
10201020
}
10211021

10221022
if (shouldAddCWDToCP()) {
@@ -1062,9 +1062,12 @@ private int completeImageBuild() {
10621062
mainClass = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHClass);
10631063
boolean buildExecutable = imageBuilderArgs.stream().noneMatch(arg -> arg.contains(oHEnableSharedLibraryFlag));
10641064
boolean listModules = imageBuilderArgs.stream().anyMatch(arg -> arg.contains(oH + "+" + "ListModules"));
1065-
boolean printFlags = imageBuilderArgs.stream().anyMatch(arg -> arg.contains(enablePrintFlags) || arg.contains(enablePrintFlagsWithExtraHelp));
1065+
printFlags |= imageBuilderArgs.stream().anyMatch(arg -> arg.contains("-march=list"));
10661066

1067-
if (!printFlags) {
1067+
if (printFlags) {
1068+
/* Ensure name for bundle support */
1069+
addPlainImageBuilderArg(oHName + "dummy-image");
1070+
} else {
10681071
List<String> extraImageArgs = new ArrayList<>();
10691072
ListIterator<String> leftoverArgsItr = leftoverArgs.listIterator();
10701073
while (leftoverArgsItr.hasNext()) {
@@ -1133,7 +1136,7 @@ private int completeImageBuild() {
11331136
Path imageNamePath = Path.of(imageName);
11341137
Path imageNamePathParent = imageNamePath.getParent();
11351138
if (imageNamePathParent != null) {
1136-
/* Readjust imageName & imagePath so that imageName is just a simple fileName */
1139+
/* Read just imageName & imagePath so that imageName is just a simple fileName */
11371140
imageName = imageNamePath.getFileName().toString();
11381141
if (!imageNamePathParent.isAbsolute()) {
11391142
imageNamePathParent = imagePath.resolve(imageNamePathParent);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/CPUFeatureAccessFeatureBase.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2023, 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
@@ -115,9 +115,10 @@ protected <T extends Enum<T>> void initializeCPUFeatureAccessData(Enum<T>[] allC
115115
}
116116
}
117117
if (!unknownFeatures.isEmpty()) {
118-
throw VMError.shouldNotReachHere("Native image does not support the following JVMCI CPU features: " + unknownFeatures);
118+
throw VMError.shouldNotReachHere("The image does not support the following JVMCI CPU features: " + unknownFeatures);
119119
}
120-
String errorMessage = "Current target does not support the following CPU features that are required by the image: " + buildtimeCPUFeatures.toString() + "\n\0";
120+
String errorMessage = "The current machine does not support all of the following CPU features that are required by the image: " + buildtimeCPUFeatures.toString() + "." +
121+
System.lineSeparator() + "Please rebuild the executable with an appropriate setting of the -march option.\0";
121122
var cpuFeatureAccess = createCPUFeatureAccessSingleton(buildtimeCPUFeatures, cpuFeatureEnumToStructOffset, errorMessage.getBytes(StandardCharsets.UTF_8), requiredFeaturesStruct);
122123
ImageSingletons.add(CPUFeatureAccess.class, cpuFeatureAccess);
123124
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2023, 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
@@ -293,6 +293,8 @@
293293
import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor;
294294
import com.oracle.svm.hosted.substitute.DeletedFieldsPlugin;
295295
import com.oracle.svm.hosted.substitute.UnsafeAutomaticSubstitutionProcessor;
296+
import com.oracle.svm.hosted.util.CPUTypeAArch64;
297+
import com.oracle.svm.hosted.util.CPUTypeAMD64;
296298
import com.oracle.svm.util.ClassUtil;
297299
import com.oracle.svm.util.ImageBuildStatistics;
298300
import com.oracle.svm.util.ReflectionUtil;
@@ -439,17 +441,8 @@ protected SubstrateTargetDescription createTarget() {
439441

440442
public static SubstrateTargetDescription createTarget(Platform platform) {
441443
if (includedIn(platform, Platform.AMD64.class)) {
442-
Architecture architecture;
443-
EnumSet<AMD64.CPUFeature> features = EnumSet.noneOf(AMD64.CPUFeature.class);
444-
if (NativeImageOptions.NativeArchitecture.getValue()) {
445-
features.addAll(((AMD64) GraalAccess.getOriginalTarget().arch).getFeatures());
446-
} else {
447-
// SSE and SSE2 are added by default as they are required by Graal
448-
features.add(AMD64.CPUFeature.SSE);
449-
features.add(AMD64.CPUFeature.SSE2);
450-
451-
features.addAll(parseCSVtoEnum(AMD64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AMD64.CPUFeature.values()));
452-
}
444+
EnumSet<AMD64.CPUFeature> features = CPUTypeAMD64.getSelectedFeatures();
445+
features.addAll(parseCSVtoEnum(AMD64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AMD64.CPUFeature.values()));
453446
// GR-33542 RTM is only intermittently detected and is not used by Graal
454447
features.remove(AMD64.CPUFeature.RTM);
455448
// set up the runtime checked cpu features
@@ -464,50 +457,31 @@ public static SubstrateTargetDescription createTarget(Platform platform) {
464457
}
465458
}
466459
}
467-
architecture = new AMD64(features, AMD64CPUFeatureAccess.allAMD64Flags());
468-
assert architecture instanceof AMD64 : "using AMD64 platform with a different architecture";
460+
AMD64 architecture = new AMD64(features, AMD64CPUFeatureAccess.allAMD64Flags());
469461
int deoptScratchSpace = 2 * 8; // Space for two 64-bit registers: rax and xmm0
470462
return new SubstrateTargetDescription(architecture, true, 16, 0, deoptScratchSpace, runtimeCheckedFeatures);
471463
} else if (includedIn(platform, Platform.AARCH64.class)) {
472-
Architecture architecture;
473-
if (NativeImageOptions.NativeArchitecture.getValue()) {
474-
architecture = GraalAccess.getOriginalTarget().arch;
475-
} else {
476-
EnumSet<AArch64.CPUFeature> features = EnumSet.noneOf(AArch64.CPUFeature.class);
477-
/*
478-
* FP is added by default, as floating-point operations are required by Graal.
479-
*/
480-
features.add(AArch64.CPUFeature.FP);
481-
/*
482-
* ASIMD is added by default, as it is available in all AArch64 machines with
483-
* floating-port support.
484-
*/
485-
features.add(AArch64.CPUFeature.ASIMD);
486-
487-
features.addAll(parseCSVtoEnum(AArch64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AArch64.CPUFeature.values()));
488-
489-
architecture = new AArch64(features, AArch64CPUFeatureAccess.enabledAArch64Flags());
490-
}
491-
assert architecture instanceof AArch64 : "using AArch64 platform with a different architecture";
464+
EnumSet<AArch64.CPUFeature> features = CPUTypeAArch64.getSelectedFeatures();
465+
features.addAll(parseCSVtoEnum(AArch64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AArch64.CPUFeature.values()));
466+
AArch64 architecture = new AArch64(features, AArch64CPUFeatureAccess.enabledAArch64Flags());
492467
// runtime checked features are the same as static features on AArch64 for now
493-
EnumSet<AArch64.CPUFeature> runtimeCheckedFeatures = ((AArch64) architecture).getFeatures().clone();
468+
EnumSet<AArch64.CPUFeature> runtimeCheckedFeatures = architecture.getFeatures().clone();
494469
int deoptScratchSpace = 2 * 8; // Space for two 64-bit registers: r0 and v0.
495470
return new SubstrateTargetDescription(architecture, true, 16, 0, deoptScratchSpace, runtimeCheckedFeatures);
496471
} else if (includedIn(platform, Platform.RISCV64.class)) {
497472
Class<?> riscv64CPUFeature = RISCV64ReflectionUtil.lookupClass(false, RISCV64ReflectionUtil.featureClass);
498473
Architecture architecture;
499-
if (NativeImageOptions.NativeArchitecture.getValue()) {
474+
if (NativeImageOptions.MICRO_ARCHITECTURE_NATIVE.equals(NativeImageOptions.MicroArchitecture.getValue())) {
500475
architecture = GraalAccess.getOriginalTarget().arch;
501476
} else {
502477
Method noneOf = RISCV64ReflectionUtil.lookupMethod(EnumSet.class, "noneOf", Class.class);
503478
EnumSet<?> features = (EnumSet<?>) RISCV64ReflectionUtil.invokeMethod(noneOf, null, riscv64CPUFeature);
504479
Method parseCSVtoEnum = RISCV64ReflectionUtil.lookupMethod(NativeImageGenerator.class, "parseCSVtoEnum", Class.class, List.class, Enum[].class);
505480
parseCSVtoEnum.setAccessible(true);
506481
Method addAll = RISCV64ReflectionUtil.lookupMethod(AbstractCollection.class, "addAll", Collection.class);
507-
508482
RISCV64ReflectionUtil.invokeMethod(addAll, features,
509-
RISCV64ReflectionUtil.invokeMethod(parseCSVtoEnum, null, riscv64CPUFeature, NativeImageOptions.CPUFeatures.getValue().values(), riscv64CPUFeature.getEnumConstants()));
510-
483+
RISCV64ReflectionUtil.invokeMethod(parseCSVtoEnum, null, riscv64CPUFeature, NativeImageOptions.CPUFeatures.getValue().values(),
484+
riscv64CPUFeature.getEnumConstants()));
511485
architecture = (Architecture) ReflectionUtil.newInstance(ReflectionUtil.lookupConstructor(RISCV64ReflectionUtil.getArch(false), EnumSet.class, EnumSet.class), features,
512486
RISCV64CPUFeatureAccess.enabledRISCV64Flags());
513487
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGeneratorRunner.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,13 +521,13 @@ public static void printCPUFeatures(Platform platform) {
521521
if (NativeImageGenerator.includedIn(platform, Platform.AMD64.class)) {
522522
message.append("All AMD64 CPUFeatures: ").append(Arrays.toString(AMD64.CPUFeature.values()));
523523
if (arch instanceof AMD64) {
524-
message.append("\nHost machine AMD64 CPUFeatures: ").append(((AMD64) arch).getFeatures().toString());
524+
message.append(System.lineSeparator()).append("Host machine AMD64 CPUFeatures: ").append(((AMD64) arch).getFeatures().toString());
525525
}
526526
} else {
527527
assert NativeImageGenerator.includedIn(platform, Platform.AARCH64.class);
528528
message.append("All AArch64 CPUFeatures: ").append(Arrays.toString(AArch64.CPUFeature.values()));
529529
if (arch instanceof AArch64) {
530-
message.append("\nHost machine AArch64 CPUFeatures: ").append(((AArch64) arch).getFeatures().toString());
530+
message.append(System.lineSeparator()).append("Host machine AArch64 CPUFeatures: ").append(((AArch64) arch).getFeatures().toString());
531531
}
532532
}
533533
System.out.println(message);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2023, 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
@@ -47,8 +47,12 @@
4747
import com.oracle.svm.core.option.HostedOptionKey;
4848
import com.oracle.svm.core.option.LocatableMultiOptionValue;
4949
import com.oracle.svm.core.option.SubstrateOptionsParser;
50+
import com.oracle.svm.core.util.InterruptImageBuilding;
5051
import com.oracle.svm.core.util.UserError;
5152
import com.oracle.svm.hosted.classinitialization.ClassInitializationOptions;
53+
import com.oracle.svm.hosted.util.CPUType;
54+
import com.oracle.svm.hosted.util.CPUTypeAArch64;
55+
import com.oracle.svm.hosted.util.CPUTypeAMD64;
5256

5357
public class NativeImageOptions {
5458

@@ -58,7 +62,8 @@ public class NativeImageOptions {
5862
"target executable, irrespective of whether they are supported by the hosted " +
5963
"environment. Note that enabling features not present within the target environment " +
6064
"may result in application crashes. The specific options available are target " +
61-
"platform dependent. See --list-cpu-features for feature list.", type = User)//
65+
"platform dependent. See --list-cpu-features for feature list. These features " +
66+
"are in addition to -march.", type = User)//
6267
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> CPUFeatures = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
6368

6469
@APIOption(name = "list-cpu-features")//
@@ -76,8 +81,37 @@ public class NativeImageOptions {
7681
"AMD64: 'AVX,AVX2'; AArch64: ''", type = User)//
7782
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> RuntimeCheckedCPUFeatures = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
7883

79-
@Option(help = "Overrides CPUFeatures and uses the native architecture, i.e., the architecture of a machine that builds an image. NativeArchitecture takes precedence over CPUFeatures", type = User)//
80-
public static final HostedOptionKey<Boolean> NativeArchitecture = new HostedOptionKey<>(false);
84+
public static final String MICRO_ARCHITECTURE_NATIVE = "native";
85+
public static final String MICRO_ARCHITECTURE_COMPATIBILITY = "compatibility";
86+
public static final String MICRO_ARCHITECTURE_LIST = "list";
87+
88+
@APIOption(name = "-march")//
89+
@Option(help = "Generate instructions for a specific machine type. Defaults to 'x86-64-v3' on AMD64 and 'armv8-a' on AArch64. " +
90+
"Use -march=" + MICRO_ARCHITECTURE_COMPATIBILITY + " for best compatibility, or -march=" + MICRO_ARCHITECTURE_NATIVE +
91+
" for best performance if the native executable is deployed on the same machine or on a machine with the same CPU features. " +
92+
"To list all available machine types, use -march=" + MICRO_ARCHITECTURE_LIST + ".", type = User)//
93+
public static final HostedOptionKey<String> MicroArchitecture = new HostedOptionKey<>(null) {
94+
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String oldValue, String newValue) {
95+
if (MICRO_ARCHITECTURE_LIST.equals(newValue)) {
96+
if (System.getProperty("os.arch").equalsIgnoreCase("aarch64")) {
97+
CPUType.print("AArch64", CPUTypeAArch64.values());
98+
CPUTypeAArch64.printFeatureModifiers();
99+
} else {
100+
CPUType.print("AMD64", CPUTypeAMD64.values());
101+
}
102+
throw new InterruptImageBuilding("");
103+
}
104+
}
105+
};
106+
107+
@Option(help = "Uses the native architecture, i.e., the architecture of a machine that builds an image.", type = User, //
108+
deprecated = true, deprecationMessage = "Please use -march=native instead. See --help for details.") //
109+
public static final HostedOptionKey<Boolean> NativeArchitecture = new HostedOptionKey<>(false) {
110+
@Override
111+
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
112+
MicroArchitecture.update(values, newValue ? MICRO_ARCHITECTURE_NATIVE : null);
113+
}
114+
};
81115

82116
@Option(help = "Print information about classes, methods, and fields that are present in the native image")//
83117
public static final HostedOptionKey<Boolean> PrintUniverse = new HostedOptionKey<>(false);

0 commit comments

Comments
 (0)