Skip to content

Commit c9658c9

Browse files
committed
[GR-43361] [GR-50205] Whole-Program Sparse Conditional Constant Propagation
PullRequest: graal/18609
2 parents ee62612 + 9a73d5d commit c9658c9

File tree

52 files changed

+2295
-321
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2295
-321
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AnalysisObjectScanningObserver.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@ public AnalysisObjectScanningObserver(BigBang bb) {
4444

4545
@Override
4646
public boolean forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue, ScanReason reason) {
47-
if (!field.isWritten()) {
48-
return field.registerAsWritten(reason);
49-
}
47+
var changed = false;
5048
if (fieldValue.isNonNull()) {
5149
FieldTypeFlow fieldTypeFlow = getFieldTypeFlow(field, receiver);
52-
return fieldTypeFlow.addState(getAnalysis(), TypeState.anyPrimitiveState());
50+
changed = fieldTypeFlow.addState(getAnalysis(), TypeState.anyPrimitiveState());
5351
}
54-
return false;
52+
if (!field.isWritten()) {
53+
changed |= field.registerAsWritten(reason);
54+
}
55+
return changed;
5556
}
5657

5758
@Override

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java

+22-2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ public abstract class PointsToAnalysis extends AbstractAnalysisEngine {
102102
* immediately represented as {@link com.oracle.graal.pointsto.flow.AnyPrimitiveSourceTypeFlow}.
103103
*/
104104
private final boolean trackPrimitiveValues;
105+
private final AnalysisType longType;
106+
private final AnalysisType voidType;
107+
private final boolean usePredicates;
105108
private AnyPrimitiveSourceTypeFlow anyPrimitiveSourceTypeFlow;
106109

107110
protected final boolean trackTypeFlowInputs;
@@ -121,10 +124,15 @@ public PointsToAnalysis(OptionValues options, AnalysisUniverse universe, HostVM
121124
ClassInclusionPolicy classInclusionPolicy) {
122125
super(options, universe, hostVM, metaAccess, snippetReflectionProvider, constantReflectionProvider, wordTypes, unsupportedFeatures, debugContext, timerCollection, classInclusionPolicy);
123126
this.typeFlowTimer = timerCollection.createTimer("(typeflow)");
124-
this.trackPrimitiveValues = PointstoOptions.TrackPrimitiveValues.getValue(options);
125-
this.anyPrimitiveSourceTypeFlow = new AnyPrimitiveSourceTypeFlow(null, null);
126127

127128
this.objectType = metaAccess.lookupJavaType(Object.class);
129+
this.longType = metaAccess.lookupJavaType(long.class);
130+
this.voidType = metaAccess.lookupJavaType(void.class);
131+
132+
this.trackPrimitiveValues = PointstoOptions.TrackPrimitiveValues.getValue(options);
133+
this.usePredicates = PointstoOptions.UsePredicates.getValue(options);
134+
this.anyPrimitiveSourceTypeFlow = new AnyPrimitiveSourceTypeFlow(null, longType);
135+
this.anyPrimitiveSourceTypeFlow.enableFlow(null);
128136
/*
129137
* Make sure the all-instantiated type flow is created early. We do not have any
130138
* instantiated types yet, so the state is empty at first.
@@ -270,6 +278,14 @@ public AnalysisType getObjectType() {
270278
return universe.objectType();
271279
}
272280

281+
public AnalysisType getLongType() {
282+
return longType;
283+
}
284+
285+
public AnalysisType getVoidType() {
286+
return voidType;
287+
}
288+
273289
public AnalysisType getObjectArrayType() {
274290
return metaAccess.lookupJavaType(Object[].class);
275291
}
@@ -538,6 +554,10 @@ public boolean trackPrimitiveValues() {
538554
return trackPrimitiveValues;
539555
}
540556

557+
public boolean usePredicates() {
558+
return usePredicates;
559+
}
560+
541561
public interface TypeFlowRunnable extends DebugContextRunnable {
542562
TypeFlow<?> getTypeFlow();
543563
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/PointstoOptions.java

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public class PointstoOptions {
3939
@Option(help = "Track primitive values using the infrastructure of points-to analysis.")//
4040
public static final OptionKey<Boolean> TrackPrimitiveValues = new OptionKey<>(false);
4141

42+
@Option(help = "Use predicates in points-to analysis.")//
43+
public static final OptionKey<Boolean> UsePredicates = new OptionKey<>(false);
44+
4245
@Option(help = "Use experimental Reachability Analysis instead of points-to.")//
4346
public static final OptionKey<Boolean> UseExperimentalReachabilityAnalysis = new OptionKey<>(false);
4447

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AbstractSpecialInvokeTypeFlow.java

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ protected AbstractSpecialInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph me
4545
super(bb, methodFlows, original);
4646
}
4747

48+
@Override
49+
protected void onFlowEnabled(PointsToAnalysis bb) {
50+
bb.postTask(() -> onObservedUpdate(bb));
51+
}
52+
4853
@Override
4954
public boolean addState(PointsToAnalysis bb, TypeState add, boolean postFlow) {
5055
throw AnalysisError.shouldNotReachHere("The SpecialInvokeTypeFlow should not be updated directly.");

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AbstractStaticInvokeTypeFlow.java

-11
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,6 @@ protected AbstractStaticInvokeTypeFlow(PointsToAnalysis bb, MethodFlowsGraph met
4141
super(bb, methodFlows, original);
4242
}
4343

44-
@Override
45-
public void initFlow(PointsToAnalysis bb) {
46-
/* Trigger the update for static invokes, there is no receiver to trigger it. */
47-
bb.postFlow(this);
48-
}
49-
50-
@Override
51-
public boolean needsInitialization() {
52-
return true;
53-
}
54-
5544
@Override
5645
public String toString() {
5746
return "StaticInvoke<" + targetMethod.format("%h.%n") + ">" + ":" + getState();

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AbstractVirtualInvokeTypeFlow.java

+5
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public final boolean isDirectInvoke() {
8787
return false;
8888
}
8989

90+
@Override
91+
protected void onFlowEnabled(PointsToAnalysis bb) {
92+
bb.postTask(() -> onObservedUpdate(bb));
93+
}
94+
9095
@Override
9196
public boolean addState(PointsToAnalysis bb, TypeState add, boolean postFlow) {
9297
throw AnalysisError.shouldNotReachHere("The VirtualInvokeTypeFlow should not be updated directly.");

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AllInstantiatedTypeFlow.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
* of the all assignable types. This flow is used for uses that need to be notified when a sub-type
3333
* of a specific type is marked as instantiated, e.g., a saturated field access type flow needs to
3434
* be notified when a sub-type of its declared type is marked as instantiated.
35-
*
35+
* <p>
3636
* Note this flow should only be instantiated within AnalysisType. When needed, this flow should be
3737
* retrieved via calling {@link AnalysisType#getTypeFlow}.
3838
*/
39-
public final class AllInstantiatedTypeFlow extends TypeFlow<AnalysisType> {
39+
public final class AllInstantiatedTypeFlow extends TypeFlow<AnalysisType> implements GlobalFlow {
4040

4141
public AllInstantiatedTypeFlow(AnalysisType declaredType, boolean canBeNull) {
4242
super(declaredType, declaredType, canBeNull);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2024, 2024, 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 com.oracle.graal.pointsto.flow;
26+
27+
import com.oracle.graal.pointsto.typestate.TypeState;
28+
29+
import jdk.vm.ci.code.BytecodePosition;
30+
31+
/**
32+
* Always-enabled global flow that is used as a predicate before any other suitable flow is
33+
* available.
34+
*/
35+
public class AlwaysEnabledPredicateFlow extends TypeFlow<BytecodePosition> implements GlobalFlow {
36+
37+
public AlwaysEnabledPredicateFlow() {
38+
/* We use any primitive state here just to make sure the state is always non-empty. */
39+
super(TypeState.anyPrimitiveState());
40+
}
41+
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/AnyPrimitiveSourceTypeFlow.java

+30-1
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,47 @@
2424
*/
2525
package com.oracle.graal.pointsto.flow;
2626

27+
import com.oracle.graal.pointsto.PointsToAnalysis;
2728
import com.oracle.graal.pointsto.meta.AnalysisType;
2829
import com.oracle.graal.pointsto.typestate.TypeState;
2930

3031
import jdk.vm.ci.code.BytecodePosition;
3132

3233
/**
3334
* Produces AnyPrimitive state that leads to immediate saturation of all uses. Used to represent any
34-
* operation that is not modeled by the analysis.
35+
* operation on primitives that is not explicitly modeled by the analysis.
36+
* </p>
37+
* This flow can be either global (source == null) or local (source != null).
3538
*/
3639
public final class AnyPrimitiveSourceTypeFlow extends TypeFlow<BytecodePosition> implements PrimitiveFlow {
3740

3841
public AnyPrimitiveSourceTypeFlow(BytecodePosition source, AnalysisType type) {
3942
super(source, type, TypeState.anyPrimitiveState());
4043
}
44+
45+
private AnyPrimitiveSourceTypeFlow(MethodFlowsGraph methodFlows, AnyPrimitiveSourceTypeFlow original) {
46+
super(original, methodFlows, TypeState.anyPrimitiveState());
47+
}
48+
49+
@Override
50+
public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) {
51+
assert isLocal() : "Global flow should never be cloned: " + this;
52+
return new AnyPrimitiveSourceTypeFlow(methodFlows, this);
53+
}
54+
55+
private boolean isLocal() {
56+
return source != null;
57+
}
58+
59+
@Override
60+
public boolean canSaturate() {
61+
/*
62+
* AnyPrimitiveSourceTypeFlow can be used as a global flow that should always propagate
63+
* values. The global version can be identified be having source == null, and it should
64+
* never saturate.
65+
*
66+
* The local versions of this flow have a concrete bytecode position and can saturate.
67+
*/
68+
return isLocal();
69+
}
4170
}

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/ArrayElementsTypeFlow.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
/**
3535
* This class is used to model the elements type flow for array objects.
3636
*/
37-
public class ArrayElementsTypeFlow extends TypeFlow<AnalysisType> {
37+
public class ArrayElementsTypeFlow extends TypeFlow<AnalysisType> implements GlobalFlow {
3838

3939
/** The array object. */
4040
private final AnalysisObject object;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2024, 2024, 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 com.oracle.graal.pointsto.flow;
26+
27+
import com.oracle.graal.pointsto.PointsToAnalysis;
28+
import com.oracle.graal.pointsto.meta.AnalysisType;
29+
import com.oracle.graal.pointsto.typestate.TypeState;
30+
import com.oracle.graal.pointsto.util.AnalysisError;
31+
32+
import jdk.vm.ci.code.BytecodePosition;
33+
34+
/**
35+
* This flow represents a boolean check, i.e. a null check, type check, or primitive check that
36+
* converts its inputs into boolean values. Instances of this class are used as conditions for
37+
* {@link ConditionalFlow}.
38+
*/
39+
public abstract class BooleanCheckTypeFlow extends TypeFlow<BytecodePosition> {
40+
41+
public BooleanCheckTypeFlow(BytecodePosition position, AnalysisType declaredType) {
42+
super(position, declaredType);
43+
}
44+
45+
protected BooleanCheckTypeFlow(BooleanCheckTypeFlow original, MethodFlowsGraph methodFlows) {
46+
super(original, methodFlows);
47+
}
48+
49+
protected static TypeState convertToBoolean(boolean canBeTrue, boolean canBeFalse) {
50+
if (canBeTrue && canBeFalse) {
51+
return TypeState.anyPrimitiveState();
52+
} else if (canBeTrue) {
53+
return TypeState.forBoolean(true);
54+
} else if (canBeFalse) {
55+
return TypeState.forBoolean(false);
56+
}
57+
return TypeState.forEmpty();
58+
}
59+
60+
protected static TypeState convertToBoolean(TypeState trueState, TypeState falseState) {
61+
return convertToBoolean(trueState.isNotEmpty(), falseState.isNotEmpty());
62+
}
63+
64+
@Override
65+
public void addPredicated(PointsToAnalysis bb, TypeFlow<?> predicatedFlow) {
66+
AnalysisError.shouldNotReachHere(getClass() + " shouldn't act as a predicate.");
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2023, 2023, 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 com.oracle.graal.pointsto.flow;
26+
27+
import com.oracle.graal.pointsto.PointsToAnalysis;
28+
import com.oracle.graal.pointsto.meta.AnalysisType;
29+
import com.oracle.graal.pointsto.typestate.TypeState;
30+
31+
import jdk.vm.ci.code.BytecodePosition;
32+
33+
/**
34+
* This flow represents a type check used by {@link ConditionalFlow}.
35+
*/
36+
public class BooleanInstanceOfCheckTypeFlow extends BooleanCheckTypeFlow {
37+
private final AnalysisType checkedType;
38+
private final boolean isExact;
39+
private final boolean includeNull;
40+
41+
public BooleanInstanceOfCheckTypeFlow(BytecodePosition position, AnalysisType checkedType, boolean isExact, boolean includeNull, AnalysisType longType) {
42+
super(position, longType);
43+
this.checkedType = checkedType;
44+
this.isExact = isExact;
45+
this.includeNull = includeNull;
46+
}
47+
48+
private BooleanInstanceOfCheckTypeFlow(MethodFlowsGraph methodFlows, BooleanInstanceOfCheckTypeFlow original) {
49+
super(original, methodFlows);
50+
this.checkedType = original.checkedType;
51+
this.isExact = original.isExact;
52+
this.includeNull = original.includeNull;
53+
}
54+
55+
@Override
56+
public TypeFlow<BytecodePosition> copy(PointsToAnalysis bb, MethodFlowsGraph methodFlows) {
57+
return new BooleanInstanceOfCheckTypeFlow(methodFlows, this);
58+
}
59+
60+
@Override
61+
public TypeState filter(PointsToAnalysis bb, TypeState update) {
62+
TypeState canBeTrue;
63+
TypeState canBeFalse;
64+
if (isExact) {
65+
canBeTrue = TypeState.forIntersection(bb, update, TypeState.forExactType(bb, checkedType, includeNull));
66+
canBeFalse = TypeState.forSubtraction(bb, update, TypeState.forExactType(bb, checkedType, includeNull));
67+
} else {
68+
canBeTrue = TypeState.forIntersection(bb, update, checkedType.getAssignableTypes(includeNull));
69+
canBeFalse = TypeState.forSubtraction(bb, update, checkedType.getAssignableTypes(includeNull));
70+
}
71+
return convertToBoolean(canBeTrue, canBeFalse);
72+
}
73+
}

0 commit comments

Comments
 (0)