7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
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.phases;
26
27 import org.graalvm.compiler.graph.Graph;
28 import org.graalvm.compiler.loop.LoopEx;
29 import org.graalvm.compiler.loop.LoopPolicies;
30 import org.graalvm.compiler.loop.LoopsData;
31 import org.graalvm.compiler.nodes.StructuredGraph;
32 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
33 import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener;
34 import org.graalvm.compiler.phases.tiers.PhaseContext;
35
36 public class LoopPartialUnrollPhase extends LoopPhase<LoopPolicies> {
37
38 private final CanonicalizerPhase canonicalizer;
39
40 public LoopPartialUnrollPhase(LoopPolicies policies, CanonicalizerPhase canonicalizer) {
41 super(policies);
42 this.canonicalizer = canonicalizer;
43 }
44
45 @Override
46 @SuppressWarnings("try")
47 protected void run(StructuredGraph graph, PhaseContext context) {
48 if (graph.hasLoops()) {
49 HashSetNodeEventListener listener = new HashSetNodeEventListener();
50 boolean changed = true;
51 while (changed) {
52 changed = false;
53 try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) {
54 LoopsData dataCounted = new LoopsData(graph);
55 dataCounted.detectedCountedLoops();
56 Graph.Mark mark = graph.getMark();
57 boolean prePostInserted = false;
58 for (LoopEx loop : dataCounted.countedLoops()) {
59 if (!LoopTransformations.isUnrollableLoop(loop)) {
60 continue;
61 }
62 if (getPolicies().shouldPartiallyUnroll(loop)) {
63 if (loop.loopBegin().isSimpleLoop()) {
64 // First perform the pre/post transformation and do the partial
65 // unroll when we come around again.
66 LoopTransformations.insertPrePostLoops(loop);
67 prePostInserted = true;
68 } else {
69 LoopTransformations.partialUnroll(loop);
70 }
71 changed = true;
72 }
73 }
74 dataCounted.deleteUnusedNodes();
75
76 if (!listener.getNodes().isEmpty()) {
77 canonicalizer.applyIncremental(graph, context, listener.getNodes());
78 listener.getNodes().clear();
79 }
80
81 assert !prePostInserted || checkCounted(graph, mark);
82 }
83 }
84 }
85 }
86
87 private static boolean checkCounted(StructuredGraph graph, Graph.Mark mark) {
88 LoopsData dataCounted;
89 dataCounted = new LoopsData(graph);
90 dataCounted.detectedCountedLoops();
91 for (LoopEx anyLoop : dataCounted.loops()) {
92 if (graph.isNew(mark, anyLoop.loopBegin())) {
93 assert anyLoop.isCounted() : "pre/post transformation loses counted loop " + anyLoop.loopBegin();
94 }
95 }
96 return true;
97 }
98
99 @Override
100 public boolean checkContract() {
101 return false;
|
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
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.phases;
26
27 import jdk.internal.vm.compiler.collections.EconomicMap;
28 import jdk.internal.vm.compiler.collections.Equivalence;
29 import org.graalvm.compiler.graph.Graph;
30 import org.graalvm.compiler.loop.LoopEx;
31 import org.graalvm.compiler.loop.LoopPolicies;
32 import org.graalvm.compiler.loop.LoopsData;
33 import org.graalvm.compiler.nodes.LoopBeginNode;
34 import org.graalvm.compiler.nodes.StructuredGraph;
35 import org.graalvm.compiler.nodes.extended.OpaqueNode;
36 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
37 import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
38 import org.graalvm.compiler.phases.tiers.PhaseContext;
39
40 public class LoopPartialUnrollPhase extends LoopPhase<LoopPolicies> {
41
42 private final CanonicalizerPhase canonicalizer;
43
44 public LoopPartialUnrollPhase(LoopPolicies policies, CanonicalizerPhase canonicalizer) {
45 super(policies);
46 this.canonicalizer = canonicalizer;
47 }
48
49 @Override
50 @SuppressWarnings("try")
51 protected void run(StructuredGraph graph, PhaseContext context) {
52 if (graph.hasLoops()) {
53 EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener();
54 boolean changed = true;
55 EconomicMap<LoopBeginNode, OpaqueNode> opaqueUnrolledStrides = null;
56 while (changed) {
57 changed = false;
58 try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) {
59 LoopsData dataCounted = new LoopsData(graph);
60 dataCounted.detectedCountedLoops();
61 Graph.Mark mark = graph.getMark();
62 boolean prePostInserted = false;
63 for (LoopEx loop : dataCounted.countedLoops()) {
64 if (!LoopTransformations.isUnrollableLoop(loop)) {
65 continue;
66 }
67 if (getPolicies().shouldPartiallyUnroll(loop)) {
68 if (loop.loopBegin().isSimpleLoop()) {
69 // First perform the pre/post transformation and do the partial
70 // unroll when we come around again.
71 LoopTransformations.insertPrePostLoops(loop);
72 prePostInserted = true;
73 } else {
74 if (opaqueUnrolledStrides == null) {
75 opaqueUnrolledStrides = EconomicMap.create(Equivalence.IDENTITY);
76 }
77 LoopTransformations.partialUnroll(loop, opaqueUnrolledStrides);
78 }
79 changed = true;
80 }
81 }
82 dataCounted.deleteUnusedNodes();
83
84 if (!listener.getNodes().isEmpty()) {
85 canonicalizer.applyIncremental(graph, context, listener.getNodes());
86 listener.getNodes().clear();
87 }
88
89 assert !prePostInserted || checkCounted(graph, mark);
90 }
91 }
92 if (opaqueUnrolledStrides != null) {
93 try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) {
94 for (OpaqueNode opaque : opaqueUnrolledStrides.getValues()) {
95 opaque.remove();
96 }
97 if (!listener.getNodes().isEmpty()) {
98 canonicalizer.applyIncremental(graph, context, listener.getNodes());
99 }
100 }
101 }
102 }
103 }
104
105 private static boolean checkCounted(StructuredGraph graph, Graph.Mark mark) {
106 LoopsData dataCounted;
107 dataCounted = new LoopsData(graph);
108 dataCounted.detectedCountedLoops();
109 for (LoopEx anyLoop : dataCounted.loops()) {
110 if (graph.isNew(mark, anyLoop.loopBegin())) {
111 assert anyLoop.isCounted() : "pre/post transformation loses counted loop " + anyLoop.loopBegin();
112 }
113 }
114 return true;
115 }
116
117 @Override
118 public boolean checkContract() {
119 return false;
|