src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java
changeset 58877 aec7bf35d6f5
parent 58299 6df94ce3ab2f
equal deleted inserted replaced
58876:1a8d65e71a66 58877:aec7bf35d6f5
     1 /*
     1 /*
     2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    33 import jdk.internal.vm.compiler.collections.EconomicMap;
    33 import jdk.internal.vm.compiler.collections.EconomicMap;
    34 import org.graalvm.compiler.core.common.RetryableBailoutException;
    34 import org.graalvm.compiler.core.common.RetryableBailoutException;
    35 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
    35 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
    36 import org.graalvm.compiler.debug.DebugContext;
    36 import org.graalvm.compiler.debug.DebugContext;
    37 import org.graalvm.compiler.graph.Graph.Mark;
    37 import org.graalvm.compiler.graph.Graph.Mark;
       
    38 import org.graalvm.compiler.graph.Graph.NodeEventScope;
    38 import org.graalvm.compiler.graph.Node;
    39 import org.graalvm.compiler.graph.Node;
    39 import org.graalvm.compiler.graph.Position;
    40 import org.graalvm.compiler.graph.Position;
       
    41 import org.graalvm.compiler.graph.spi.Simplifiable;
       
    42 import org.graalvm.compiler.graph.spi.SimplifierTool;
    40 import org.graalvm.compiler.loop.CountedLoopInfo;
    43 import org.graalvm.compiler.loop.CountedLoopInfo;
       
    44 import org.graalvm.compiler.loop.DefaultLoopPolicies;
    41 import org.graalvm.compiler.loop.InductionVariable.Direction;
    45 import org.graalvm.compiler.loop.InductionVariable.Direction;
    42 import org.graalvm.compiler.loop.LoopEx;
    46 import org.graalvm.compiler.loop.LoopEx;
    43 import org.graalvm.compiler.loop.LoopFragmentInside;
    47 import org.graalvm.compiler.loop.LoopFragmentInside;
    44 import org.graalvm.compiler.loop.LoopFragmentWhole;
    48 import org.graalvm.compiler.loop.LoopFragmentWhole;
    45 import org.graalvm.compiler.nodeinfo.InputType;
    49 import org.graalvm.compiler.nodeinfo.InputType;
    47 import org.graalvm.compiler.nodes.AbstractEndNode;
    51 import org.graalvm.compiler.nodes.AbstractEndNode;
    48 import org.graalvm.compiler.nodes.AbstractMergeNode;
    52 import org.graalvm.compiler.nodes.AbstractMergeNode;
    49 import org.graalvm.compiler.nodes.BeginNode;
    53 import org.graalvm.compiler.nodes.BeginNode;
    50 import org.graalvm.compiler.nodes.ControlSplitNode;
    54 import org.graalvm.compiler.nodes.ControlSplitNode;
    51 import org.graalvm.compiler.nodes.EndNode;
    55 import org.graalvm.compiler.nodes.EndNode;
       
    56 import org.graalvm.compiler.nodes.FixedGuardNode;
    52 import org.graalvm.compiler.nodes.FixedNode;
    57 import org.graalvm.compiler.nodes.FixedNode;
    53 import org.graalvm.compiler.nodes.FixedWithNextNode;
    58 import org.graalvm.compiler.nodes.FixedWithNextNode;
    54 import org.graalvm.compiler.nodes.IfNode;
    59 import org.graalvm.compiler.nodes.IfNode;
    55 import org.graalvm.compiler.nodes.LogicNode;
    60 import org.graalvm.compiler.nodes.LogicNode;
    56 import org.graalvm.compiler.nodes.LoopBeginNode;
    61 import org.graalvm.compiler.nodes.LoopBeginNode;
    63 import org.graalvm.compiler.nodes.calc.CompareNode;
    68 import org.graalvm.compiler.nodes.calc.CompareNode;
    64 import org.graalvm.compiler.nodes.calc.ConditionalNode;
    69 import org.graalvm.compiler.nodes.calc.ConditionalNode;
    65 import org.graalvm.compiler.nodes.extended.OpaqueNode;
    70 import org.graalvm.compiler.nodes.extended.OpaqueNode;
    66 import org.graalvm.compiler.nodes.extended.SwitchNode;
    71 import org.graalvm.compiler.nodes.extended.SwitchNode;
    67 import org.graalvm.compiler.nodes.spi.CoreProviders;
    72 import org.graalvm.compiler.nodes.spi.CoreProviders;
       
    73 import org.graalvm.compiler.nodes.util.GraphUtil;
    68 import org.graalvm.compiler.nodes.util.IntegerHelper;
    74 import org.graalvm.compiler.nodes.util.IntegerHelper;
    69 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
    75 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
       
    76 import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
    70 
    77 
    71 public abstract class LoopTransformations {
    78 public abstract class LoopTransformations {
    72 
    79 
    73     private LoopTransformations() {
    80     private LoopTransformations() {
    74         // does not need to be instantiated
    81         // does not need to be instantiated
    75     }
    82     }
    76 
    83 
    77     public static void peel(LoopEx loop) {
    84     public static void peel(LoopEx loop) {
       
    85         loop.detectCounted();
    78         loop.inside().duplicate().insertBefore(loop);
    86         loop.inside().duplicate().insertBefore(loop);
    79         loop.loopBegin().setLoopFrequency(Math.max(0.0, loop.loopBegin().loopFrequency() - 1));
    87         if (loop.isCounted()) {
    80     }
    88             // For counted loops we assume that we have an effect on the loop frequency.
    81 
    89             loop.loopBegin().setLoopFrequency(Math.max(1.0, loop.loopBegin().loopFrequency() - 1));
       
    90         }
       
    91     }
       
    92 
       
    93     @SuppressWarnings("try")
    82     public static void fullUnroll(LoopEx loop, CoreProviders context, CanonicalizerPhase canonicalizer) {
    94     public static void fullUnroll(LoopEx loop, CoreProviders context, CanonicalizerPhase canonicalizer) {
    83         // assert loop.isCounted(); //TODO (gd) strengthen : counted with known trip count
    95         // assert loop.isCounted(); //TODO (gd) strengthen : counted with known trip count
    84         LoopBeginNode loopBegin = loop.loopBegin();
    96         LoopBeginNode loopBegin = loop.loopBegin();
    85         StructuredGraph graph = loopBegin.graph();
    97         StructuredGraph graph = loopBegin.graph();
    86         int initialNodeCount = graph.getNodeCount();
    98         int initialNodeCount = graph.getNodeCount();
    87         while (!loopBegin.isDeleted()) {
    99         SimplifierTool defaultSimplifier = GraphUtil.getDefaultSimplifier(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(),
    88             Mark mark = graph.getMark();
   100                         canonicalizer.getCanonicalizeReads(), graph.getAssumptions(), graph.getOptions());
    89             peel(loop);
   101         /*
    90             canonicalizer.applyIncremental(graph, context, mark);
   102          * IMPORTANT: Canonicalizations inside the body of the remaining loop can introduce new
    91             loop.invalidateFragments();
   103          * control flow that is not automatically picked up by the control flow graph computation of
    92             if (graph.getNodeCount() > initialNodeCount + MaximumDesiredSize.getValue(graph.getOptions()) * 2) {
   104          * the original LoopEx data structure, thus we disable simplification and manually simplify
    93                 throw new RetryableBailoutException("FullUnroll : Graph seems to grow out of proportion");
   105          * conditions in the peeled iteration to simplify the exit path.
    94             }
   106          */
    95         }
   107         CanonicalizerPhase c = canonicalizer.copyWithoutSimplification();
       
   108         EconomicSetNodeEventListener l = new EconomicSetNodeEventListener();
       
   109         int peelings = 0;
       
   110         try (NodeEventScope ev = graph.trackNodeEvents(l)) {
       
   111             while (!loopBegin.isDeleted()) {
       
   112                 Mark newNodes = graph.getMark();
       
   113                 /*
       
   114                  * Mark is not enough for the canonicalization of the floating nodes in the unrolled
       
   115                  * code since pre-existing constants are not new nodes. Therefore, we canonicalize
       
   116                  * (without simplification) all floating nodes changed during peeling but only
       
   117                  * simplify new (in the peeled iteration) ones.
       
   118                  */
       
   119                 EconomicSetNodeEventListener peeledListener = new EconomicSetNodeEventListener();
       
   120                 try (NodeEventScope peeledScope = graph.trackNodeEvents(peeledListener)) {
       
   121                     LoopTransformations.peel(loop);
       
   122                 }
       
   123                 graph.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, graph, "After peeling loop %s", loop);
       
   124                 c.applyIncremental(graph, context, peeledListener.getNodes());
       
   125                 loop.invalidateFragments();
       
   126                 for (Node n : graph.getNewNodes(newNodes)) {
       
   127                     if (n.isAlive() && (n instanceof IfNode || n instanceof SwitchNode || n instanceof FixedGuardNode || n instanceof BeginNode)) {
       
   128                         Simplifiable s = (Simplifiable) n;
       
   129                         s.simplify(defaultSimplifier);
       
   130                         graph.getDebug().dump(DebugContext.VERY_DETAILED_LEVEL, graph, "After simplifying if %s", s);
       
   131                     }
       
   132                 }
       
   133                 if (graph.getNodeCount() > initialNodeCount + MaximumDesiredSize.getValue(graph.getOptions()) * 2 ||
       
   134                                 peelings > DefaultLoopPolicies.Options.FullUnrollMaxIterations.getValue(graph.getOptions())) {
       
   135                     throw new RetryableBailoutException("FullUnroll : Graph seems to grow out of proportion");
       
   136                 }
       
   137                 peelings++;
       
   138             }
       
   139         }
       
   140         // Canonicalize with the original canonicalizer to capture all simplifications
       
   141         canonicalizer.applyIncremental(graph, context, l.getNodes());
    96     }
   142     }
    97 
   143 
    98     public static void unswitch(LoopEx loop, List<ControlSplitNode> controlSplitNodeSet) {
   144     public static void unswitch(LoopEx loop, List<ControlSplitNode> controlSplitNodeSet) {
    99         ControlSplitNode firstNode = controlSplitNodeSet.iterator().next();
   145         ControlSplitNode firstNode = controlSplitNodeSet.iterator().next();
   100         LoopFragmentWhole originalLoop = loop.whole();
   146         LoopFragmentWhole originalLoop = loop.whole();
   278         cleanupMerge(postMergeNode, postLoopExitNode);
   324         cleanupMerge(postMergeNode, postLoopExitNode);
   279         cleanupMerge(mainMergeNode, mainLandingNode);
   325         cleanupMerge(mainMergeNode, mainLandingNode);
   280 
   326 
   281         // Change the preLoop to execute one iteration for now
   327         // Change the preLoop to execute one iteration for now
   282         updatePreLoopLimit(preCounted);
   328         updatePreLoopLimit(preCounted);
   283         preLoopBegin.setLoopFrequency(1);
   329         preLoopBegin.setLoopFrequency(1.0);
   284         mainLoopBegin.setLoopFrequency(Math.max(0.0, mainLoopBegin.loopFrequency() - 2));
   330         mainLoopBegin.setLoopFrequency(Math.max(1.0, mainLoopBegin.loopFrequency() - 2));
   285         postLoopBegin.setLoopFrequency(Math.max(0.0, postLoopBegin.loopFrequency() - 1));
   331         postLoopBegin.setLoopFrequency(Math.max(1.0, postLoopBegin.loopFrequency() - 1));
   286 
   332 
   287         // The pre and post loops don't require safepoints at all
   333         // The pre and post loops don't require safepoints at all
   288         for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) {
   334         for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) {
   289             graph.removeFixed(safepoint);
   335             graph.removeFixed(safepoint);
   290         }
   336         }