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