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
equal deleted inserted replaced
58876:1a8d65e71a66 58877:aec7bf35d6f5
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
    24 
    24 
    25 package org.graalvm.compiler.phases.common;
    25 package org.graalvm.compiler.phases.common;
       
    26 
       
    27 import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.CFG_SIMPLIFICATION;
       
    28 import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.GVN;
       
    29 import static org.graalvm.compiler.phases.common.CanonicalizerPhase.CanonicalizerFeature.READ_CANONICALIZATION;
       
    30 
       
    31 import java.util.EnumSet;
    26 
    32 
    27 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
    33 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
    28 import org.graalvm.compiler.core.common.type.Stamp;
    34 import org.graalvm.compiler.core.common.type.Stamp;
    29 import org.graalvm.compiler.debug.CounterKey;
    35 import org.graalvm.compiler.debug.CounterKey;
    30 import org.graalvm.compiler.debug.DebugCloseable;
    36 import org.graalvm.compiler.debug.DebugCloseable;
    64 import jdk.vm.ci.meta.ConstantReflectionProvider;
    70 import jdk.vm.ci.meta.ConstantReflectionProvider;
    65 import jdk.vm.ci.meta.MetaAccessProvider;
    71 import jdk.vm.ci.meta.MetaAccessProvider;
    66 
    72 
    67 public class CanonicalizerPhase extends BasePhase<CoreProviders> {
    73 public class CanonicalizerPhase extends BasePhase<CoreProviders> {
    68 
    74 
       
    75     public enum CanonicalizerFeature {
       
    76         READ_CANONICALIZATION,
       
    77         CFG_SIMPLIFICATION,
       
    78         GVN
       
    79     }
       
    80 
    69     private static final int MAX_ITERATION_PER_NODE = 10;
    81     private static final int MAX_ITERATION_PER_NODE = 10;
    70     private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes");
    82     private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes");
    71     private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes");
    83     private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes");
    72     private static final CounterKey COUNTER_CANONICALIZATION_CONSIDERED_NODES = DebugContext.counter("CanonicalizationConsideredNodes");
    84     private static final CounterKey COUNTER_CANONICALIZATION_CONSIDERED_NODES = DebugContext.counter("CanonicalizationConsideredNodes");
    73     private static final CounterKey COUNTER_INFER_STAMP_CALLED = DebugContext.counter("InferStampCalled");
    85     private static final CounterKey COUNTER_INFER_STAMP_CALLED = DebugContext.counter("InferStampCalled");
    74     private static final CounterKey COUNTER_STAMP_CHANGED = DebugContext.counter("StampChanged");
    86     private static final CounterKey COUNTER_STAMP_CHANGED = DebugContext.counter("StampChanged");
    75     private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes");
    87     private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes");
    76     private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits");
    88     private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits");
    77 
    89 
    78     private boolean globalValueNumber = true;
    90     private final EnumSet<CanonicalizerFeature> features;
    79     private boolean canonicalizeReads = true;
    91     private final CustomCanonicalization customCanonicalization;
    80     private boolean simplify = true;
    92     private final CustomSimplification customSimplification;
    81     private final CustomCanonicalizer customCanonicalizer;
    93 
    82 
    94     public interface CustomCanonicalization {
    83     public abstract static class CustomCanonicalizer {
    95         /**
    84 
    96          * @param node the node to be canonicalized
    85         public Node canonicalize(Node node) {
    97          * @return the same node if no action should be taken, {@code null} if the node should be
    86             return node;
    98          *         deleted, or a new node that should replace the given node
    87         }
    99          */
    88 
   100         Node canonicalize(Node node);
    89         @SuppressWarnings("unused")
   101     }
    90         public void simplify(Node node, SimplifierTool tool) {
   102 
    91         }
   103     public interface CustomSimplification {
    92     }
   104         /**
    93 
   105          * @param node the node to be simplified
    94     public CanonicalizerPhase() {
   106          * @param tool utility available during the simplification process
    95         this(null);
   107          */
    96     }
   108         void simplify(Node node, SimplifierTool tool);
    97 
   109     }
    98     public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) {
   110 
    99         this.customCanonicalizer = customCanonicalizer;
   111     protected CanonicalizerPhase(EnumSet<CanonicalizerFeature> features) {
   100     }
   112         this(null, null, features);
   101 
   113     }
   102     public void disableGVN() {
   114 
   103         globalValueNumber = false;
   115     protected CanonicalizerPhase() {
   104     }
   116         this(null, null, EnumSet.allOf(CanonicalizerFeature.class));
   105 
   117     }
   106     public void disableReadCanonicalization() {
   118 
   107         canonicalizeReads = false;
   119     protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification) {
   108     }
   120         this(customCanonicalization, customSimplification, EnumSet.allOf(CanonicalizerFeature.class));
   109 
   121     }
   110     public void disableSimplification() {
   122 
   111         simplify = false;
   123     protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification, EnumSet<CanonicalizerFeature> features) {
       
   124         this.customCanonicalization = customCanonicalization;
       
   125         this.customSimplification = customSimplification;
       
   126         this.features = features;
       
   127     }
       
   128 
       
   129     public CanonicalizerPhase copyWithCustomCanonicalization(CustomCanonicalization newCanonicalization) {
       
   130         return new CanonicalizerPhase(newCanonicalization, customSimplification, features);
       
   131     }
       
   132 
       
   133     public CanonicalizerPhase copyWithCustomSimplification(CustomSimplification newSimplification) {
       
   134         return new CanonicalizerPhase(customCanonicalization, newSimplification, features);
       
   135     }
       
   136 
       
   137     public CanonicalizerPhase copyWithoutGVN() {
       
   138         EnumSet<CanonicalizerFeature> newFeatures = EnumSet.copyOf(features);
       
   139         newFeatures.remove(GVN);
       
   140         return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures);
       
   141     }
       
   142 
       
   143     public CanonicalizerPhase copyWithoutSimplification() {
       
   144         EnumSet<CanonicalizerFeature> newFeatures = EnumSet.copyOf(features);
       
   145         newFeatures.remove(CFG_SIMPLIFICATION);
       
   146         return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures);
       
   147     }
       
   148 
       
   149     public static CanonicalizerPhase create() {
       
   150         return new CanonicalizerPhase(null, null, EnumSet.allOf(CanonicalizerFeature.class));
       
   151     }
       
   152 
       
   153     public static CanonicalizerPhase createWithoutReadCanonicalization() {
       
   154         return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(READ_CANONICALIZATION)));
       
   155     }
       
   156 
       
   157     public static CanonicalizerPhase createWithoutGVN() {
       
   158         return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(GVN)));
       
   159     }
       
   160 
       
   161     public static CanonicalizerPhase createWithoutCFGSimplification() {
       
   162         return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(CFG_SIMPLIFICATION)));
   112     }
   163     }
   113 
   164 
   114     @Override
   165     @Override
   115     public boolean checkContract() {
   166     public boolean checkContract() {
   116         /*
   167         /*
   272             NodeClass<?> nodeClass = node.getNodeClass();
   323             NodeClass<?> nodeClass = node.getNodeClass();
   273             StructuredGraph graph = (StructuredGraph) node.graph();
   324             StructuredGraph graph = (StructuredGraph) node.graph();
   274             if (tryCanonicalize(node, nodeClass)) {
   325             if (tryCanonicalize(node, nodeClass)) {
   275                 return true;
   326                 return true;
   276             }
   327             }
   277             if (globalValueNumber && tryGlobalValueNumbering(node, nodeClass)) {
   328             if (features.contains(GVN) && tryGlobalValueNumbering(node, nodeClass)) {
   278                 return true;
   329                 return true;
   279             }
   330             }
   280             if (node instanceof ValueNode) {
   331             if (node instanceof ValueNode) {
   281                 ValueNode valueNode = (ValueNode) node;
   332                 ValueNode valueNode = (ValueNode) node;
   282                 boolean improvedStamp = tryInferStamp(valueNode);
   333                 boolean improvedStamp = tryInferStamp(valueNode);
   327         }
   378         }
   328 
   379 
   329         @SuppressWarnings("try")
   380         @SuppressWarnings("try")
   330         public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
   381         public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
   331             try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) {
   382             try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) {
   332                 if (customCanonicalizer != null) {
       
   333                     Node canonical = customCanonicalizer.canonicalize(node);
       
   334                     if (performReplacement(node, canonical)) {
       
   335                         return true;
       
   336                     } else {
       
   337                         customCanonicalizer.simplify(node, tool);
       
   338                         if (node.isDeleted()) {
       
   339                             return true;
       
   340                         }
       
   341                     }
       
   342                 }
       
   343                 if (nodeClass.isCanonicalizable()) {
   383                 if (nodeClass.isCanonicalizable()) {
   344                     COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug);
   384                     COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug);
   345                     Node canonical;
   385                     Node canonical = node;
   346                     try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
   386                     try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
   347                         canonical = ((Canonicalizable) node).canonical(tool);
   387                         if (customCanonicalization != null) {
   348                         if (canonical == node && nodeClass.isCommutative()) {
   388                             canonical = customCanonicalization.canonicalize(node);
   349                             canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs();
   389                         }
       
   390                         if (canonical == node) {
       
   391                             canonical = ((Canonicalizable) node).canonical(tool);
       
   392                             if (canonical == node && nodeClass.isCommutative()) {
       
   393                                 canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs();
       
   394                             }
   350                         }
   395                         }
   351                     } catch (Throwable e) {
   396                     } catch (Throwable e) {
   352                         throw new GraalGraphError(e).addContext(node);
   397                         throw new GraalGraphError(e).addContext(node);
   353                     }
   398                     }
   354                     if (performReplacement(node, canonical)) {
   399                     if (performReplacement(node, canonical)) {
   355                         return true;
   400                         return true;
   356                     }
   401                     }
   357                 }
   402                 }
   358 
   403 
   359                 if (nodeClass.isSimplifiable() && simplify) {
   404                 if (features.contains(CFG_SIMPLIFICATION) && nodeClass.isSimplifiable()) {
   360                     debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node);
   405                     debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node);
   361                     COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug);
   406                     COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug);
   362                     node.simplify(tool);
   407                     if (customSimplification != null) {
   363                     if (node.isDeleted()) {
   408                         customSimplification.simplify(node, tool);
   364                         debug.log("Canonicalizer: simplified %s", node);
   409                     }
       
   410                     if (node.isAlive()) {
       
   411                         node.simplify(tool);
       
   412                         if (node.isDeleted()) {
       
   413                             debug.log("Canonicalizer: simplified %s", node);
       
   414                         }
   365                     }
   415                     }
   366                     return node.isDeleted();
   416                     return node.isDeleted();
   367                 }
   417                 }
   368                 return false;
   418                 return false;
   369             } catch (Throwable throwable) {
   419             } catch (Throwable throwable) {
   516                 GraphUtil.tryKillUnused(node);
   566                 GraphUtil.tryKillUnused(node);
   517             }
   567             }
   518 
   568 
   519             @Override
   569             @Override
   520             public boolean canonicalizeReads() {
   570             public boolean canonicalizeReads() {
   521                 return canonicalizeReads;
   571                 return features.contains(READ_CANONICALIZATION);
   522             }
   572             }
   523 
   573 
   524             @Override
   574             @Override
   525             public boolean allUsagesAvailable() {
   575             public boolean allUsagesAvailable() {
   526                 return true;
   576                 return true;
   547             }
   597             }
   548         }
   598         }
   549     }
   599     }
   550 
   600 
   551     public boolean getCanonicalizeReads() {
   601     public boolean getCanonicalizeReads() {
   552         return canonicalizeReads;
   602         return features.contains(READ_CANONICALIZATION);
   553     }
   603     }
   554 
   604 
   555 }
   605 }