private void processFixedGuardAndMerge(
     FixedGuardNode fixedGuard,
     PhaseContext context,
     CompareNode compare,
     ValueNode x,
     ValuePhiNode xPhi,
     ValueNode y,
     ValuePhiNode yPhi,
     AbstractMergeNode merge) {
   List<EndNode> mergePredecessors = merge.cfgPredecessors().snapshot();
   for (int i = 0; i < mergePredecessors.size(); ++i) {
     AbstractEndNode mergePredecessor = mergePredecessors.get(i);
     if (!mergePredecessor.isAlive()) {
       break;
     }
     Constant xs;
     if (xPhi == null) {
       xs = x.asConstant();
     } else {
       xs = xPhi.valueAt(mergePredecessor).asConstant();
     }
     Constant ys;
     if (yPhi == null) {
       ys = y.asConstant();
     } else {
       ys = yPhi.valueAt(mergePredecessor).asConstant();
     }
     if (xs != null
         && ys != null
         && compare
                 .condition()
                 .foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue())
             == fixedGuard.isNegated()) {
       visitDeoptBegin(
           AbstractBeginNode.prevBegin(mergePredecessor),
           fixedGuard.getAction(),
           fixedGuard.getReason(),
           fixedGuard.getSpeculation(),
           fixedGuard.graph());
     }
   }
 }
  @Override
  protected void run(final StructuredGraph graph, PhaseContext context) {
    assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies";
    if (graph.getNodes(DeoptimizeNode.TYPE).isEmpty()) {
      return;
    }
    for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.TYPE)) {
      assert d.isAlive();
      visitDeoptBegin(
          AbstractBeginNode.prevBegin(d), d.action(), d.reason(), d.getSpeculation(), graph);
    }

    if (context != null) {
      for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.TYPE)) {
        trySplitFixedGuard(fixedGuard, context);
      }
    }

    new DeadCodeEliminationPhase(Optional).apply(graph);
  }
  private void processFixedGuardAndPhis(
      FixedGuardNode fixedGuard,
      PhaseContext context,
      CompareNode compare,
      ValueNode x,
      ValuePhiNode xPhi,
      ValueNode y,
      ValuePhiNode yPhi) {
    AbstractBeginNode pred = AbstractBeginNode.prevBegin(fixedGuard);
    if (pred instanceof AbstractMergeNode) {
      AbstractMergeNode merge = (AbstractMergeNode) pred;
      if (xPhi != null && xPhi.merge() != merge) {
        return;
      }
      if (yPhi != null && yPhi.merge() != merge) {
        return;
      }

      processFixedGuardAndMerge(fixedGuard, context, compare, x, xPhi, y, yPhi, merge);
    }
  }
  private void visitDeoptBegin(
      AbstractBeginNode deoptBegin,
      DeoptimizationAction deoptAction,
      DeoptimizationReason deoptReason,
      JavaConstant speculation,
      StructuredGraph graph) {
    if (deoptBegin.predecessor() instanceof AbstractBeginNode) {
      /* Walk up chains of LoopExitNodes to the "real" BeginNode that leads to deoptimization. */
      visitDeoptBegin(
          (AbstractBeginNode) deoptBegin.predecessor(),
          deoptAction,
          deoptReason,
          speculation,
          graph);
      return;
    }

    if (deoptBegin instanceof AbstractMergeNode) {
      AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
      Debug.log("Visiting %s", mergeNode);
      FixedNode next = mergeNode.next();
      while (mergeNode.isAlive()) {
        AbstractEndNode end = mergeNode.forwardEnds().first();
        AbstractBeginNode newBeginNode = findBeginNode(end);
        visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph);
      }
      assert next.isAlive();
      AbstractBeginNode newBeginNode = findBeginNode(next);
      visitDeoptBegin(newBeginNode, deoptAction, deoptReason, speculation, graph);
      return;
    } else if (deoptBegin.predecessor() instanceof IfNode) {
      IfNode ifNode = (IfNode) deoptBegin.predecessor();
      AbstractBeginNode otherBegin = ifNode.trueSuccessor();
      LogicNode conditionNode = ifNode.condition();
      FixedGuardNode guard =
          graph.add(
              new FixedGuardNode(
                  conditionNode,
                  deoptReason,
                  deoptAction,
                  speculation,
                  deoptBegin == ifNode.trueSuccessor()));
      FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
      AbstractBeginNode survivingSuccessor;
      if (deoptBegin == ifNode.trueSuccessor()) {
        survivingSuccessor = ifNode.falseSuccessor();
      } else {
        survivingSuccessor = ifNode.trueSuccessor();
      }
      graph.removeSplitPropagate(ifNode, survivingSuccessor);

      Node newGuard = guard;
      if (survivingSuccessor instanceof LoopExitNode) {
        newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
      }
      survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);

      Debug.log(
          "Converting deopt on %-5s branch of %s to guard for remaining branch %s.",
          deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin);
      FixedNode next = pred.next();
      pred.setNext(guard);
      guard.setNext(next);
      survivingSuccessor.simplify(simplifierTool);
      return;
    }

    // We could not convert the control split - at least cut off control flow after the split.
    FixedWithNextNode deoptPred = deoptBegin;
    FixedNode next = deoptPred.next();

    if (!(next instanceof DeoptimizeNode)) {
      DeoptimizeNode newDeoptNode =
          graph.add(new DeoptimizeNode(deoptAction, deoptReason, speculation));
      deoptPred.setNext(newDeoptNode);
      assert deoptPred == newDeoptNode.predecessor();
      GraphUtil.killCFG(next);
    }
  }
