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 package org.graalvm.compiler.phases.common;
24
25 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional;
26
27 import java.util.List;
28
29 import org.graalvm.compiler.debug.Debug;
30 import org.graalvm.compiler.debug.DebugCloseable;
31 import org.graalvm.compiler.graph.Node;
32 import org.graalvm.compiler.graph.spi.SimplifierTool;
33 import org.graalvm.compiler.nodeinfo.InputType;
34 import org.graalvm.compiler.nodes.AbstractBeginNode;
35 import org.graalvm.compiler.nodes.AbstractEndNode;
36 import org.graalvm.compiler.nodes.AbstractMergeNode;
37 import org.graalvm.compiler.nodes.ConstantNode;
38 import org.graalvm.compiler.nodes.ControlSplitNode;
39 import org.graalvm.compiler.nodes.DeoptimizeNode;
40 import org.graalvm.compiler.nodes.EndNode;
41 import org.graalvm.compiler.nodes.FixedGuardNode;
42 import org.graalvm.compiler.nodes.FixedNode;
43 import org.graalvm.compiler.nodes.FixedWithNextNode;
44 import org.graalvm.compiler.nodes.GuardNode;
45 import org.graalvm.compiler.nodes.IfNode;
46 import org.graalvm.compiler.nodes.LogicNode;
47 import org.graalvm.compiler.nodes.LoopExitNode;
48 import org.graalvm.compiler.nodes.ProxyNode;
49 import org.graalvm.compiler.nodes.StructuredGraph;
50 import org.graalvm.compiler.nodes.ValueNode;
152 ys = y.asConstant();
153 } else {
154 ys = yPhi.valueAt(mergePredecessor).asConstant();
155 }
156 if (xs != null && ys != null && compare.condition().foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) {
157 visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.getSpeculation(), fixedGuard.graph(), context.getLowerer());
158 }
159 }
160 }
161
162 private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, JavaConstant speculation, StructuredGraph graph,
163 LoweringProvider loweringProvider) {
164 if (deoptBegin.predecessor() instanceof AbstractBeginNode) {
165 /*
166 * Walk up chains of LoopExitNodes to the "real" BeginNode that leads to deoptimization.
167 */
168 visitDeoptBegin((AbstractBeginNode) deoptBegin.predecessor(), deoptAction, deoptReason, speculation, graph, loweringProvider);
169 return;
170 }
171
172 if (deoptBegin instanceof AbstractMergeNode) {
173 AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
174 Debug.log("Visiting %s", mergeNode);
175 FixedNode next = mergeNode.next();
176 while (mergeNode.isAlive()) {
177 AbstractEndNode end = mergeNode.forwardEnds().first();
178 AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(end);
179 visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider);
180 }
181 assert next.isAlive();
182 AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(next);
183 visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider);
184 return;
185 } else if (deoptBegin.predecessor() instanceof IfNode) {
186 IfNode ifNode = (IfNode) deoptBegin.predecessor();
187 LogicNode conditionNode = ifNode.condition();
188 FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, speculation, deoptBegin == ifNode.trueSuccessor()));
189 FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
190 AbstractBeginNode survivingSuccessor;
191 if (deoptBegin == ifNode.trueSuccessor()) {
192 survivingSuccessor = ifNode.falseSuccessor();
193 } else {
194 survivingSuccessor = ifNode.trueSuccessor();
195 }
196 graph.removeSplitPropagate(ifNode, survivingSuccessor);
197
198 Node newGuard = guard;
199 if (survivingSuccessor instanceof LoopExitNode) {
200 newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
201 }
202 survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);
203
204 Debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor);
205 FixedNode next = pred.next();
206 pred.setNext(guard);
207 guard.setNext(next);
208 SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider);
209 survivingSuccessor.simplify(simplifierTool);
210 return;
211 }
212
213 // We could not convert the control split - at least cut off control flow after the split.
214 FixedWithNextNode deoptPred = deoptBegin;
215 FixedNode next = deoptPred.next();
216
217 if (!(next instanceof DeoptimizeNode)) {
218 DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason, speculation));
219 deoptPred.setNext(newDeoptNode);
220 assert deoptPred == newDeoptNode.predecessor();
221 GraphUtil.killCFG(next);
222 }
223 }
224 }
|
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 package org.graalvm.compiler.phases.common;
24
25 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional;
26
27 import java.util.List;
28
29 import org.graalvm.compiler.debug.DebugCloseable;
30 import org.graalvm.compiler.debug.DebugContext;
31 import org.graalvm.compiler.graph.Node;
32 import org.graalvm.compiler.graph.spi.SimplifierTool;
33 import org.graalvm.compiler.nodeinfo.InputType;
34 import org.graalvm.compiler.nodes.AbstractBeginNode;
35 import org.graalvm.compiler.nodes.AbstractEndNode;
36 import org.graalvm.compiler.nodes.AbstractMergeNode;
37 import org.graalvm.compiler.nodes.ConstantNode;
38 import org.graalvm.compiler.nodes.ControlSplitNode;
39 import org.graalvm.compiler.nodes.DeoptimizeNode;
40 import org.graalvm.compiler.nodes.EndNode;
41 import org.graalvm.compiler.nodes.FixedGuardNode;
42 import org.graalvm.compiler.nodes.FixedNode;
43 import org.graalvm.compiler.nodes.FixedWithNextNode;
44 import org.graalvm.compiler.nodes.GuardNode;
45 import org.graalvm.compiler.nodes.IfNode;
46 import org.graalvm.compiler.nodes.LogicNode;
47 import org.graalvm.compiler.nodes.LoopExitNode;
48 import org.graalvm.compiler.nodes.ProxyNode;
49 import org.graalvm.compiler.nodes.StructuredGraph;
50 import org.graalvm.compiler.nodes.ValueNode;
152 ys = y.asConstant();
153 } else {
154 ys = yPhi.valueAt(mergePredecessor).asConstant();
155 }
156 if (xs != null && ys != null && compare.condition().foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) {
157 visitDeoptBegin(AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.getSpeculation(), fixedGuard.graph(), context.getLowerer());
158 }
159 }
160 }
161
162 private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, JavaConstant speculation, StructuredGraph graph,
163 LoweringProvider loweringProvider) {
164 if (deoptBegin.predecessor() instanceof AbstractBeginNode) {
165 /*
166 * Walk up chains of LoopExitNodes to the "real" BeginNode that leads to deoptimization.
167 */
168 visitDeoptBegin((AbstractBeginNode) deoptBegin.predecessor(), deoptAction, deoptReason, speculation, graph, loweringProvider);
169 return;
170 }
171
172 DebugContext debug = deoptBegin.getDebug();
173 if (deoptBegin instanceof AbstractMergeNode) {
174 AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
175 debug.log("Visiting %s", mergeNode);
176 FixedNode next = mergeNode.next();
177 while (mergeNode.isAlive()) {
178 AbstractEndNode end = mergeNode.forwardEnds().first();
179 AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(end);
180 visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider);
181 }
182 assert next.isAlive();
183 AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(next);
184 visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph, loweringProvider);
185 return;
186 } else if (deoptBegin.predecessor() instanceof IfNode) {
187 IfNode ifNode = (IfNode) deoptBegin.predecessor();
188 LogicNode conditionNode = ifNode.condition();
189 FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, speculation, deoptBegin == ifNode.trueSuccessor()));
190 FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
191 AbstractBeginNode survivingSuccessor;
192 if (deoptBegin == ifNode.trueSuccessor()) {
193 survivingSuccessor = ifNode.falseSuccessor();
194 } else {
195 survivingSuccessor = ifNode.trueSuccessor();
196 }
197 graph.removeSplitPropagate(ifNode, survivingSuccessor);
198
199 Node newGuard = guard;
200 if (survivingSuccessor instanceof LoopExitNode) {
201 newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
202 }
203 survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);
204
205 debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor);
206 FixedNode next = pred.next();
207 pred.setNext(guard);
208 guard.setNext(next);
209 SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider);
210 survivingSuccessor.simplify(simplifierTool);
211 return;
212 }
213
214 // We could not convert the control split - at least cut off control flow after the split.
215 FixedWithNextNode deoptPred = deoptBegin;
216 FixedNode next = deoptPred.next();
217
218 if (!(next instanceof DeoptimizeNode)) {
219 DeoptimizeNode newDeoptNode = graph.add(new DeoptimizeNode(deoptAction, deoptReason, speculation));
220 deoptPred.setNext(newDeoptNode);
221 assert deoptPred == newDeoptNode.predecessor();
222 GraphUtil.killCFG(next);
223 }
224 }
225 }
|