1 /* 2 * Copyright (c) 2017, 2018, 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.phases.common; 26 27 import jdk.internal.vm.compiler.collections.EconomicMap; 28 import jdk.internal.vm.compiler.collections.MapCursor; 29 import org.graalvm.compiler.core.common.GraalOptions; 30 import org.graalvm.compiler.core.common.cfg.BlockMap; 31 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; 32 import org.graalvm.compiler.core.common.type.FloatStamp; 33 import org.graalvm.compiler.core.common.type.Stamp; 34 import org.graalvm.compiler.core.common.type.StampFactory; 35 import org.graalvm.compiler.debug.CounterKey; 36 import org.graalvm.compiler.debug.DebugContext; 37 import org.graalvm.compiler.graph.Node; 38 import org.graalvm.compiler.graph.NodeMap; 39 import org.graalvm.compiler.graph.NodeStack; 40 import org.graalvm.compiler.graph.Position; 41 import org.graalvm.compiler.graph.spi.CanonicalizerTool; 42 import org.graalvm.compiler.nodeinfo.InputType; 43 import org.graalvm.compiler.nodes.AbstractBeginNode; 44 import org.graalvm.compiler.nodes.AbstractMergeNode; 45 import org.graalvm.compiler.nodes.BinaryOpLogicNode; 46 import org.graalvm.compiler.nodes.ConstantNode; 47 import org.graalvm.compiler.nodes.EndNode; 48 import org.graalvm.compiler.nodes.IfNode; 49 import org.graalvm.compiler.nodes.LogicNode; 50 import org.graalvm.compiler.nodes.MergeNode; 51 import org.graalvm.compiler.nodes.NodeView; 52 import org.graalvm.compiler.nodes.PhiNode; 53 import org.graalvm.compiler.nodes.PiNode; 54 import org.graalvm.compiler.nodes.StructuredGraph; 55 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; 56 import org.graalvm.compiler.nodes.UnaryOpLogicNode; 57 import org.graalvm.compiler.nodes.ValueNode; 58 import org.graalvm.compiler.nodes.ValuePhiNode; 59 import org.graalvm.compiler.nodes.calc.BinaryNode; 60 import org.graalvm.compiler.nodes.calc.ConditionalNode; 61 import org.graalvm.compiler.nodes.calc.UnaryNode; 62 import org.graalvm.compiler.nodes.cfg.Block; 63 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; 64 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph.RecursiveVisitor; 65 import org.graalvm.compiler.nodes.extended.GuardingNode; 66 import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; 67 import org.graalvm.compiler.nodes.memory.FixedAccessNode; 68 import org.graalvm.compiler.nodes.memory.FloatingAccessNode; 69 import org.graalvm.compiler.nodes.memory.FloatingReadNode; 70 import org.graalvm.compiler.nodes.memory.MemoryAccess; 71 import org.graalvm.compiler.nodes.memory.MemoryPhiNode; 72 import org.graalvm.compiler.nodes.util.GraphUtil; 73 import org.graalvm.compiler.options.OptionValues; 74 import org.graalvm.compiler.phases.BasePhase; 75 import org.graalvm.compiler.phases.Phase; 76 import org.graalvm.compiler.phases.graph.ScheduledNodeIterator; 77 import org.graalvm.compiler.phases.schedule.SchedulePhase; 78 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; 79 import org.graalvm.compiler.phases.tiers.LowTierContext; 80 import org.graalvm.compiler.phases.tiers.PhaseContext; 81 82 import jdk.vm.ci.meta.Assumptions; 83 import jdk.vm.ci.meta.Constant; 84 import jdk.vm.ci.meta.ConstantReflectionProvider; 85 import jdk.vm.ci.meta.MetaAccessProvider; 86 import jdk.vm.ci.meta.TriState; 87 88 /** 89 * This phase lowers {@link FloatingReadNode FloatingReadNodes} into corresponding fixed reads. 90 */ 91 public class FixReadsPhase extends BasePhase<LowTierContext> { 92 93 private static final CounterKey counterStampsRegistered = DebugContext.counter("FixReads_StampsRegistered"); 94 private static final CounterKey counterIfsKilled = DebugContext.counter("FixReads_KilledIfs"); 95 private static final CounterKey counterConditionalsKilled = DebugContext.counter("FixReads_KilledConditionals"); 96 private static final CounterKey counterCanonicalizedSwitches = DebugContext.counter("FixReads_CanonicalizedSwitches"); 97 private static final CounterKey counterConstantReplacements = DebugContext.counter("FixReads_ConstantReplacement"); 98 private static final CounterKey counterConstantInputReplacements = DebugContext.counter("FixReads_ConstantInputReplacement"); 99 private static final CounterKey counterBetterMergedStamps = DebugContext.counter("FixReads_BetterMergedStamp"); 100 101 protected boolean replaceInputsWithConstants; 102 protected Phase schedulePhase; 103 104 @Override 105 public float codeSizeIncrease() { 106 return 2.0f; 107 } 108 109 private static class FixReadsClosure extends ScheduledNodeIterator { 110 111 @Override 112 protected void processNode(Node node) { 113 if (node instanceof AbstractMergeNode) { 114 AbstractMergeNode mergeNode = (AbstractMergeNode) node; 115 for (MemoryPhiNode memoryPhi : mergeNode.memoryPhis().snapshot()) { 116 // Memory phi nodes are no longer necessary at this point. 117 memoryPhi.replaceAtUsages(null); 118 memoryPhi.safeDelete(); 119 } 120 } else if (node instanceof FloatingAccessNode) { 121 FloatingAccessNode floatingAccessNode = (FloatingAccessNode) node; 122 floatingAccessNode.setLastLocationAccess(null); 123 GuardingNode guard = floatingAccessNode.getGuard(); 124 if (guard != null) { 125 floatingAccessNode.setGuard(null); 126 GraphUtil.tryKillUnused(guard.asNode()); 127 } 128 FixedAccessNode fixedAccess = floatingAccessNode.asFixedNode(); 129 replaceCurrent(fixedAccess); 130 } else if (node instanceof PiNode) { 131 PiNode piNode = (PiNode) node; 132 if (piNode.stamp(NodeView.DEFAULT).isCompatible(piNode.getOriginalNode().stamp(NodeView.DEFAULT))) { 133 // Pi nodes are no longer necessary at this point. 134 piNode.replaceAndDelete(piNode.getOriginalNode()); 135 } 136 } else if (node instanceof MemoryAccess) { 137 MemoryAccess memoryAccess = (MemoryAccess) node; 138 memoryAccess.setLastLocationAccess(null); 139 } 140 } 141 142 } 143 144 public static class RawConditionalEliminationVisitor implements RecursiveVisitor<Integer> { 145 146 protected final NodeMap<StampElement> stampMap; 147 protected final NodeStack undoOperations; 148 private final ScheduleResult schedule; 149 private final StructuredGraph graph; 150 private final MetaAccessProvider metaAccess; 151 private final boolean replaceConstantInputs; 152 private final BlockMap<Integer> blockActionStart; 153 private final EconomicMap<MergeNode, EconomicMap<ValueNode, Stamp>> endMaps; 154 private final DebugContext debug; 155 private final RawCanonicalizerTool rawCanonicalizerTool = new RawCanonicalizerTool(); 156 157 private class RawCanonicalizerTool implements NodeView, CanonicalizerTool { 158 159 @Override 160 public Assumptions getAssumptions() { 161 return graph.getAssumptions(); 162 } 163 164 @Override 165 public MetaAccessProvider getMetaAccess() { 166 return metaAccess; 167 } 168 169 @Override 170 public ConstantReflectionProvider getConstantReflection() { 171 return null; 172 } 173 174 @Override 175 public ConstantFieldProvider getConstantFieldProvider() { 176 return null; 177 } 178 179 @Override 180 public boolean canonicalizeReads() { 181 return false; 182 } 183 184 @Override 185 public boolean allUsagesAvailable() { 186 return true; 187 } 188 189 @Override 190 public Integer smallestCompareWidth() { 191 return null; 192 } 193 194 @Override 195 public OptionValues getOptions() { 196 return graph.getOptions(); 197 } 198 199 @Override 200 public Stamp stamp(ValueNode node) { 201 return getBestStamp(node); 202 } 203 204 } 205 206 public RawConditionalEliminationVisitor(StructuredGraph graph, ScheduleResult schedule, MetaAccessProvider metaAccess, boolean replaceInputsWithConstants) { 207 this.graph = graph; 208 this.debug = graph.getDebug(); 209 this.schedule = schedule; 210 this.metaAccess = metaAccess; 211 blockActionStart = new BlockMap<>(schedule.getCFG()); 212 endMaps = EconomicMap.create(); 213 stampMap = graph.createNodeMap(); 214 undoOperations = new NodeStack(); 215 replaceConstantInputs = replaceInputsWithConstants && GraalOptions.ReplaceInputsWithConstantsBasedOnStamps.getValue(graph.getOptions()); 216 } 217 218 protected void replaceInput(Position p, Node oldInput, Node newConstantInput) { 219 p.set(oldInput, newConstantInput); 220 } 221 222 protected int replaceConstantInputs(Node node) { 223 int replacements = 0; 224 // Check if we can replace any of the inputs with a constant. 225 for (Position p : node.inputPositions()) { 226 Node input = p.get(node); 227 if (p.getInputType() == InputType.Value) { 228 if (input instanceof ValueNode) { 229 ValueNode valueNode = (ValueNode) input; 230 if (valueNode instanceof ConstantNode) { 231 // Input already is a constant. 232 } else { 233 Stamp bestStamp = getBestStamp(valueNode); 234 Constant constant = bestStamp.asConstant(); 235 if (constant != null) { 236 if (bestStamp instanceof FloatStamp) { 237 FloatStamp floatStamp = (FloatStamp) bestStamp; 238 if (floatStamp.contains(0.0d)) { 239 // Could also be -0.0d. 240 continue; 241 } 242 } 243 counterConstantInputReplacements.increment(node.getDebug()); 244 ConstantNode stampConstant = ConstantNode.forConstant(bestStamp, constant, metaAccess, graph); 245 assert stampConstant.stamp(NodeView.DEFAULT).isCompatible(valueNode.stamp(NodeView.DEFAULT)); 246 replaceInput(p, node, stampConstant); 247 replacements++; 248 } 249 } 250 } 251 } 252 } 253 return replacements; 254 } 255 256 protected void processNode(Node node) { 257 assert node.isAlive(); 258 259 if (replaceConstantInputs) { 260 replaceConstantInputs(node); 261 } 262 263 if (node instanceof MergeNode) { 264 registerCombinedStamps((MergeNode) node); 265 } 266 267 if (node instanceof AbstractBeginNode) { 268 processAbstractBegin((AbstractBeginNode) node); 269 } else if (node instanceof IfNode) { 270 processIf((IfNode) node); 271 } else if (node instanceof IntegerSwitchNode) { 272 processIntegerSwitch((IntegerSwitchNode) node); 273 } else if (node instanceof BinaryNode) { 274 processBinary((BinaryNode) node); 275 } else if (node instanceof ConditionalNode) { 276 processConditional((ConditionalNode) node); 277 } else if (node instanceof UnaryNode) { 278 processUnary((UnaryNode) node); 279 } else if (node instanceof EndNode) { 280 processEnd((EndNode) node); 281 } 282 } 283 284 protected void registerCombinedStamps(MergeNode node) { 285 EconomicMap<ValueNode, Stamp> endMap = endMaps.get(node); 286 MapCursor<ValueNode, Stamp> entries = endMap.getEntries(); 287 while (entries.advance()) { 288 ValueNode value = entries.getKey(); 289 if (value.isDeleted()) { 290 // nodes from this map can be deleted when a loop dies 291 continue; 292 } 293 if (registerNewValueStamp(value, entries.getValue())) { 294 counterBetterMergedStamps.increment(debug); 295 } 296 } 297 } 298 299 protected void processEnd(EndNode node) { 300 AbstractMergeNode abstractMerge = node.merge(); 301 if (abstractMerge instanceof MergeNode) { 302 MergeNode merge = (MergeNode) abstractMerge; 303 304 NodeMap<Block> blockToNodeMap = this.schedule.getNodeToBlockMap(); 305 Block mergeBlock = blockToNodeMap.get(merge); 306 Block mergeBlockDominator = mergeBlock.getDominator(); 307 Block currentBlock = blockToNodeMap.get(node); 308 309 EconomicMap<ValueNode, Stamp> currentEndMap = endMaps.get(merge); 310 311 if (currentEndMap == null || !currentEndMap.isEmpty()) { 312 313 EconomicMap<ValueNode, Stamp> endMap = EconomicMap.create(); 314 315 // Process phis 316 for (ValuePhiNode phi : merge.valuePhis()) { 317 if (currentEndMap == null || currentEndMap.containsKey(phi)) { 318 ValueNode valueAt = phi.valueAt(node); 319 Stamp bestStamp = getBestStamp(valueAt); 320 321 if (currentEndMap != null) { 322 bestStamp = bestStamp.meet(currentEndMap.get(phi)); 323 } 324 325 if (!bestStamp.equals(phi.stamp(NodeView.DEFAULT))) { 326 endMap.put(phi, bestStamp); 327 } 328 } 329 } 330 331 int lastMark = undoOperations.size(); 332 while (currentBlock != mergeBlockDominator) { 333 int mark = blockActionStart.get(currentBlock); 334 for (int i = lastMark - 1; i >= mark; --i) { 335 ValueNode nodeWithNewStamp = (ValueNode) undoOperations.get(i); 336 337 if (nodeWithNewStamp.isDeleted() || nodeWithNewStamp instanceof LogicNode || nodeWithNewStamp instanceof ConstantNode || blockToNodeMap.isNew(nodeWithNewStamp)) { 338 continue; 339 } 340 341 Block block = getBlock(nodeWithNewStamp, blockToNodeMap); 342 if (block == null || block.getId() <= mergeBlockDominator.getId()) { 343 // Node with new stamp in path to the merge block dominator and that 344 // at the same time was defined at least in the merge block 345 // dominator (i.e., therefore can be used after the merge.) 346 347 Stamp bestStamp = getBestStamp(nodeWithNewStamp); 348 assert bestStamp != null; 349 350 if (currentEndMap != null) { 351 Stamp otherEndsStamp = currentEndMap.get(nodeWithNewStamp); 352 if (otherEndsStamp == null) { 353 // No stamp registered in one of the previously processed 354 // ends => skip. 355 continue; 356 } 357 bestStamp = bestStamp.meet(otherEndsStamp); 358 } 359 360 if (nodeWithNewStamp.stamp(NodeView.DEFAULT).tryImproveWith(bestStamp) == null) { 361 // No point in registering the stamp. 362 } else { 363 endMap.put(nodeWithNewStamp, bestStamp); 364 } 365 } 366 } 367 currentBlock = currentBlock.getDominator(); 368 } 369 370 endMaps.put(merge, endMap); 371 } 372 } 373 } 374 375 private static Block getBlock(ValueNode node, NodeMap<Block> blockToNodeMap) { 376 if (node instanceof PhiNode) { 377 PhiNode phiNode = (PhiNode) node; 378 return blockToNodeMap.get(phiNode.merge()); 379 } 380 return blockToNodeMap.get(node); 381 } 382 383 protected void processUnary(UnaryNode node) { 384 ValueNode value = node.getValue(); 385 Stamp bestStamp = getBestStamp(value); 386 Stamp newStamp = node.foldStamp(bestStamp); 387 if (!checkReplaceWithConstant(newStamp, node)) { 388 if (!bestStamp.equals(value.stamp(NodeView.DEFAULT))) { 389 ValueNode newNode = node.canonical(rawCanonicalizerTool); 390 if (newNode != node) { 391 // Canonicalization successfully triggered. 392 if (newNode != null && !newNode.isAlive()) { 393 newNode = graph.addWithoutUniqueWithInputs(newNode); 394 } 395 node.replaceAndDelete(newNode); 396 GraphUtil.tryKillUnused(value); 397 return; 398 } 399 } 400 registerNewValueStamp(node, newStamp); 401 } 402 } 403 404 protected boolean checkReplaceWithConstant(Stamp newStamp, ValueNode node) { 405 Constant constant = newStamp.asConstant(); 406 if (constant != null && !(node instanceof ConstantNode)) { 407 ConstantNode stampConstant = ConstantNode.forConstant(newStamp, constant, metaAccess, graph); 408 debug.log("RawConditionElimination: constant stamp replaces %1s with %1s", node, stampConstant); 409 counterConstantReplacements.increment(debug); 410 node.replaceAtUsages(InputType.Value, stampConstant); 411 GraphUtil.tryKillUnused(node); 412 return true; 413 } 414 return false; 415 } 416 417 protected void processBinary(BinaryNode node) { 418 419 ValueNode x = node.getX(); 420 ValueNode y = node.getY(); 421 422 Stamp xStamp = getBestStamp(x); 423 Stamp yStamp = getBestStamp(y); 424 Stamp newStamp = node.foldStamp(xStamp, yStamp); 425 if (!checkReplaceWithConstant(newStamp, node)) { 426 427 if (!xStamp.equals(x.stamp(NodeView.DEFAULT)) || !yStamp.equals(y.stamp(NodeView.DEFAULT))) { 428 // At least one of the inputs has an improved stamp => attempt to canonicalize 429 // based on that improvement. 430 ValueNode newNode = node.canonical(rawCanonicalizerTool); 431 if (newNode != node) { 432 // Canonicalization successfully triggered. 433 if (newNode != null && !newNode.isAlive()) { 434 newNode = graph.addWithoutUniqueWithInputs(newNode); 435 } 436 node.replaceAndDelete(newNode); 437 GraphUtil.tryKillUnused(x); 438 GraphUtil.tryKillUnused(y); 439 return; 440 } 441 } 442 443 registerNewValueStamp(node, newStamp); 444 } 445 } 446 447 protected void processIntegerSwitch(IntegerSwitchNode node) { 448 Stamp bestStamp = getBestStamp(node.value()); 449 if (node.tryRemoveUnreachableKeys(null, bestStamp)) { 450 debug.log("\t Canonicalized integer switch %s for value %s and stamp %s", node, node.value(), bestStamp); 451 counterCanonicalizedSwitches.increment(debug); 452 } 453 } 454 455 protected void processIf(IfNode node) { 456 TriState result = tryProveCondition(node.condition()); 457 if (result != TriState.UNKNOWN) { 458 boolean isTrue = (result == TriState.TRUE); 459 AbstractBeginNode survivingSuccessor = node.getSuccessor(isTrue); 460 survivingSuccessor.replaceAtUsages(null); 461 survivingSuccessor.replaceAtPredecessor(null); 462 node.replaceAtPredecessor(survivingSuccessor); 463 GraphUtil.killCFG(node); 464 465 counterIfsKilled.increment(debug); 466 } 467 } 468 469 protected void processConditional(ConditionalNode node) { 470 TriState result = tryProveCondition(node.condition()); 471 if (result != TriState.UNKNOWN) { 472 boolean isTrue = (result == TriState.TRUE); 473 counterConditionalsKilled.increment(debug); 474 node.replaceAndDelete(isTrue ? node.trueValue() : node.falseValue()); 475 } else { 476 Stamp trueStamp = getBestStamp(node.trueValue()); 477 Stamp falseStamp = getBestStamp(node.falseValue()); 478 registerNewStamp(node, trueStamp.meet(falseStamp)); 479 } 480 } 481 482 protected TriState tryProveCondition(LogicNode condition) { 483 Stamp conditionStamp = this.getBestStamp(condition); 484 if (conditionStamp == StampFactory.tautology()) { 485 return TriState.TRUE; 486 } else if (conditionStamp == StampFactory.contradiction()) { 487 return TriState.FALSE; 488 } 489 490 if (condition instanceof UnaryOpLogicNode) { 491 UnaryOpLogicNode unaryOpLogicNode = (UnaryOpLogicNode) condition; 492 return unaryOpLogicNode.tryFold(this.getBestStamp(unaryOpLogicNode.getValue())); 493 } else if (condition instanceof BinaryOpLogicNode) { 494 BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) condition; 495 return binaryOpLogicNode.tryFold(this.getBestStamp(binaryOpLogicNode.getX()), this.getBestStamp(binaryOpLogicNode.getY())); 496 } 497 498 return TriState.UNKNOWN; 499 } 500 501 protected void processAbstractBegin(AbstractBeginNode beginNode) { 502 Node predecessor = beginNode.predecessor(); 503 if (predecessor instanceof IfNode) { 504 IfNode ifNode = (IfNode) predecessor; 505 boolean negated = (ifNode.falseSuccessor() == beginNode); 506 LogicNode condition = ifNode.condition(); 507 registerNewCondition(condition, negated); 508 } else if (predecessor instanceof IntegerSwitchNode) { 509 IntegerSwitchNode integerSwitchNode = (IntegerSwitchNode) predecessor; 510 registerIntegerSwitch(beginNode, integerSwitchNode); 511 } 512 } 513 514 private void registerIntegerSwitch(AbstractBeginNode beginNode, IntegerSwitchNode integerSwitchNode) { 515 registerNewValueStamp(integerSwitchNode.value(), integerSwitchNode.getValueStampForSuccessor(beginNode)); 516 } 517 518 protected void registerNewCondition(LogicNode condition, boolean negated) { 519 if (condition instanceof UnaryOpLogicNode) { 520 UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) condition; 521 ValueNode value = unaryLogicNode.getValue(); 522 Stamp newStamp = unaryLogicNode.getSucceedingStampForValue(negated); 523 registerNewValueStamp(value, newStamp); 524 } else if (condition instanceof BinaryOpLogicNode) { 525 BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) condition; 526 ValueNode x = binaryOpLogicNode.getX(); 527 ValueNode y = binaryOpLogicNode.getY(); 528 Stamp xStamp = getBestStamp(x); 529 Stamp yStamp = getBestStamp(y); 530 registerNewValueStamp(x, binaryOpLogicNode.getSucceedingStampForX(negated, xStamp, yStamp)); 531 registerNewValueStamp(y, binaryOpLogicNode.getSucceedingStampForY(negated, xStamp, yStamp)); 532 } 533 registerCondition(condition, negated); 534 } 535 536 protected void registerCondition(LogicNode condition, boolean negated) { 537 registerNewStamp(condition, negated ? StampFactory.contradiction() : StampFactory.tautology()); 538 } 539 540 protected boolean registerNewValueStamp(ValueNode value, Stamp newStamp) { 541 if (newStamp != null && !value.isConstant()) { 542 Stamp currentStamp = getBestStamp(value); 543 Stamp betterStamp = currentStamp.tryImproveWith(newStamp); 544 if (betterStamp != null) { 545 registerNewStamp(value, betterStamp); 546 return true; 547 } 548 } 549 return false; 550 } 551 552 protected void registerNewStamp(ValueNode value, Stamp newStamp) { 553 counterStampsRegistered.increment(debug); 554 debug.log("\t Saving stamp for node %s stamp %s", value, newStamp); 555 ValueNode originalNode = value; 556 stampMap.setAndGrow(originalNode, new StampElement(newStamp, stampMap.getAndGrow(originalNode))); 557 undoOperations.push(originalNode); 558 } 559 560 protected Stamp getBestStamp(ValueNode value) { 561 ValueNode originalNode = value; 562 if (!value.isAlive()) { 563 return value.stamp(NodeView.DEFAULT); 564 } 565 566 StampElement currentStamp = stampMap.getAndGrow(originalNode); 567 if (currentStamp == null) { 568 return value.stamp(NodeView.DEFAULT); 569 } 570 return currentStamp.getStamp(); 571 } 572 573 @Override 574 public Integer enter(Block b) { 575 int mark = undoOperations.size(); 576 blockActionStart.put(b, mark); 577 for (Node n : schedule.getBlockToNodesMap().get(b)) { 578 if (n.isAlive()) { 579 processNode(n); 580 } 581 } 582 return mark; 583 } 584 585 @Override 586 public void exit(Block b, Integer state) { 587 int mark = state; 588 while (undoOperations.size() > mark) { 589 Node node = undoOperations.pop(); 590 if (node.isAlive()) { 591 stampMap.set(node, stampMap.get(node).getParent()); 592 } 593 } 594 } 595 596 } 597 598 public FixReadsPhase(boolean replaceInputsWithConstants, Phase schedulePhase) { 599 this.replaceInputsWithConstants = replaceInputsWithConstants; 600 this.schedulePhase = schedulePhase; 601 } 602 603 @Override 604 protected void run(StructuredGraph graph, LowTierContext context) { 605 schedulePhase.apply(graph); 606 ScheduleResult schedule = graph.getLastSchedule(); 607 FixReadsClosure fixReadsClosure = new FixReadsClosure(); 608 for (Block block : schedule.getCFG().getBlocks()) { 609 fixReadsClosure.processNodes(block, schedule); 610 } 611 if (GraalOptions.RawConditionalElimination.getValue(graph.getOptions())) { 612 schedule.getCFG().visitDominatorTree(createVisitor(graph, schedule, context), false); 613 } 614 graph.setAfterFixReadPhase(true); 615 } 616 617 public static class RawCEPhase extends BasePhase<LowTierContext> { 618 619 private final boolean replaceInputsWithConstants; 620 621 public RawCEPhase(boolean replaceInputsWithConstants) { 622 this.replaceInputsWithConstants = replaceInputsWithConstants; 623 } 624 625 @Override 626 protected CharSequence getName() { 627 return "RawCEPhase"; 628 } 629 630 @Override 631 protected void run(StructuredGraph graph, LowTierContext context) { 632 if (GraalOptions.RawConditionalElimination.getValue(graph.getOptions())) { 633 SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST, true); 634 schedulePhase.apply(graph); 635 ScheduleResult schedule = graph.getLastSchedule(); 636 schedule.getCFG().visitDominatorTree(new RawConditionalEliminationVisitor(graph, schedule, context.getMetaAccess(), replaceInputsWithConstants), false); 637 } 638 } 639 } 640 641 protected ControlFlowGraph.RecursiveVisitor<?> createVisitor(StructuredGraph graph, ScheduleResult schedule, PhaseContext context) { 642 return new RawConditionalEliminationVisitor(graph, schedule, context.getMetaAccess(), replaceInputsWithConstants); 643 } 644 645 protected static final class StampElement { 646 private final Stamp stamp; 647 private final StampElement parent; 648 649 public StampElement(Stamp stamp, StampElement parent) { 650 this.stamp = stamp; 651 this.parent = parent; 652 } 653 654 public StampElement getParent() { 655 return parent; 656 } 657 658 public Stamp getStamp() { 659 return stamp; 660 } 661 662 @Override 663 public String toString() { 664 StringBuilder result = new StringBuilder(); 665 result.append(stamp); 666 if (this.parent != null) { 667 result.append(" ("); 668 result.append(this.parent.toString()); 669 result.append(")"); 670 } 671 return result.toString(); 672 } 673 } 674 675 public void setReplaceInputsWithConstants(boolean replaceInputsWithConstants) { 676 this.replaceInputsWithConstants = replaceInputsWithConstants; 677 } 678 }