1 /*
2 * Copyright (c) 2009, 2016, 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 package org.graalvm.compiler.nodes;
24
25 import static org.graalvm.compiler.nodeinfo.InputType.Association;
26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
28
29 import java.util.Iterator;
30
31 import org.graalvm.compiler.core.common.type.Stamp;
32 import org.graalvm.compiler.graph.Node;
33 import org.graalvm.compiler.graph.NodeClass;
34 import org.graalvm.compiler.graph.NodeInputList;
35 import org.graalvm.compiler.graph.iterators.NodeIterable;
36 import org.graalvm.compiler.graph.spi.Canonicalizable;
37 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
38 import org.graalvm.compiler.nodeinfo.NodeInfo;
39 import org.graalvm.compiler.nodeinfo.Verbosity;
40 import org.graalvm.compiler.nodes.calc.FloatingNode;
41
42 /**
43 * {@code PhiNode}s represent the merging of edges at a control flow merges (
44 * {@link AbstractMergeNode} or {@link LoopBeginNode}). For a {@link AbstractMergeNode}, the order
45 * of the values corresponds to the order of the ends. For {@link LoopBeginNode}s, the first value
46 * corresponds to the loop's predecessor, while the rest of the values correspond to the
47 * {@link LoopEndNode}s.
48 */
49 @NodeInfo(cycles = CYCLES_0, size = SIZE_1)
50 public abstract class PhiNode extends FloatingNode implements Canonicalizable {
137 return super.toString(Verbosity.Name) + "(" + str + ")";
138 } else {
139 return super.toString(verbosity);
140 }
141 }
142
143 public void addInput(ValueNode x) {
144 assert !(x instanceof ValuePhiNode) || ((ValuePhiNode) x).merge() instanceof LoopBeginNode || ((ValuePhiNode) x).merge() != this.merge();
145 assert !(this instanceof ValuePhiNode) || x.stamp().isCompatible(stamp());
146 values().add(x);
147 }
148
149 public void removeInput(int index) {
150 values().remove(index);
151 }
152
153 public NodeIterable<ValueNode> backValues() {
154 return values().subList(merge().forwardEndCount());
155 }
156
157 @NodeInfo
158 static final class MultipleValuesNode extends ValueNode {
159
160 public static final NodeClass<MultipleValuesNode> TYPE = NodeClass.create(MultipleValuesNode.class);
161
162 protected MultipleValuesNode() {
163 super(TYPE, null);
164 }
165
166 }
167
168 public static final ValueNode MULTIPLE_VALUES = new MultipleValuesNode();
169
170 /**
171 * If all inputs are the same value, this value is returned, otherwise {@link #MULTIPLE_VALUES}.
172 * Note that {@code null} is a valid return value, since {@link GuardPhiNode}s can have
173 * {@code null} inputs.
174 */
175 public ValueNode singleValue() {
176 ValueNode singleValue = valueAt(0);
177 int count = valueCount();
178 for (int i = 1; i < count; ++i) {
179 ValueNode value = valueAt(i);
180 if (value != this) {
181 if (value != singleValue) {
182 return MULTIPLE_VALUES;
183 }
184 }
185 }
186 return singleValue;
187 }
188
189 /**
190 * If all inputs (but the first one) are the same value, this value is returned, otherwise
191 * {@link #MULTIPLE_VALUES}. Note that {@code null} is a valid return value, since
192 * {@link GuardPhiNode}s can have {@code null} inputs.
193 */
194 public ValueNode singleBackValue() {
195 assert merge() instanceof LoopBeginNode;
196 Iterator<ValueNode> iterator = values().iterator();
197 iterator.next();
198 ValueNode singleValue = iterator.next();
199 while (iterator.hasNext()) {
200 if (iterator.next() != singleValue) {
201 return MULTIPLE_VALUES;
202 }
203 }
204 return singleValue;
205 }
206
207 @Override
208 public ValueNode canonical(CanonicalizerTool tool) {
209
210 if (isLoopPhi()) {
211 if (singleBackValue() == this) {
212 return firstValue();
213 }
214
215 boolean onlySelfUsage = true;
216 for (Node n : this.usages()) {
217 if (n != this) {
218 onlySelfUsage = false;
219 break;
220 }
221 }
222
223 if (onlySelfUsage) {
224 return null;
225 }
226 }
227
228 ValueNode singleValue = singleValue();
229 if (singleValue != MULTIPLE_VALUES) {
230 return singleValue;
231 }
232 return this;
233 }
234
235 public ValueNode firstValue() {
236 return valueAt(0);
237 }
238
239 public boolean isLoopPhi() {
240 return merge() instanceof LoopBeginNode;
241 }
242
243 public boolean hasValidInput() {
244 for (ValueNode n : values()) {
245 if (n != null) {
246 return true;
247 }
248 }
249 return false;
250 }
251 }
|
1 /*
2 * Copyright (c) 2009, 2017, 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 package org.graalvm.compiler.nodes;
24
25 import static org.graalvm.compiler.nodeinfo.InputType.Association;
26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
28
29 import org.graalvm.compiler.core.common.type.Stamp;
30 import org.graalvm.compiler.graph.Node;
31 import org.graalvm.compiler.graph.NodeClass;
32 import org.graalvm.compiler.graph.NodeInputList;
33 import org.graalvm.compiler.graph.iterators.NodeIterable;
34 import org.graalvm.compiler.graph.spi.Canonicalizable;
35 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
36 import org.graalvm.compiler.nodeinfo.NodeInfo;
37 import org.graalvm.compiler.nodeinfo.Verbosity;
38 import org.graalvm.compiler.nodes.calc.FloatingNode;
39
40 /**
41 * {@code PhiNode}s represent the merging of edges at a control flow merges (
42 * {@link AbstractMergeNode} or {@link LoopBeginNode}). For a {@link AbstractMergeNode}, the order
43 * of the values corresponds to the order of the ends. For {@link LoopBeginNode}s, the first value
44 * corresponds to the loop's predecessor, while the rest of the values correspond to the
45 * {@link LoopEndNode}s.
46 */
47 @NodeInfo(cycles = CYCLES_0, size = SIZE_1)
48 public abstract class PhiNode extends FloatingNode implements Canonicalizable {
135 return super.toString(Verbosity.Name) + "(" + str + ")";
136 } else {
137 return super.toString(verbosity);
138 }
139 }
140
141 public void addInput(ValueNode x) {
142 assert !(x instanceof ValuePhiNode) || ((ValuePhiNode) x).merge() instanceof LoopBeginNode || ((ValuePhiNode) x).merge() != this.merge();
143 assert !(this instanceof ValuePhiNode) || x.stamp().isCompatible(stamp());
144 values().add(x);
145 }
146
147 public void removeInput(int index) {
148 values().remove(index);
149 }
150
151 public NodeIterable<ValueNode> backValues() {
152 return values().subList(merge().forwardEndCount());
153 }
154
155 /**
156 * If all inputs are the same value, this value is returned, otherwise {@code this}. Note that
157 * {@code null} is a valid return value, since {@link GuardPhiNode}s can have {@code null}
158 * inputs.
159 */
160 public ValueNode singleValueOrThis() {
161 ValueNode singleValue = valueAt(0);
162 int count = valueCount();
163 for (int i = 1; i < count; ++i) {
164 ValueNode value = valueAt(i);
165 if (value != this) {
166 if (value != singleValue) {
167 return this;
168 }
169 }
170 }
171 return singleValue;
172 }
173
174 /**
175 * If all inputs (but the first one) are the same value, the value is returned, otherwise
176 * {@code this}. Note that {@code null} is a valid return value, since {@link GuardPhiNode}s can
177 * have {@code null} inputs.
178 */
179 public ValueNode singleBackValueOrThis() {
180 int valueCount = valueCount();
181 assert merge() instanceof LoopBeginNode && valueCount >= 2;
182 // Skip first value, assume second value as single value.
183 ValueNode singleValue = valueAt(1);
184 for (int i = 2; i < valueCount; ++i) {
185 ValueNode value = valueAt(i);
186 if (value != singleValue) {
187 return this;
188 }
189 }
190 return singleValue;
191 }
192
193 @Override
194 public ValueNode canonical(CanonicalizerTool tool) {
195
196 if (isLoopPhi()) {
197
198 int valueCount = valueCount();
199 assert valueCount >= 2;
200 int i;
201 for (i = 1; i < valueCount; ++i) {
202 ValueNode value = valueAt(i);
203 if (value != this) {
204 break;
205 }
206 }
207
208 // All back edges are self-references => return forward edge input value.
209 if (i == valueCount) {
210 return firstValue();
211 }
212
213 boolean onlySelfUsage = true;
214 for (Node n : this.usages()) {
215 if (n != this) {
216 onlySelfUsage = false;
217 break;
218 }
219 }
220
221 if (onlySelfUsage) {
222 return null;
223 }
224 }
225
226 return singleValueOrThis();
227 }
228
229 public ValueNode firstValue() {
230 return valueAt(0);
231 }
232
233 public boolean isLoopPhi() {
234 return merge() instanceof LoopBeginNode;
235 }
236 }
|