26 27 import org.graalvm.compiler.core.common.type.IntegerStamp; 28 import org.graalvm.compiler.graph.IterableNodeType; 29 import org.graalvm.compiler.graph.Node; 30 import org.graalvm.compiler.graph.NodeClass; 31 import org.graalvm.compiler.graph.iterators.NodeIterable; 32 import org.graalvm.compiler.graph.spi.SimplifierTool; 33 import org.graalvm.compiler.nodeinfo.InputType; 34 import org.graalvm.compiler.nodeinfo.NodeInfo; 35 import org.graalvm.compiler.nodes.calc.AddNode; 36 import org.graalvm.compiler.nodes.extended.GuardingNode; 37 import org.graalvm.compiler.nodes.spi.LIRLowerable; 38 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 39 import org.graalvm.compiler.nodes.util.GraphUtil; 40 41 @NodeInfo 42 public final class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable { 43 44 public static final NodeClass<LoopBeginNode> TYPE = NodeClass.create(LoopBeginNode.class); 45 protected double loopFrequency; 46 protected int nextEndIndex; 47 protected int unswitches; 48 protected int inversionCount; 49 50 /** See {@link LoopEndNode#canSafepoint} for more information. */ 51 boolean canEndsSafepoint; 52 53 @OptionalInput(InputType.Guard) GuardingNode overflowGuard; 54 55 public LoopBeginNode() { 56 super(TYPE); 57 loopFrequency = 1; 58 this.canEndsSafepoint = true; 59 } 60 61 /** Disables safepoint for the whole loop, i.e., for all {@link LoopEndNode loop ends}. */ 62 public void disableSafepoint() { 63 /* Store flag locally in case new loop ends are created later on. */ 64 this.canEndsSafepoint = false; 65 /* Propagate flag to all existing loop ends. */ 66 for (LoopEndNode loopEnd : loopEnds()) { 67 loopEnd.disableSafepoint(); 68 } 69 } 70 71 public double loopFrequency() { 72 return loopFrequency; 73 } 74 75 public void setLoopFrequency(double loopFrequency) { 76 assert loopFrequency >= 0; 77 this.loopFrequency = loopFrequency; 78 } 79 80 /** 81 * Returns the <b>unordered</b> set of {@link LoopEndNode} that correspond to back-edges for 82 * this loop. The order of the back-edges is unspecified, if you need to get an ordering 83 * compatible for {@link PhiNode} creation, use {@link #orderedLoopEnds()}. 84 * 85 * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop 86 */ 87 public NodeIterable<LoopEndNode> loopEnds() { 88 return usages().filter(LoopEndNode.class); 89 } 90 105 * For example a new PhiNode may be added as follow: 106 * 107 * <pre> 108 * PhiNode phi = new ValuePhiNode(stamp, loop); 109 * phi.addInput(forwardEdgeValue); 110 * for (LoopEndNode loopEnd : loop.orderedLoopEnds()) { 111 * phi.addInput(backEdgeValue(loopEnd)); 112 * } 113 * </pre> 114 * 115 * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop 116 */ 117 public LoopEndNode[] orderedLoopEnds() { 118 LoopEndNode[] result = new LoopEndNode[this.getLoopEndCount()]; 119 for (LoopEndNode end : loopEnds()) { 120 result[end.endIndex()] = end; 121 } 122 return result; 123 } 124 125 public AbstractEndNode forwardEnd() { 126 assert forwardEndCount() == 1; 127 return forwardEndAt(0); 128 } 129 130 @Override 131 public void generate(NodeLIRBuilderTool gen) { 132 // Nothing to emit, since this is node is used for structural purposes only. 133 } 134 135 @Override 136 protected void deleteEnd(AbstractEndNode end) { 137 if (end instanceof LoopEndNode) { 138 LoopEndNode loopEnd = (LoopEndNode) end; 139 loopEnd.setLoopBegin(null); 140 int idx = loopEnd.endIndex(); 141 for (LoopEndNode le : loopEnds()) { 142 int leIdx = le.endIndex(); 143 assert leIdx != idx; 144 if (leIdx > idx) { 145 le.setEndIndex(leIdx - 1); 146 } 147 } 148 nextEndIndex--; 149 } else { | 26 27 import org.graalvm.compiler.core.common.type.IntegerStamp; 28 import org.graalvm.compiler.graph.IterableNodeType; 29 import org.graalvm.compiler.graph.Node; 30 import org.graalvm.compiler.graph.NodeClass; 31 import org.graalvm.compiler.graph.iterators.NodeIterable; 32 import org.graalvm.compiler.graph.spi.SimplifierTool; 33 import org.graalvm.compiler.nodeinfo.InputType; 34 import org.graalvm.compiler.nodeinfo.NodeInfo; 35 import org.graalvm.compiler.nodes.calc.AddNode; 36 import org.graalvm.compiler.nodes.extended.GuardingNode; 37 import org.graalvm.compiler.nodes.spi.LIRLowerable; 38 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 39 import org.graalvm.compiler.nodes.util.GraphUtil; 40 41 @NodeInfo 42 public final class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable { 43 44 public static final NodeClass<LoopBeginNode> TYPE = NodeClass.create(LoopBeginNode.class); 45 protected double loopFrequency; 46 protected double loopOrigFrequency; 47 protected int nextEndIndex; 48 protected int unswitches; 49 protected int splits; 50 protected int inversionCount; 51 protected LoopType loopType; 52 protected int unrollFactor; 53 54 public enum LoopType { 55 SIMPLE_LOOP, 56 PRE_LOOP, 57 MAIN_LOOP, 58 POST_LOOP 59 } 60 61 /** See {@link LoopEndNode#canSafepoint} for more information. */ 62 boolean canEndsSafepoint; 63 64 @OptionalInput(InputType.Guard) GuardingNode overflowGuard; 65 66 public LoopBeginNode() { 67 super(TYPE); 68 loopFrequency = 1; 69 loopOrigFrequency = 1; 70 unswitches = 0; 71 splits = 0; 72 this.canEndsSafepoint = true; 73 loopType = LoopType.SIMPLE_LOOP; 74 unrollFactor = 1; 75 } 76 77 public boolean isSimpleLoop() { 78 return (loopType == LoopType.SIMPLE_LOOP); 79 } 80 81 public void setPreLoop() { 82 assert isSimpleLoop(); 83 loopType = LoopType.PRE_LOOP; 84 } 85 86 public boolean isPreLoop() { 87 return (loopType == LoopType.PRE_LOOP); 88 } 89 90 public void setMainLoop() { 91 assert isSimpleLoop(); 92 loopType = LoopType.MAIN_LOOP; 93 } 94 95 public boolean isMainLoop() { 96 return (loopType == LoopType.MAIN_LOOP); 97 } 98 99 public void setPostLoop() { 100 assert isSimpleLoop(); 101 loopType = LoopType.POST_LOOP; 102 } 103 104 public boolean isPostLoop() { 105 return (loopType == LoopType.POST_LOOP); 106 } 107 108 public int getUnrollFactor() { 109 return unrollFactor; 110 } 111 112 public void setUnrollFactor(int currentUnrollFactor) { 113 unrollFactor = currentUnrollFactor; 114 } 115 116 /** Disables safepoint for the whole loop, i.e., for all {@link LoopEndNode loop ends}. */ 117 public void disableSafepoint() { 118 /* Store flag locally in case new loop ends are created later on. */ 119 this.canEndsSafepoint = false; 120 /* Propagate flag to all existing loop ends. */ 121 for (LoopEndNode loopEnd : loopEnds()) { 122 loopEnd.disableSafepoint(); 123 } 124 } 125 126 public double loopOrigFrequency() { 127 return loopOrigFrequency; 128 } 129 130 public void setLoopOrigFrequency(double loopOrigFrequency) { 131 assert loopOrigFrequency >= 0; 132 this.loopOrigFrequency = loopOrigFrequency; 133 } 134 135 public double loopFrequency() { 136 return loopFrequency; 137 } 138 139 public void setLoopFrequency(double loopFrequency) { 140 assert loopFrequency >= 0; 141 this.loopFrequency = loopFrequency; 142 } 143 144 /** 145 * Returns the <b>unordered</b> set of {@link LoopEndNode} that correspond to back-edges for 146 * this loop. The order of the back-edges is unspecified, if you need to get an ordering 147 * compatible for {@link PhiNode} creation, use {@link #orderedLoopEnds()}. 148 * 149 * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop 150 */ 151 public NodeIterable<LoopEndNode> loopEnds() { 152 return usages().filter(LoopEndNode.class); 153 } 154 169 * For example a new PhiNode may be added as follow: 170 * 171 * <pre> 172 * PhiNode phi = new ValuePhiNode(stamp, loop); 173 * phi.addInput(forwardEdgeValue); 174 * for (LoopEndNode loopEnd : loop.orderedLoopEnds()) { 175 * phi.addInput(backEdgeValue(loopEnd)); 176 * } 177 * </pre> 178 * 179 * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop 180 */ 181 public LoopEndNode[] orderedLoopEnds() { 182 LoopEndNode[] result = new LoopEndNode[this.getLoopEndCount()]; 183 for (LoopEndNode end : loopEnds()) { 184 result[end.endIndex()] = end; 185 } 186 return result; 187 } 188 189 public boolean isSingleEntryLoop() { 190 return (forwardEndCount() == 1); 191 } 192 193 public AbstractEndNode forwardEnd() { 194 assert forwardEndCount() == 1; 195 return forwardEndAt(0); 196 } 197 198 public int splits() { 199 return splits; 200 } 201 202 public void incrementSplits() { 203 splits++; 204 } 205 206 @Override 207 public void generate(NodeLIRBuilderTool gen) { 208 // Nothing to emit, since this is node is used for structural purposes only. 209 } 210 211 @Override 212 protected void deleteEnd(AbstractEndNode end) { 213 if (end instanceof LoopEndNode) { 214 LoopEndNode loopEnd = (LoopEndNode) end; 215 loopEnd.setLoopBegin(null); 216 int idx = loopEnd.endIndex(); 217 for (LoopEndNode le : loopEnds()) { 218 int leIdx = le.endIndex(); 219 assert leIdx != idx; 220 if (leIdx > idx) { 221 le.setEndIndex(leIdx - 1); 222 } 223 } 224 nextEndIndex--; 225 } else { |