16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.loop;
26
27 import static org.graalvm.compiler.core.common.GraalOptions.LoopMaxUnswitch;
28 import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
29 import static org.graalvm.compiler.core.common.GraalOptions.MinimumPeelProbability;
30
31 import java.util.List;
32
33 import org.graalvm.compiler.core.common.util.UnsignedLong;
34 import org.graalvm.compiler.debug.CounterKey;
35 import org.graalvm.compiler.debug.DebugContext;
36 import org.graalvm.compiler.graph.Node;
37 import org.graalvm.compiler.graph.NodeBitMap;
38 import org.graalvm.compiler.nodes.AbstractBeginNode;
39 import org.graalvm.compiler.nodes.ControlSplitNode;
40 import org.graalvm.compiler.nodes.DeoptimizeNode;
41 import org.graalvm.compiler.nodes.FixedNode;
42 import org.graalvm.compiler.nodes.FixedWithNextNode;
43 import org.graalvm.compiler.nodes.InvokeNode;
44 import org.graalvm.compiler.nodes.LoopBeginNode;
45 import org.graalvm.compiler.nodes.MergeNode;
46 import org.graalvm.compiler.nodes.StructuredGraph;
47 import org.graalvm.compiler.nodes.VirtualState;
48 import org.graalvm.compiler.nodes.VirtualState.VirtualClosure;
49 import org.graalvm.compiler.nodes.cfg.Block;
50 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
51 import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
52 import org.graalvm.compiler.nodes.java.TypeSwitchNode;
53 import org.graalvm.compiler.options.Option;
54 import org.graalvm.compiler.options.OptionKey;
55 import org.graalvm.compiler.options.OptionType;
56 import org.graalvm.compiler.options.OptionValues;
57
58 import jdk.vm.ci.meta.MetaAccessProvider;
59
60 public class DefaultLoopPolicies implements LoopPolicies {
61
62 public static class Options {
63 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchMaxIncrease = new OptionKey<>(500);
64 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchTrivial = new OptionKey<>(10);
65 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Double> LoopUnswitchFrequencyBoost = new OptionKey<>(10.0);
66
67 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxNodes = new OptionKey<>(300);
68 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxIterations = new OptionKey<>(600);
69 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactFullUnrollMaxNodes = new OptionKey<>(1200);
70 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactPartialUnrollMaxNodes = new OptionKey<>(200);
71
72 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> UnrollMaxIterations = new OptionKey<>(16);
73 }
74
75 @Override
76 public boolean shouldPeel(LoopEx loop, ControlFlowGraph cfg, MetaAccessProvider metaAccess) {
77 LoopBeginNode loopBegin = loop.loopBegin();
78 double entryProbability = cfg.blockFor(loopBegin.forwardEnd()).getRelativeFrequency();
79 OptionValues options = cfg.graph.getOptions();
80 if (entryProbability > MinimumPeelProbability.getValue(options) && loop.size() + loopBegin.graph().getNodeCount() < MaximumDesiredSize.getValue(options)) {
81 // check whether we're allowed to peel this loop
82 return loop.canDuplicateLoop();
83 } else {
84 return false;
85 }
86 }
87
88 @Override
89 public boolean shouldFullUnroll(LoopEx loop) {
90 if (!loop.isCounted() || !loop.counted().isConstantMaxTripCount()) {
91 return false;
92 }
93 OptionValues options = loop.entryPoint().getOptions();
94 CountedLoopInfo counted = loop.counted();
95 UnsignedLong maxTrips = counted.constantMaxTripCount();
96 if (maxTrips.equals(0)) {
97 return loop.canDuplicateLoop();
98 }
99 int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? Options.ExactFullUnrollMaxNodes.getValue(options) : Options.FullUnrollMaxNodes.getValue(options);
100 maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount()));
101 int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
102 /* @formatter:off
103 * The check below should not throw ArithmeticException because:
104 * maxTrips is guaranteed to be >= 1 by the check above
105 * - maxTrips * size can not overfow because:
106 * - maxTrips <= FullUnrollMaxIterations <= Integer.MAX_VALUE
107 * - 1 <= size <= Integer.MAX_VALUE
108 * @formatter:on
109 */
110 if (maxTrips.isLessOrEqualTo(Options.FullUnrollMaxIterations.getValue(options)) && maxTrips.minus(1).times(size).isLessOrEqualTo(maxNodes)) {
111 // check whether we're allowed to unroll this loop
112 return loop.canDuplicateLoop();
113 } else {
114 return false;
115 }
116 }
117
118 @Override
119 public boolean shouldPartiallyUnroll(LoopEx loop) {
120 LoopBeginNode loopBegin = loop.loopBegin();
121 if (!loop.isCounted()) {
122 loopBegin.getDebug().log(DebugContext.VERBOSE_LEVEL, "shouldPartiallyUnroll %s isn't counted", loopBegin);
123 return false;
124 }
125 OptionValues options = loop.entryPoint().getOptions();
126 int maxNodes = Options.ExactPartialUnrollMaxNodes.getValue(options);
127 maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount()));
128 int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
129 int unrollFactor = loopBegin.getUnrollFactor();
130 if (unrollFactor == 1) {
223 FixedNode current = (FixedNode) succ;
224 while (current instanceof FixedWithNextNode) {
225 current = ((FixedWithNextNode) current).next();
226 }
227 if (current instanceof DeoptimizeNode) {
228 copies--;
229 }
230 }
231 actualDiff = actualDiff * copies;
232 }
233
234 debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff,
235 loopFrequency, phis, actualDiff <= maxDiff);
236 if (actualDiff <= maxDiff) {
237 // check whether we're allowed to unswitch this loop
238 return loop.canDuplicateLoop();
239 } else {
240 return false;
241 }
242 }
243
244 }
|
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25 package org.graalvm.compiler.loop;
26
27 import static org.graalvm.compiler.core.common.GraalOptions.LoopMaxUnswitch;
28 import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
29 import static org.graalvm.compiler.core.common.GraalOptions.MinimumPeelProbability;
30
31 import java.util.List;
32
33 import org.graalvm.compiler.core.common.util.UnsignedLong;
34 import org.graalvm.compiler.debug.CounterKey;
35 import org.graalvm.compiler.debug.DebugContext;
36 import org.graalvm.compiler.debug.GraalError;
37 import org.graalvm.compiler.graph.Node;
38 import org.graalvm.compiler.graph.NodeBitMap;
39 import org.graalvm.compiler.nodes.AbstractBeginNode;
40 import org.graalvm.compiler.nodes.ControlSplitNode;
41 import org.graalvm.compiler.nodes.DeoptimizeNode;
42 import org.graalvm.compiler.nodes.FixedNode;
43 import org.graalvm.compiler.nodes.FixedWithNextNode;
44 import org.graalvm.compiler.nodes.InvokeNode;
45 import org.graalvm.compiler.nodes.LoopBeginNode;
46 import org.graalvm.compiler.nodes.MergeNode;
47 import org.graalvm.compiler.nodes.StructuredGraph;
48 import org.graalvm.compiler.nodes.VirtualState;
49 import org.graalvm.compiler.nodes.VirtualState.VirtualClosure;
50 import org.graalvm.compiler.nodes.calc.CompareNode;
51 import org.graalvm.compiler.nodes.cfg.Block;
52 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
53 import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
54 import org.graalvm.compiler.nodes.java.TypeSwitchNode;
55 import org.graalvm.compiler.options.Option;
56 import org.graalvm.compiler.options.OptionKey;
57 import org.graalvm.compiler.options.OptionType;
58 import org.graalvm.compiler.options.OptionValues;
59
60 import jdk.vm.ci.meta.MetaAccessProvider;
61
62 public class DefaultLoopPolicies implements LoopPolicies {
63
64 public static class Options {
65 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchMaxIncrease = new OptionKey<>(500);
66 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchTrivial = new OptionKey<>(10);
67 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Double> LoopUnswitchFrequencyBoost = new OptionKey<>(10.0);
68
69 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxNodes = new OptionKey<>(400);
70 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollConstantCompareBoost = new OptionKey<>(15);
71 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxIterations = new OptionKey<>(600);
72 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactFullUnrollMaxNodes = new OptionKey<>(800);
73 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactPartialUnrollMaxNodes = new OptionKey<>(200);
74
75 @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> UnrollMaxIterations = new OptionKey<>(16);
76 }
77
78 @Override
79 public boolean shouldPeel(LoopEx loop, ControlFlowGraph cfg, MetaAccessProvider metaAccess) {
80 LoopBeginNode loopBegin = loop.loopBegin();
81 double entryProbability = cfg.blockFor(loopBegin.forwardEnd()).getRelativeFrequency();
82 OptionValues options = cfg.graph.getOptions();
83 if (entryProbability > MinimumPeelProbability.getValue(options) && loop.size() + loopBegin.graph().getNodeCount() < MaximumDesiredSize.getValue(options)) {
84 // check whether we're allowed to peel this loop
85 return loop.canDuplicateLoop();
86 } else {
87 return false;
88 }
89 }
90
91 @Override
92 public boolean shouldFullUnroll(LoopEx loop) {
93 if (!loop.isCounted() || !loop.counted().isConstantMaxTripCount() || !loop.counted().counterNeverOverflows()) {
94 return false;
95 }
96 OptionValues options = loop.entryPoint().getOptions();
97 CountedLoopInfo counted = loop.counted();
98 UnsignedLong maxTrips = counted.constantMaxTripCount();
99 if (maxTrips.equals(0)) {
100 return loop.canDuplicateLoop();
101 }
102 if (maxTrips.isGreaterThan(Options.FullUnrollMaxIterations.getValue(options))) {
103 return false;
104 }
105 int globalMax = MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount();
106 if (globalMax <= 0) {
107 return false;
108 }
109 int maxNodes = counted.isExactTripCount() ? Options.ExactFullUnrollMaxNodes.getValue(options) : Options.FullUnrollMaxNodes.getValue(options);
110 for (Node usage : counted.getCounter().valueNode().usages()) {
111 if (usage instanceof CompareNode) {
112 CompareNode compare = (CompareNode) usage;
113 if (compare.getY().isConstant()) {
114 maxNodes += Options.FullUnrollConstantCompareBoost.getValue(options);
115 }
116 }
117 }
118 maxNodes = Math.min(maxNodes, globalMax);
119 int size = loop.inside().nodes().count();
120 size -= 2; // remove the counted if and its non-exit begin
121 size -= loop.loopBegin().loopEnds().count();
122 GraalError.guarantee(size >= 0, "Wrong size");
123 /* @formatter:off
124 * The check below should not throw ArithmeticException because:
125 * maxTrips is guaranteed to be >= 1 by the check above
126 * - maxTrips * size can not overfow because:
127 * - maxTrips <= FullUnrollMaxIterations <= Integer.MAX_VALUE
128 * - 1 <= size <= Integer.MAX_VALUE
129 * @formatter:on
130 */
131 if (maxTrips.minus(1).times(size).isLessOrEqualTo(maxNodes)) {
132 // check whether we're allowed to unroll this loop
133 return loop.canDuplicateLoop();
134 } else {
135 return false;
136 }
137 }
138
139 @Override
140 public boolean shouldPartiallyUnroll(LoopEx loop) {
141 LoopBeginNode loopBegin = loop.loopBegin();
142 if (!loop.isCounted()) {
143 loopBegin.getDebug().log(DebugContext.VERBOSE_LEVEL, "shouldPartiallyUnroll %s isn't counted", loopBegin);
144 return false;
145 }
146 OptionValues options = loop.entryPoint().getOptions();
147 int maxNodes = Options.ExactPartialUnrollMaxNodes.getValue(options);
148 maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount()));
149 int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
150 int unrollFactor = loopBegin.getUnrollFactor();
151 if (unrollFactor == 1) {
244 FixedNode current = (FixedNode) succ;
245 while (current instanceof FixedWithNextNode) {
246 current = ((FixedWithNextNode) current).next();
247 }
248 if (current instanceof DeoptimizeNode) {
249 copies--;
250 }
251 }
252 actualDiff = actualDiff * copies;
253 }
254
255 debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff,
256 loopFrequency, phis, actualDiff <= maxDiff);
257 if (actualDiff <= maxDiff) {
258 // check whether we're allowed to unswitch this loop
259 return loop.canDuplicateLoop();
260 } else {
261 return false;
262 }
263 }
264 }
|