--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Oct 31 14:23:06 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Oct 31 16:54:16 2019 -0700
@@ -24,6 +24,12 @@
package org.graalvm.compiler.phases.common;
+import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.CFG_SIMPLIFICATION;
+import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.GVN;
+import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.READ_CANONICALIZATION;
+
+import java.util.EnumSet;
+
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.CounterKey;
@@ -66,6 +72,12 @@
public class CanonicalizerPhase extends BasePhase<CoreProviders> {
+ public enum CanonicalizerFeature {
+ READ_CANONICALIZATION,
+ CFG_SIMPLIFICATION,
+ GVN
+ }
+
private static final int MAX_ITERATION_PER_NODE = 10;
private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes");
private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes");
@@ -75,40 +87,79 @@
private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes");
private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits");
- private boolean globalValueNumber = true;
- private boolean canonicalizeReads = true;
- private boolean simplify = true;
- private final CustomCanonicalizer customCanonicalizer;
+ private final EnumSet<CanonicalizerFeature> features;
+ private final CustomCanonicalization customCanonicalization;
+ private final CustomSimplification customSimplification;
- public abstract static class CustomCanonicalizer {
+ public interface CustomCanonicalization {
+ /**
+ * @param node the node to be canonicalized
+ * @return the same node if no action should be taken, {@code null} if the node should be
+ * deleted, or a new node that should replace the given node
+ */
+ Node canonicalize(Node node);
+ }
- public Node canonicalize(Node node) {
- return node;
- }
+ public interface CustomSimplification {
+ /**
+ * @param node the node to be simplified
+ * @param tool utility available during the simplification process
+ */
+ void simplify(Node node, SimplifierTool tool);
+ }
- @SuppressWarnings("unused")
- public void simplify(Node node, SimplifierTool tool) {
- }
+ protected CanonicalizerPhase(EnumSet<CanonicalizerFeature> features) {
+ this(null, null, features);
+ }
+
+ protected CanonicalizerPhase() {
+ this(null, null, EnumSet.allOf(CanonicalizerFeature.class));
+ }
+
+ protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification) {
+ this(customCanonicalization, customSimplification, EnumSet.allOf(CanonicalizerFeature.class));
}
- public CanonicalizerPhase() {
- this(null);
+ protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification, EnumSet<CanonicalizerFeature> features) {
+ this.customCanonicalization = customCanonicalization;
+ this.customSimplification = customSimplification;
+ this.features = features;
}
- public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) {
- this.customCanonicalizer = customCanonicalizer;
+ public CanonicalizerPhase copyWithCustomCanonicalization(CustomCanonicalization newCanonicalization) {
+ return new CanonicalizerPhase(newCanonicalization, customSimplification, features);
+ }
+
+ public CanonicalizerPhase copyWithCustomSimplification(CustomSimplification newSimplification) {
+ return new CanonicalizerPhase(customCanonicalization, newSimplification, features);
+ }
+
+ public CanonicalizerPhase copyWithoutGVN() {
+ EnumSet<CanonicalizerFeature> newFeatures = EnumSet.copyOf(features);
+ newFeatures.remove(GVN);
+ return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures);
}
- public void disableGVN() {
- globalValueNumber = false;
+ public CanonicalizerPhase copyWithoutSimplification() {
+ EnumSet<CanonicalizerFeature> newFeatures = EnumSet.copyOf(features);
+ newFeatures.remove(CFG_SIMPLIFICATION);
+ return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures);
+ }
+
+ public static CanonicalizerPhase create() {
+ return new CanonicalizerPhase(null, null, EnumSet.allOf(CanonicalizerFeature.class));
}
- public void disableReadCanonicalization() {
- canonicalizeReads = false;
+ public static CanonicalizerPhase createWithoutReadCanonicalization() {
+ return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(READ_CANONICALIZATION)));
}
- public void disableSimplification() {
- simplify = false;
+ public static CanonicalizerPhase createWithoutGVN() {
+ return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(GVN)));
+ }
+
+ public static CanonicalizerPhase createWithoutCFGSimplification() {
+ return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(CFG_SIMPLIFICATION)));
}
@Override
@@ -274,7 +325,7 @@
if (tryCanonicalize(node, nodeClass)) {
return true;
}
- if (globalValueNumber && tryGlobalValueNumbering(node, nodeClass)) {
+ if (features.contains(GVN) && tryGlobalValueNumbering(node, nodeClass)) {
return true;
}
if (node instanceof ValueNode) {
@@ -329,24 +380,18 @@
@SuppressWarnings("try")
public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) {
- if (customCanonicalizer != null) {
- Node canonical = customCanonicalizer.canonicalize(node);
- if (performReplacement(node, canonical)) {
- return true;
- } else {
- customCanonicalizer.simplify(node, tool);
- if (node.isDeleted()) {
- return true;
- }
- }
- }
if (nodeClass.isCanonicalizable()) {
COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug);
- Node canonical;
+ Node canonical = node;
try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
- canonical = ((Canonicalizable) node).canonical(tool);
- if (canonical == node && nodeClass.isCommutative()) {
- canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs();
+ if (customCanonicalization != null) {
+ canonical = customCanonicalization.canonicalize(node);
+ }
+ if (canonical == node) {
+ canonical = ((Canonicalizable) node).canonical(tool);
+ if (canonical == node && nodeClass.isCommutative()) {
+ canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs();
+ }
}
} catch (Throwable e) {
throw new GraalGraphError(e).addContext(node);
@@ -356,12 +401,17 @@
}
}
- if (nodeClass.isSimplifiable() && simplify) {
+ if (features.contains(CFG_SIMPLIFICATION) && nodeClass.isSimplifiable()) {
debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node);
COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug);
- node.simplify(tool);
- if (node.isDeleted()) {
- debug.log("Canonicalizer: simplified %s", node);
+ if (customSimplification != null) {
+ customSimplification.simplify(node, tool);
+ }
+ if (node.isAlive()) {
+ node.simplify(tool);
+ if (node.isDeleted()) {
+ debug.log("Canonicalizer: simplified %s", node);
+ }
}
return node.isDeleted();
}
@@ -518,7 +568,7 @@
@Override
public boolean canonicalizeReads() {
- return canonicalizeReads;
+ return features.contains(READ_CANONICALIZATION);
}
@Override
@@ -549,7 +599,7 @@
}
public boolean getCanonicalizeReads() {
- return canonicalizeReads;
+ return features.contains(READ_CANONICALIZATION);
}
}