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 } |