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 { 49 50 public static final NodeClass<PhiNode> TYPE = NodeClass.create(PhiNode.class); 51 @Input(Association) protected AbstractMergeNode merge; 52 53 protected PhiNode(NodeClass<? extends PhiNode> c, Stamp stamp, AbstractMergeNode merge) { 54 super(c, stamp); 55 this.merge = merge; 56 } 57 58 public abstract NodeInputList<ValueNode> values(); 59 60 public AbstractMergeNode merge() { 61 return merge; 62 } 63 64 public void setMerge(AbstractMergeNode x) { 65 updateUsages(merge, x); 66 merge = x; 67 } 68 69 @Override 70 public boolean verify() { 71 assertTrue(merge() != null, "missing merge"); 72 assertTrue(merge().phiPredecessorCount() == valueCount(), "mismatch between merge predecessor count and phi value count: %d != %d", merge().phiPredecessorCount(), valueCount()); 73 return super.verify(); 74 } 75 76 /** 77 * Get the instruction that produces the value associated with the i'th predecessor of the 78 * merge. 79 * 80 * @param i the index of the predecessor 81 * @return the instruction that produced the value in the i'th predecessor 82 */ 83 public ValueNode valueAt(int i) { 84 return values().get(i); 85 } 86 87 /** 88 * Sets the value at the given index and makes sure that the values list is large enough. 89 * 90 * @param i the index at which to set the value 91 * @param x the new phi input value for the given location 92 */ 93 public void initializeValueAt(int i, ValueNode x) { 94 while (values().size() <= i) { 95 values().add(null); 96 } 97 values().set(i, x); 98 } 99 100 public void setValueAt(int i, ValueNode x) { 101 values().set(i, x); 102 } 103 104 public void setValueAt(AbstractEndNode end, ValueNode x) { 105 setValueAt(merge().phiPredecessorIndex(end), x); 106 } 107 108 public ValueNode valueAt(AbstractEndNode pred) { 109 return valueAt(merge().phiPredecessorIndex(pred)); 110 } 111 112 /** 113 * Get the number of inputs to this phi (i.e. the number of predecessors to the merge). 114 * 115 * @return the number of inputs in this phi 116 */ 117 public int valueCount() { 118 return values().size(); 119 } 120 121 public void clearValues() { 122 values().clear(); 123 } 124 125 @Override 126 public String toString(Verbosity verbosity) { 127 if (verbosity == Verbosity.Name) { 128 StringBuilder str = new StringBuilder(); 129 for (int i = 0; i < valueCount(); ++i) { 130 if (i != 0) { 131 str.append(' '); 132 } 133 str.append(valueAt(i) == null ? "-" : valueAt(i).toString(Verbosity.Id)); 134 } 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 }