@SuppressWarnings("try")
    public void run(
        StructuredGraph graph, SchedulingStrategy selectedStrategy, boolean immutableGraph) {
      // assert GraphOrder.assertNonCyclicGraph(graph);
      cfg = ControlFlowGraph.compute(graph, true, true, true, false);

      NodeMap<Block> currentNodeMap = graph.createNodeMap();
      NodeBitMap visited = graph.createNodeBitMap();
      BlockMap<List<Node>> earliestBlockToNodesMap = new BlockMap<>(cfg);
      this.nodeToBlockMap = currentNodeMap;
      this.blockToNodesMap = earliestBlockToNodesMap;

      scheduleEarliestIterative(
          earliestBlockToNodesMap, currentNodeMap, visited, graph, immutableGraph);

      if (selectedStrategy != SchedulingStrategy.EARLIEST) {
        // For non-earliest schedules, we need to do a second pass.
        BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg);
        for (Block b : cfg.getBlocks()) {
          latestBlockToNodesMap.put(b, new ArrayList<Node>());
        }

        BlockMap<ArrayList<FloatingReadNode>> watchListMap =
            calcLatestBlocks(
                selectedStrategy,
                currentNodeMap,
                earliestBlockToNodesMap,
                visited,
                latestBlockToNodesMap,
                immutableGraph);
        sortNodesLatestWithinBlock(
            cfg,
            earliestBlockToNodesMap,
            latestBlockToNodesMap,
            currentNodeMap,
            watchListMap,
            visited);

        assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap);
        assert MemoryScheduleVerification.check(cfg.getStartBlock(), latestBlockToNodesMap);

        this.blockToNodesMap = latestBlockToNodesMap;

        cfg.setNodeToBlock(currentNodeMap);
      }

      graph.setLastSchedule(
          new ScheduleResult(this.cfg, this.nodeToBlockMap, this.blockToNodesMap));
    }
