Skip to content

Commit 4d67665

Browse files
committed
[GR-67783] Correctly update vector architecture for SVM runtime compilations, delay Vector API stamp computation
PullRequest: graal/21546
2 parents 74c0848 + 5ab60d4 commit 4d67665

File tree

12 files changed

+81
-37
lines changed

12 files changed

+81
-37
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/GraphState.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, 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
@@ -610,6 +610,7 @@ public enum StageFlag {
610610
LOOP_OVERFLOWS_CHECKED,
611611
PARTIAL_ESCAPE,
612612
FINAL_PARTIAL_ESCAPE,
613+
VECTOR_API_EXPANSION,
613614
HIGH_TIER_LOWERING,
614615
/* Stages applied by mid tier. */
615616
FLOATING_READS,

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/vector/architecture/VectorArchitecture.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import jdk.graal.compiler.options.OptionValues;
5151
import jdk.graal.compiler.vector.nodes.simd.LogicValueStamp;
5252
import jdk.graal.compiler.vector.nodes.simd.SimdStamp;
53+
import jdk.graal.compiler.vector.replacements.vectorapi.VectorAPIType;
5354
import jdk.vm.ci.meta.JavaKind;
5455

5556
/**
@@ -69,6 +70,9 @@ public abstract class VectorArchitecture {
6970
protected final Stamp oopMaskStamp;
7071
protected int cachedMaxVectorLength;
7172

73+
/** The table of Vector API types associated with this vector architecture. */
74+
protected VectorAPIType.Table vectorAPITypeTable;
75+
7276
@Override
7377
public boolean equals(Object o) {
7478
if (o == null || getClass() != o.getClass()) {
@@ -472,4 +476,13 @@ public Stamp maskStamp(Stamp elementStamp) {
472476
return LogicValueStamp.UNRESTRICTED;
473477
}
474478
}
479+
480+
public VectorAPIType.Table getVectorAPITypeTable() {
481+
return vectorAPITypeTable;
482+
}
483+
484+
public void setVectorAPITypeTable(VectorAPIType.Table table) {
485+
GraalError.guarantee(this.vectorAPITypeTable == null, "Vector API type table must only be set once per vector architecture");
486+
this.vectorAPITypeTable = table;
487+
}
475488
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/vector/architecture/amd64/VectorAMD64.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,15 @@ private static int maxVectorSizeForArchitecture(AMD64 arch) {
432432
return Math.min(maxPhysicalSize, maxDesiredSize);
433433
}
434434

435-
public void updateMaxVectorSizeForArchitecture(AMD64 newArch) {
435+
/**
436+
* To be called only when (re-)configuring the compiler for an SVM runtime compilation. Resets
437+
* precomputed values stored in this vector architecture instance for the now known runtime
438+
* target architecture.
439+
*/
440+
public void updateForRuntimeArchitecture(AMD64 newArch) {
436441
this.cachedMaxVectorLength = 0; // force recomputation
437442
this.maxVectorSize = maxVectorSizeForArchitecture(newArch);
443+
this.vectorAPITypeTable = null;
438444
}
439445

440446
/**

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/vector/replacements/vectorapi/VectorAPIExpansionPhase.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,19 @@ public void checkInvariants() {
211211

212212
@Override
213213
protected void run(StructuredGraph graph, HighTierContext context) {
214+
graph.getGraphState().setDuringStage(GraphState.StageFlag.VECTOR_API_EXPANSION);
214215
if (!graph.hasNode(VectorAPIMacroNode.TYPE)) {
215216
return;
216217
}
217218

219+
/*
220+
* Canonicalize first. Needed for computing SIMD stamps, since we delay their computation to
221+
* compile time. We can't generally compute SIMD stamps at the time we build the macro nodes
222+
* because the target architecture for SVM runtime compilations is not known at that time.
223+
*/
224+
canonicalizer.applyIncremental(graph, context, graph.getNodes(VectorAPIMacroNode.TYPE));
225+
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "after Vector API macro canonicalization");
226+
218227
VectorArchitecture vectorArch = ((VectorLoweringProvider) context.getLowerer()).getVectorArchitecture();
219228
/*
220229
* Nodes visited while discovering the equivalence classes. All nodes that are in one of the

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/vector/replacements/vectorapi/VectorAPIType.java

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,14 @@
2626

2727
import org.graalvm.collections.EconomicMap;
2828

29-
import jdk.graal.compiler.vector.architecture.VectorArchitecture;
30-
import jdk.graal.compiler.vector.nodes.simd.SimdStamp;
31-
3229
import jdk.graal.compiler.core.common.type.IntegerStamp;
3330
import jdk.graal.compiler.core.common.type.Stamp;
3431
import jdk.graal.compiler.core.common.type.StampFactory;
3532
import jdk.graal.compiler.debug.GraalError;
3633
import jdk.graal.compiler.nodes.ValueNode;
3734
import jdk.graal.compiler.nodes.spi.CoreProviders;
35+
import jdk.graal.compiler.vector.architecture.VectorArchitecture;
36+
import jdk.graal.compiler.vector.nodes.simd.SimdStamp;
3837
import jdk.vm.ci.meta.ConstantReflectionProvider;
3938
import jdk.vm.ci.meta.JavaKind;
4039
import jdk.vm.ci.meta.ResolvedJavaField;
@@ -112,11 +111,12 @@ public static VectorAPIType ofConstant(ValueNode value, CoreProviders providers)
112111
public static final String VECTOR_PACKAGE_NAME = "jdk.incubator.vector";
113112

114113
/**
115-
* Lookup table for Java Vector API types. An unmodifiable singleton instance of this table is
116-
* built lazily on the first lookup request. Users of {@link VectorAPIType} should not interact
117-
* with this class directly, only through {@link #ofType}.
114+
* Lookup table for Java Vector API types. An unmodifiable instance of this table is built
115+
* lazily on the first lookup request for each {@link VectorArchitecture} instance. The vector
116+
* architecture is the owner of its associated table. Users of {@link VectorAPIType} should not
117+
* interact with this class directly, only through {@link #ofType}.
118118
*/
119-
private static final class Table {
119+
public static final class Table {
120120

121121
/** The element types for which the Vector API provides vector types. */
122122
private static final JavaKind[] KINDS = new JavaKind[]{JavaKind.Byte, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Float, JavaKind.Double};
@@ -132,17 +132,14 @@ private static final class Table {
132132
/** The vector architecture for which this table was built. */
133133
private final VectorArchitecture vectorArch;
134134

135-
/** Singleton instance lazily initialized via double-checked locking. */
136-
private static volatile Table instance;
137-
138135
private static Table instance(VectorArchitecture vectorArch) {
139-
Table result = instance;
136+
Table result = vectorArch.getVectorAPITypeTable();
140137
if (result == null) {
141-
synchronized (Table.class) {
142-
result = instance;
138+
synchronized (vectorArch) {
139+
result = vectorArch.getVectorAPITypeTable();
143140
if (result == null) {
144141
result = buildLookupTable(vectorArch);
145-
instance = result;
142+
vectorArch.setVectorAPITypeTable(result);
146143
}
147144
}
148145
}
@@ -194,18 +191,6 @@ private static void recordEntries(EconomicMap<String, VectorAPIType> table, Java
194191
}
195192
}
196193

197-
/**
198-
* Reset the singleton {@link Table} instance to {@code null}. The next lookup in the table will
199-
* reinitialize it. This method is for testing only: Native image tests can build multiple
200-
* images in the same process with different vector architectures, so we need to forget the type
201-
* table between builds.
202-
*/
203-
public static void resetTableForTestingOnly() {
204-
synchronized (Table.class) {
205-
Table.instance = null;
206-
}
207-
}
208-
209194
/**
210195
* Verify that this data structure corresponds to the given {@code javaType}. Specifically, the
211196
* type must be initialized, and its {@code VLENGTH} and {@code ETYPE} fields must correspond to

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/vector/replacements/vectorapi/nodes/VectorAPIMacroNode.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@
4747
import jdk.graal.compiler.nodes.ConstantNode;
4848
import jdk.graal.compiler.nodes.FixedNode;
4949
import jdk.graal.compiler.nodes.FrameState;
50+
import jdk.graal.compiler.nodes.GraphState;
5051
import jdk.graal.compiler.nodes.Invoke;
5152
import jdk.graal.compiler.nodes.NodeView;
5253
import jdk.graal.compiler.nodes.PiNode;
54+
import jdk.graal.compiler.nodes.StructuredGraph;
5355
import jdk.graal.compiler.nodes.ValueNode;
5456
import jdk.graal.compiler.nodes.ValuePhiNode;
5557
import jdk.graal.compiler.nodes.extended.GetClassNode;
@@ -264,6 +266,16 @@ protected static SimdStamp improveVectorStamp(SimdStamp oldVectorStamp, ValueNod
264266
ValueNode vmClass = arguments[vmClassIndex];
265267
ValueNode eClass = arguments[elementClassIndex];
266268
ValueNode length = arguments[lengthIndex];
269+
StructuredGraph graph = vmClass.graph();
270+
if (graph == null || graph.isBeforeStage(GraphState.StageFlag.VECTOR_API_EXPANSION)) {
271+
/*
272+
* Don't compute SIMD stamps before we actually start a compilation. The reason we want
273+
* to delay until actual compilation time is that the stamp may differ between native
274+
* image build time and runtime compilation time since the native image target
275+
* architecture may have different CPU features from the runtime target architecture.
276+
*/
277+
return null;
278+
}
267279
return VectorAPIUtils.stampForVectorClass(vmClass, eClass, length, providers);
268280
}
269281

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/CPUFeatureAccess.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2025, 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
@@ -29,6 +29,7 @@
2929
import org.graalvm.nativeimage.ImageSingletons;
3030

3131
import jdk.graal.compiler.api.replacements.Fold;
32+
import jdk.graal.compiler.nodes.spi.LoweringProvider;
3233
import jdk.vm.ci.code.Architecture;
3334

3435
public interface CPUFeatureAccess {
@@ -43,7 +44,7 @@ static CPUFeatureAccess singleton() {
4344
@Uninterruptible(reason = "Thread state not set up yet.")
4445
void verifyHostSupportsArchitectureEarlyOrExit();
4546

46-
void enableFeatures(Architecture architecture);
47+
void enableFeatures(Architecture architecture, LoweringProvider runtimeLowerer);
4748

4849
/**
4950
* Compute the CPU features enabled at image run time.

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64CPUFeatureAccess.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
3939
import com.oracle.svm.core.util.VMError;
4040

41+
import jdk.graal.compiler.nodes.spi.LoweringProvider;
4142
import jdk.vm.ci.aarch64.AArch64;
4243
import jdk.vm.ci.code.Architecture;
4344

@@ -85,7 +86,7 @@ public void verifyHostSupportsArchitectureEarlyOrExit() {
8586
}
8687

8788
@Override
88-
public void enableFeatures(Architecture runtimeArchitecture) {
89+
public void enableFeatures(Architecture runtimeArchitecture, LoweringProvider runtimeLowerer) {
8990
AArch64 architecture = (AArch64) runtimeArchitecture;
9091
EnumSet<AArch64.CPUFeature> features = determineHostCPUFeatures();
9192
architecture.getFeatures().addAll(features);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64CPUFeatureAccess.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
import com.oracle.svm.core.jdk.JVMCISubstitutions;
4242
import com.oracle.svm.core.util.VMError;
4343

44+
import jdk.graal.compiler.nodes.spi.LoweringProvider;
45+
import jdk.graal.compiler.vector.architecture.VectorLoweringProvider;
46+
import jdk.graal.compiler.vector.architecture.amd64.VectorAMD64;
4447
import jdk.vm.ci.amd64.AMD64;
4548
import jdk.vm.ci.amd64.AMD64Kind;
4649
import jdk.vm.ci.code.Architecture;
@@ -103,7 +106,7 @@ public static boolean canUpdateCPUFeatures() {
103106
}
104107

105108
@Override
106-
public void enableFeatures(Architecture runtimeArchitecture) {
109+
public void enableFeatures(Architecture runtimeArchitecture, LoweringProvider runtimeLowerer) {
107110
if (!canUpdateCPUFeatures()) {
108111
return;
109112
}
@@ -115,5 +118,11 @@ public void enableFeatures(Architecture runtimeArchitecture) {
115118
// update largest storable kind
116119
AMD64Kind largestStorableKind = new AMD64(features).getLargestStorableKind(AMD64.XMM);
117120
JVMCISubstitutions.updateLargestStorableKind(architecture, largestStorableKind);
121+
AMD64Kind largestStorableMaskKind = new AMD64(features).getLargestStorableKind(AMD64.MASK);
122+
JVMCISubstitutions.updateLargestStorableMaskKind(architecture, largestStorableMaskKind);
123+
124+
// update vector architecture
125+
VectorAMD64 initialVectorArch = (VectorAMD64) ((VectorLoweringProvider) runtimeLowerer).getVectorArchitecture();
126+
initialVectorArch.updateForRuntimeArchitecture((AMD64) runtimeArchitecture);
118127
}
119128
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JVMCISubstitutions.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, 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
@@ -70,7 +70,7 @@ public static Map<String, String> getSavedProperties() {
7070
@TargetClass(value = AMD64.class)
7171
final class Target_jdk_vm_ci_amd64_AMD64 {
7272
@Alias AMD64Kind largestKind;
73-
73+
@Alias AMD64Kind largestMaskKind;
7474
}
7575

7676
/** Dummy class to have a class with the file's name. */
@@ -80,4 +80,10 @@ public static void updateLargestStorableKind(AMD64 architecture, AMD64Kind large
8080
Target_jdk_vm_ci_amd64_AMD64 arch = SubstrateUtil.cast(architecture, Target_jdk_vm_ci_amd64_AMD64.class);
8181
arch.largestKind = largestStorableKind;
8282
}
83+
84+
@Platforms(Platform.AMD64.class)
85+
public static void updateLargestStorableMaskKind(AMD64 architecture, AMD64Kind largestStorableMaskKind) {
86+
Target_jdk_vm_ci_amd64_AMD64 arch = SubstrateUtil.cast(architecture, Target_jdk_vm_ci_amd64_AMD64.class);
87+
arch.largestMaskKind = largestStorableMaskKind;
88+
}
8389
}

0 commit comments

Comments
 (0)