src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java
changeset 58877 aec7bf35d6f5
parent 58299 6df94ce3ab2f
--- 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);
     }
 
 }