Exemple #2
0
  public LoopsData(final StructuredGraph graph) {
    cfg =
        Debug.scope(
            "ControlFlowGraph",
            new Callable<ControlFlowGraph>() {

              @Override
              public ControlFlowGraph call() throws Exception {
                return ControlFlowGraph.compute(graph, true, true, true, true);
              }
            });
    for (Loop lirLoop : cfg.getLoops()) {
      LoopEx ex = new LoopEx(lirLoop, this);
      lirLoopToEx.put(lirLoop, ex);
      loopBeginToEx.put(ex.loopBegin(), ex);
    }
  }
 private static void sortNodesLatestWithinBlock(
     ControlFlowGraph cfg,
     BlockMap<List<Node>> earliestBlockToNodesMap,
     BlockMap<List<Node>> latestBlockToNodesMap,
     NodeMap<Block> currentNodeMap,
     BlockMap<ArrayList<FloatingReadNode>> watchListMap,
     NodeBitMap visited) {
   for (Block b : cfg.getBlocks()) {
     sortNodesLatestWithinBlock(
         b,
         earliestBlockToNodesMap,
         latestBlockToNodesMap,
         currentNodeMap,
         watchListMap,
         visited);
   }
 }
 private static boolean verifySchedule(
     ControlFlowGraph cfg, BlockMap<List<Node>> blockToNodesMap, NodeMap<Block> nodeMap) {
   for (Block b : cfg.getBlocks()) {
     List<Node> nodes = blockToNodesMap.get(b);
     for (Node n : nodes) {
       assert n.isAlive();
       assert nodeMap.get(n) == b;
       StructuredGraph g = (StructuredGraph) n.graph();
       if (g.hasLoops()
           && g.getGuardsStage() == GuardsStage.AFTER_FSA
           && n instanceof DeoptimizeNode) {
         assert b.getLoopDepth() == 0 : n;
       }
     }
   }
   return true;
 }
    private static void processStack(
        ControlFlowGraph cfg,
        BlockMap<List<Node>> blockToNodes,
        NodeMap<Block> nodeToBlock,
        NodeBitMap visited,
        BitSet floatingReads,
        NodeStack stack) {
      Block startBlock = cfg.getStartBlock();
      while (!stack.isEmpty()) {
        Node current = stack.peek();
        if (visited.checkAndMarkInc(current)) {

          // Push inputs and predecessor.
          Node predecessor = current.predecessor();
          if (predecessor != null) {
            stack.push(predecessor);
          }

          if (current instanceof PhiNode) {
            processStackPhi(stack, (PhiNode) current);
          } else if (current instanceof ProxyNode) {
            processStackProxy(stack, (ProxyNode) current);
          } else if (current instanceof FrameState) {
            processStackFrameState(stack, current);
          } else {
            current.pushInputs(stack);
          }
        } else {
          stack.pop();
          if (nodeToBlock.get(current) == null) {
            Block curBlock = cfg.blockFor(current);
            if (curBlock == null) {
              assert current.predecessor() == null && !(current instanceof FixedNode)
                  : "The assignment of blocks to fixed nodes is already done when constructing the cfg.";
              Block earliest = startBlock;
              for (Node input : current.inputs()) {
                Block inputEarliest = nodeToBlock.get(input);
                if (inputEarliest == null) {
                  assert current instanceof FrameState
                          && input instanceof StateSplit
                          && ((StateSplit) input).stateAfter() == current
                      : current;
                } else {
                  assert inputEarliest != null;
                  if (inputEarliest.getEndNode() == input) {
                    // This is the last node of the block.
                    if (current instanceof FrameState
                        && input instanceof StateSplit
                        && ((StateSplit) input).stateAfter() == current) {
                      // Keep regular inputEarliest.
                    } else if (input instanceof ControlSplitNode) {
                      inputEarliest =
                          nodeToBlock.get(((ControlSplitNode) input).getPrimarySuccessor());
                    } else {
                      assert inputEarliest.getSuccessorCount() == 1;
                      assert !(input instanceof AbstractEndNode);
                      // Keep regular inputEarliest
                    }
                  }
                  if (earliest.getDominatorDepth() < inputEarliest.getDominatorDepth()) {
                    earliest = inputEarliest;
                  }
                }
              }
              curBlock = earliest;
            }
            assert curBlock != null;
            addNode(blockToNodes, curBlock, current);
            nodeToBlock.set(current, curBlock);
            if (current instanceof FloatingReadNode) {
              FloatingReadNode floatingReadNode = (FloatingReadNode) current;
              if (curBlock.canKill(floatingReadNode.getLocationIdentity())) {
                floatingReads.set(curBlock.getId());
              }
            }
          }
        }
      }
    }
    private void scheduleEarliestIterative(
        BlockMap<List<Node>> blockToNodes,
        NodeMap<Block> nodeToBlock,
        NodeBitMap visited,
        StructuredGraph graph,
        boolean immutableGraph) {

      BitSet floatingReads = new BitSet(cfg.getBlocks().length);

      // Add begin nodes as the first entry and set the block for phi nodes.
      for (Block b : cfg.getBlocks()) {
        AbstractBeginNode beginNode = b.getBeginNode();
        ArrayList<Node> nodes = new ArrayList<>();
        nodeToBlock.set(beginNode, b);
        nodes.add(beginNode);
        blockToNodes.put(b, nodes);

        if (beginNode instanceof AbstractMergeNode) {
          AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode;
          for (PhiNode phi : mergeNode.phis()) {
            nodeToBlock.set(phi, b);
          }
        } else if (beginNode instanceof LoopExitNode) {
          LoopExitNode loopExitNode = (LoopExitNode) beginNode;
          for (ProxyNode proxy : loopExitNode.proxies()) {
            nodeToBlock.set(proxy, b);
          }
        }
      }

      NodeStack stack = new NodeStack();

      // Start analysis with control flow ends.
      Block[] reversePostOrder = cfg.reversePostOrder();
      for (int j = reversePostOrder.length - 1; j >= 0; --j) {
        Block b = reversePostOrder[j];
        FixedNode endNode = b.getEndNode();
        if (isFixedEnd(endNode)) {
          stack.push(endNode);
          nodeToBlock.set(endNode, b);
        }
      }

      processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack);

      // Visit back input edges of loop phis.
      boolean changed;
      boolean unmarkedPhi;
      do {
        changed = false;
        unmarkedPhi = false;
        for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) {
          for (PhiNode phi : loopBegin.phis()) {
            if (visited.isMarked(phi)) {
              for (int i = 0; i < loopBegin.getLoopEndCount(); ++i) {
                Node node = phi.valueAt(i + loopBegin.forwardEndCount());
                if (node != null && !visited.isMarked(node)) {
                  changed = true;
                  stack.push(node);
                  processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack);
                }
              }
            } else {
              unmarkedPhi = true;
            }
          }
        }

        /*
         * the processing of one loop phi could have marked a previously checked loop phi,
         * therefore this needs to be iterative.
         */
      } while (unmarkedPhi && changed);

      // Check for dead nodes.
      if (!immutableGraph && visited.getCounter() < graph.getNodeCount()) {
        for (Node n : graph.getNodes()) {
          if (!visited.isMarked(n)) {
            n.clearInputs();
            n.markDeleted();
          }
        }
      }

      // Add end nodes as the last nodes in each block.
      for (Block b : cfg.getBlocks()) {
        FixedNode endNode = b.getEndNode();
        if (isFixedEnd(endNode)) {
          if (endNode != b.getBeginNode()) {
            addNode(blockToNodes, b, endNode);
          }
        }
      }

      if (!floatingReads.isEmpty()) {
        for (Block b : cfg.getBlocks()) {
          if (floatingReads.get(b.getId())) {
            resortEarliestWithinBlock(b, blockToNodes, nodeToBlock, visited);
          }
        }
      }

      assert MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes);
    }
    @SuppressFBWarnings(
        value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
        justification = "false positive found by findbugs")
    private BlockMap<ArrayList<FloatingReadNode>> calcLatestBlocks(
        SchedulingStrategy strategy,
        NodeMap<Block> currentNodeMap,
        BlockMap<List<Node>> earliestBlockToNodesMap,
        NodeBitMap visited,
        BlockMap<List<Node>> latestBlockToNodesMap,
        boolean immutableGraph) {
      BlockMap<ArrayList<FloatingReadNode>> watchListMap = new BlockMap<>(cfg);
      Block[] reversePostOrder = cfg.reversePostOrder();
      for (int j = reversePostOrder.length - 1; j >= 0; --j) {
        Block currentBlock = reversePostOrder[j];
        List<Node> blockToNodes = earliestBlockToNodesMap.get(currentBlock);
        LocationSet killed = null;
        int previousIndex = blockToNodes.size();
        for (int i = blockToNodes.size() - 1; i >= 0; --i) {
          Node currentNode = blockToNodes.get(i);
          assert currentNodeMap.get(currentNode) == currentBlock;
          assert !(currentNode instanceof PhiNode) && !(currentNode instanceof ProxyNode);
          assert visited.isMarked(currentNode);
          if (currentNode instanceof FixedNode) {
            // For these nodes, the earliest is at the same time the latest block.
          } else {
            Block latestBlock = null;

            LocationIdentity constrainingLocation = null;
            if (currentNode instanceof FloatingReadNode) {
              // We are scheduling a floating read node => check memory
              // anti-dependencies.
              FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode;
              LocationIdentity location = floatingReadNode.getLocationIdentity();
              if (location.isMutable()) {
                // Location can be killed.
                constrainingLocation = location;
                if (currentBlock.canKill(location)) {
                  if (killed == null) {
                    killed = new LocationSet();
                  }
                  fillKillSet(killed, blockToNodes.subList(i + 1, previousIndex));
                  previousIndex = i;
                  if (killed.contains(location)) {
                    // Earliest block kills location => we need to stay within
                    // earliest block.
                    latestBlock = currentBlock;
                  }
                }
              }
            }

            if (latestBlock == null) {
              // We are not constraint within earliest block => calculate optimized
              // schedule.
              calcLatestBlock(
                  currentBlock,
                  strategy,
                  currentNode,
                  currentNodeMap,
                  constrainingLocation,
                  watchListMap,
                  latestBlockToNodesMap,
                  visited,
                  immutableGraph);
            } else {
              selectLatestBlock(
                  currentNode,
                  currentBlock,
                  latestBlock,
                  currentNodeMap,
                  watchListMap,
                  constrainingLocation,
                  latestBlockToNodesMap);
            }
          }
        }
      }
      return watchListMap;
    }
  @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);
  }