1 /* |
1 /* |
2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2013, 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. |
22 */ |
22 */ |
23 |
23 |
24 |
24 |
25 package org.graalvm.compiler.phases.common; |
25 package org.graalvm.compiler.phases.common; |
26 |
26 |
27 import org.graalvm.compiler.core.common.cfg.Loop; |
|
28 import org.graalvm.compiler.debug.DebugCloseable; |
27 import org.graalvm.compiler.debug.DebugCloseable; |
29 import org.graalvm.compiler.debug.DebugContext; |
28 import org.graalvm.compiler.debug.DebugContext; |
30 import org.graalvm.compiler.graph.Node; |
29 import org.graalvm.compiler.graph.Node; |
31 import org.graalvm.compiler.nodes.AbstractBeginNode; |
30 import org.graalvm.compiler.nodes.AbstractBeginNode; |
32 import org.graalvm.compiler.nodes.BeginNode; |
31 import org.graalvm.compiler.nodes.BeginNode; |
33 import org.graalvm.compiler.nodes.DeoptimizeNode; |
32 import org.graalvm.compiler.nodes.DeoptimizeNode; |
34 import org.graalvm.compiler.nodes.FixedWithNextNode; |
33 import org.graalvm.compiler.nodes.FixedWithNextNode; |
35 import org.graalvm.compiler.nodes.GuardNode; |
34 import org.graalvm.compiler.nodes.GuardNode; |
36 import org.graalvm.compiler.nodes.IfNode; |
35 import org.graalvm.compiler.nodes.IfNode; |
37 import org.graalvm.compiler.nodes.LoopBeginNode; |
|
38 import org.graalvm.compiler.nodes.LoopExitNode; |
|
39 import org.graalvm.compiler.nodes.StructuredGraph; |
36 import org.graalvm.compiler.nodes.StructuredGraph; |
40 import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; |
37 import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; |
41 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; |
38 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; |
42 import org.graalvm.compiler.nodes.cfg.Block; |
39 import org.graalvm.compiler.nodes.cfg.Block; |
43 import org.graalvm.compiler.phases.BasePhase; |
40 import org.graalvm.compiler.phases.BasePhase; |
60 */ |
57 */ |
61 public class GuardLoweringPhase extends BasePhase<MidTierContext> { |
58 public class GuardLoweringPhase extends BasePhase<MidTierContext> { |
62 |
59 |
63 private static class LowerGuards extends ScheduledNodeIterator { |
60 private static class LowerGuards extends ScheduledNodeIterator { |
64 |
61 |
65 private final Block block; |
|
66 private boolean useGuardIdAsDebugId; |
62 private boolean useGuardIdAsDebugId; |
67 |
63 |
68 LowerGuards(Block block, boolean useGuardIdAsDebugId) { |
64 LowerGuards(boolean useGuardIdAsDebugId) { |
69 this.block = block; |
|
70 this.useGuardIdAsDebugId = useGuardIdAsDebugId; |
65 this.useGuardIdAsDebugId = useGuardIdAsDebugId; |
71 } |
66 } |
72 |
67 |
73 @Override |
68 @Override |
74 protected void processNode(Node node) { |
69 protected void processNode(Node node) { |
93 int debugId = useGuardIdAsDebugId ? guard.getId() : DeoptimizeNode.DEFAULT_DEBUG_ID; |
88 int debugId = useGuardIdAsDebugId ? guard.getId() : DeoptimizeNode.DEFAULT_DEBUG_ID; |
94 DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.getAction(), guard.getReason(), debugId, guard.getSpeculation(), null)); |
89 DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.getAction(), guard.getReason(), debugId, guard.getSpeculation(), null)); |
95 AbstractBeginNode deoptBranch = BeginNode.begin(deopt); |
90 AbstractBeginNode deoptBranch = BeginNode.begin(deopt); |
96 AbstractBeginNode trueSuccessor; |
91 AbstractBeginNode trueSuccessor; |
97 AbstractBeginNode falseSuccessor; |
92 AbstractBeginNode falseSuccessor; |
98 insertLoopExits(deopt); |
|
99 if (guard.isNegated()) { |
93 if (guard.isNegated()) { |
100 trueSuccessor = deoptBranch; |
94 trueSuccessor = deoptBranch; |
101 falseSuccessor = fastPath; |
95 falseSuccessor = fastPath; |
102 } else { |
96 } else { |
103 trueSuccessor = fastPath; |
97 trueSuccessor = fastPath; |
104 falseSuccessor = deoptBranch; |
98 falseSuccessor = deoptBranch; |
105 } |
99 } |
106 IfNode ifNode = graph.add(new IfNode(guard.getCondition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0)); |
100 IfNode ifNode = graph.add(new IfNode(guard.getCondition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0)); |
107 guard.replaceAndDelete(fastPath); |
101 guard.replaceAndDelete(fastPath); |
108 insert(ifNode, fastPath); |
102 insert(ifNode, fastPath); |
109 } |
|
110 } |
|
111 |
|
112 private void insertLoopExits(DeoptimizeNode deopt) { |
|
113 Loop<Block> loop = block.getLoop(); |
|
114 StructuredGraph graph = deopt.graph(); |
|
115 while (loop != null) { |
|
116 LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode())); |
|
117 graph.addBeforeFixed(deopt, exit); |
|
118 loop = loop.getParent(); |
|
119 } |
103 } |
120 } |
104 } |
121 } |
105 } |
122 |
106 |
123 @Override |
107 @Override |
141 return true; |
125 return true; |
142 } |
126 } |
143 |
127 |
144 private static void processBlock(Block block, ScheduleResult schedule) { |
128 private static void processBlock(Block block, ScheduleResult schedule) { |
145 DebugContext debug = block.getBeginNode().getDebug(); |
129 DebugContext debug = block.getBeginNode().getDebug(); |
146 new LowerGuards(block, debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()).processNodes(block, schedule); |
130 new LowerGuards(debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()).processNodes(block, schedule); |
147 } |
131 } |
148 } |
132 } |