Example #5
0
  @Test
  public void testImplies() {
    StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES);

    EndNode trueEnd = graph.add(new EndNode());
    EndNode falseEnd = graph.add(new EndNode());

    AbstractBeginNode trueBegin = graph.add(new BeginNode());
    trueBegin.setNext(trueEnd);
    AbstractBeginNode falseBegin = graph.add(new BeginNode());
    falseBegin.setNext(falseEnd);

    IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
    graph.start().setNext(ifNode);

    AbstractMergeNode merge = graph.add(new MergeNode());
    merge.addForwardEnd(trueEnd);
    merge.addForwardEnd(falseEnd);
    ReturnNode returnNode = graph.add(new ReturnNode(null));
    merge.setNext(returnNode);

    dumpGraph(graph);

    ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);

    List<Block> blocks = cfg.getBlocks();
    // check number of blocks
    assertDeepEquals(4, blocks.size());

    // check block - node assignment
    assertDeepEquals(blocks.get(0), cfg.blockFor(graph.start()));
    assertDeepEquals(blocks.get(0), cfg.blockFor(ifNode));
    assertDeepEquals(blocks.get(1), cfg.blockFor(trueBegin));
    assertDeepEquals(blocks.get(1), cfg.blockFor(trueEnd));
    assertDeepEquals(blocks.get(2), cfg.blockFor(falseBegin));
    assertDeepEquals(blocks.get(2), cfg.blockFor(falseEnd));
    assertDeepEquals(blocks.get(3), cfg.blockFor(merge));
    assertDeepEquals(blocks.get(3), cfg.blockFor(returnNode));

    // check postOrder
    Iterator<Block> it = cfg.postOrder().iterator();
    for (int i = blocks.size() - 1; i >= 0; i--) {
      assertTrue(it.hasNext());
      Block b = it.next();
      assertDeepEquals(blocks.get(i), b);
    }

    // check dominators
    assertDominator(blocks.get(0), null);
    assertDominator(blocks.get(1), blocks.get(0));
    assertDominator(blocks.get(2), blocks.get(0));
    assertDominator(blocks.get(3), blocks.get(0));

    // check dominated
    assertDominatedSize(blocks.get(0), 3);
    assertDominatedSize(blocks.get(1), 0);
    assertDominatedSize(blocks.get(2), 0);
    assertDominatedSize(blocks.get(3), 0);

    // check postdominators
    assertPostdominator(blocks.get(0), blocks.get(3));
    assertPostdominator(blocks.get(1), blocks.get(3));
    assertPostdominator(blocks.get(2), blocks.get(3));
    assertPostdominator(blocks.get(3), null);
  }
Example #6
0
    @SuppressWarnings("try")
    private AnchoringNode process(
        final Block b, final NodeBitMap activeGuards, final AnchoringNode startAnchor) {

      final LoweringToolImpl loweringTool =
          new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode());

      // Lower the instructions of this block.
      List<Node> nodes = schedule.nodesFor(b);
      for (Node node : nodes) {

        if (node.isDeleted()) {
          // This case can happen when previous lowerings deleted nodes.
          continue;
        }

        // Cache the next node to be able to reconstruct the previous of the next node
        // after lowering.
        FixedNode nextNode = null;
        if (node instanceof FixedWithNextNode) {
          nextNode = ((FixedWithNextNode) node).next();
        } else {
          nextNode = loweringTool.lastFixedNode().next();
        }

        if (node instanceof Lowerable) {
          Collection<Node> unscheduledUsages = null;
          assert (unscheduledUsages = getUnscheduledUsages(node)) != null;
          Mark preLoweringMark = node.graph().getMark();
          try (DebugCloseable s = node.graph().withNodeContext(node)) {
            ((Lowerable) node).lower(loweringTool);
          }
          if (loweringTool.guardAnchor.asNode().isDeleted()) {
            // TODO nextNode could be deleted but this is not currently supported
            assert nextNode.isAlive();
            loweringTool.guardAnchor = AbstractBeginNode.prevBegin(nextNode);
          }
          assert checkPostNodeLowering(node, loweringTool, preLoweringMark, unscheduledUsages);
        }

        if (!nextNode.isAlive()) {
          // can happen when the rest of the block is killed by lowering
          // (e.g. by an unconditional deopt)
          break;
        } else {
          Node nextLastFixed = nextNode.predecessor();
          if (!(nextLastFixed instanceof FixedWithNextNode)) {
            // insert begin node, to have a valid last fixed for next lowerable node.
            // This is about lowering a FixedWithNextNode to a control split while this
            // FixedWithNextNode is followed by some kind of BeginNode.
            // For example the when a FixedGuard followed by a loop exit is lowered to a
            // control-split + deopt.
            AbstractBeginNode begin = node.graph().add(new BeginNode());
            nextLastFixed.replaceFirstSuccessor(nextNode, begin);
            begin.setNext(nextNode);
            nextLastFixed = begin;
          }
          loweringTool.setLastFixedNode((FixedWithNextNode) nextLastFixed);
        }
      }
      return loweringTool.getCurrentGuardAnchor();
    }