Exemple #1
0
  /**
   * This routine is called to split blocks during register allocation. At this point we know that
   * the block was legal before the spill stores and loads were inserted. For every hyperblock with
   * spills that is no longer legal, we pick its largest predicate block and split that in half. One
   * half is then placed into a new hyperblock.
   *
   * <p>The case that was causing trouble results from the classic diamond-shaped predicate flow
   * graph:
   *
   * <pre>
   *     a
   *    / \
   *   b   c
   *    \ /
   *     d
   * </pre>
   *
   * where predicate block <code>a</code> contains most of the instructions, blocks <code>b</code>
   * and <code>c</code> each contain a predicated branch, and block <code>d</code> is empty. Because
   * of spilling, the hyperblock was too big but all of the predicate blocks were legal. As a result
   * we attempted to split block <code>d</code> which did no good.
   *
   * @param blocks is a list of hyperblocks that have had spills inserted
   * @return true if a block was split
   */
  public final boolean splitBlocksWithSpills(Hyperblock hbStart, Vector<Hyperblock> blocks) {
    // If all the blocks with spills are legal we are done.

    boolean illegal = false;
    int bs = blocks.size();
    for (int i = 0; i < bs; i++) {
      Hyperblock hb = blocks.get(i);
      if (!hb.isLegalBlock(true)) {
        illegal = true;
      }
    }

    if (!illegal) {
      return false;
    }

    // Remove any spill code because the register allocator will run again.
    // And remove any blocks which are legal from the set to split.

    for (int i = bs - 1; i > -1; i--) {
      Hyperblock hb = blocks.get(i);
      if (hb.isLegalBlock(true)) {
        blocks.remove(i);
      }
      hb.removeSpillCode();
      workingSet.add(hb);
    }

    // Split hyperblocks that have violations.

    int bl = blocks.size();
    for (int i = bl - 1; i > -1; i--) {
      Hyperblock hb = blocks.remove(i);
      splitHyperblock(hb);
    }

    // The register allocator and block splitter are going to run again.
    // Analyze all the hyperblocks that were created or changed.

    DataflowAnalysis df = new DataflowAnalysis(hbStart, regs);
    df.computeLiveness3();

    int sl = workingSet.size();
    for (int i = sl - 1; i > -1; i--) {
      Hyperblock hb = workingSet.remove(i);
      hb.enterSSA();
      hb.analyzeLeaveSSA();
    }

    return true;
  }
Exemple #2
0
  /** The main routine for block splitting. */
  public final void split(Hyperblock hbStart) {
    Stack<Node> wl = WorkArea.<Node>getStack("split");
    DataflowAnalysis df = new DataflowAnalysis(hbStart, regs);
    int trips = 0;

    // Add all the hyperblocks to the working set.

    hbStart.nextVisit();
    hbStart.setVisited();
    wl.push(hbStart);

    while (!wl.isEmpty()) {
      Hyperblock hb = (Hyperblock) wl.pop();
      hb.pushOutEdges(wl);
      workingSet.add(hb);
    }

    // Split the hyperblocks.

    while (!workingSet.isEmpty()) {
      df.computeLiveness3();
      wl.addAll(workingSet);

      while (!wl.isEmpty()) {
        Hyperblock hb = (Hyperblock) wl.pop();
        hb.enterSSA();
        hb.analyzeLeaveSSA();

        if (!hb.isLegalBlock(true)) {
          splitHyperblock(hb);
        } else {
          workingSet.remove(hb);
        }
      }

      if ((++trips % WARN_SPLIT_ATTEMPTS) == 0) {
        System.err.println(
            "** Warning: the block splitter has run "
                + trips
                + " times for "
                + gen.getCurrentRoutine().getName()
                + "().");
      }
    }

    WorkArea.<Node>returnStack(wl);
  }