1 /*
2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
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
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.nodes;
26 
27 import static org.graalvm.compiler.nodeinfo.InputType.Association;
28 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
29 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
30 
31 import org.graalvm.compiler.graph.IterableNodeType;
32 import org.graalvm.compiler.graph.Node;
33 import org.graalvm.compiler.graph.NodeClass;
34 import org.graalvm.compiler.graph.iterators.NodeIterable;
35 import org.graalvm.compiler.graph.spi.Simplifiable;
36 import org.graalvm.compiler.graph.spi.SimplifierTool;
37 import org.graalvm.compiler.nodeinfo.NodeInfo;
38 
39 @NodeInfo(allowedUsageTypes = {Association}, cycles = CYCLES_0, size = SIZE_0)
40 public final class LoopExitNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable {
41 
42     public static final NodeClass<LoopExitNode> TYPE = NodeClass.create(LoopExitNode.class);
43 
44     /*
45      * The declared type of the field cannot be LoopBeginNode, because loop explosion during partial
46      * evaluation can temporarily assign a non-loop begin. This node will then be deleted shortly
47      * after - but we still must not have type system violations for that short amount of time.
48      */
49     @Input(Association) AbstractBeginNode loopBegin;
50 
LoopExitNode(LoopBeginNode loop)51     public LoopExitNode(LoopBeginNode loop) {
52         super(TYPE);
53         assert loop != null;
54         loopBegin = loop;
55     }
56 
loopBegin()57     public LoopBeginNode loopBegin() {
58         return (LoopBeginNode) loopBegin;
59     }
60 
61     @Override
anchored()62     public NodeIterable<Node> anchored() {
63         return super.anchored().filter(n -> {
64             if (n instanceof ProxyNode) {
65                 ProxyNode proxyNode = (ProxyNode) n;
66                 return proxyNode.proxyPoint() != this;
67             }
68             return true;
69         });
70     }
71 
72     @Override
73     public void prepareDelete(FixedNode evacuateFrom) {
74         removeProxies();
75         super.prepareDelete(evacuateFrom);
76     }
77 
78     public void removeProxies() {
79         if (this.hasUsages()) {
80             outer: while (true) {
81                 for (ProxyNode vpn : proxies().snapshot()) {
82                     ValueNode value = vpn.value();
83                     vpn.replaceAtUsagesAndDelete(value);
84                     if (value == this) {
85                         // Guard proxy could have this input as value.
86                         continue outer;
87                     }
88                 }
89                 break;
90             }
91         }
92     }
93 
94     @SuppressWarnings({"unchecked", "rawtypes"})
95     public NodeIterable<ProxyNode> proxies() {
96         return (NodeIterable) usages().filter(n -> {
97             if (n instanceof ProxyNode) {
98                 ProxyNode proxyNode = (ProxyNode) n;
99                 return proxyNode.proxyPoint() == this;
100             }
101             return false;
102         });
103     }
104 
105     @Override
106     public void simplify(SimplifierTool tool) {
107         Node prev = this.predecessor();
108         while (tool.allUsagesAvailable() && prev instanceof BeginNode && prev.hasNoUsages()) {
109             AbstractBeginNode begin = (AbstractBeginNode) prev;
110             this.setNodeSourcePosition(begin.getNodeSourcePosition());
111             prev = prev.predecessor();
112             graph().removeFixed(begin);
113         }
114     }
115 }
116