Beispiel #1
0
 public String toString() {
   StringBuffer buf = new StringBuffer("{RG ");
   int len = refs.size();
   if (len > 3) len = 3;
   for (int i = 0; i < len; i++) {
     if (i > 0) buf.append(',');
     buf.append(refs.elementAt(i));
   }
   if (len < refs.size()) buf.append(", ...");
   buf.append('}');
   return buf.toString();
 }
Beispiel #2
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;
  }
 public void getDeclList(AbstractCollection<Declaration> varList) {
   int l = argList.size();
   for (int i = 0; i < l; i++) {
     Expression exp = argList.get(i);
     exp.getDeclList(varList);
   }
 }
Beispiel #4
0
  /**
   * Compute the entry points for a list of hyperblocks to be inserted into the HFG. This method
   * also removes the link between hbStart and all its successors.
   */
  public static HashMap<Instruction, Hyperblock> computeEntries(
      Hyperblock hbStart, Vector<Hyperblock> hbs) {
    HashMap<Instruction, Hyperblock> entries = new HashMap<Instruction, Hyperblock>(203);

    // Find the entry points in the new hyperblocks.

    int l = hbs.size();
    for (int i = 0; i < l; i++) {
      Hyperblock hb = hbs.elementAt(i);
      PredicateBlock start = hb.getFirstBlock();
      Instruction first = start.getFirstInstruction();

      entries.put(first, hb);
    }

    // The successors of the original hyperblock are also entry points.

    int sl = hbStart.numOutEdges();
    for (int i = 0; i < sl; i++) {
      Hyperblock succ = (Hyperblock) hbStart.getOutEdge(0);
      PredicateBlock start = succ.getFirstBlock();
      Instruction first = start.getFirstInstruction();

      hbStart.deleteOutEdge(succ);
      succ.deleteInEdge(hbStart);
      entries.put(first, succ);
    }

    return entries;
  }
Beispiel #5
0
  private Cost computeRefCostSum(LoopHeaderChord loop, Vector<RefGroup> refGroups) {
    Cost lc = new Cost();
    int l = refGroups.size();
    for (int i = 0; i < l; i++) {
      RefGroup rg = refGroups.elementAt(i);
      SubscriptExpr se = rg.getRepresentative();
      Cost cost = computeRefCost(loop, se);

      if (cost == null) continue;

      lc.add(cost);
    }
    return lc;
  }
Beispiel #6
0
  /**
   * Find a split point for a block with spills. <br>
   * We know the hyperblock was legal before the insertion of spill code. Return the "deepest" split
   * point in the predicate flow graph, or if there are no split points, the block with the most
   * instructions.
   */
  private PredicateBlock findSplitPointSpills(Hyperblock hb) {
    Vector<PredicateBlock> wl = new Vector<PredicateBlock>();

    PredicateBlock start = hb.getFirstBlock();
    PredicateBlock last = hb.getLastBlock();
    PredicateBlock biggest = null;
    PredicateBlock splitPoint = null;
    int biggestSize = 0;

    if (start.numOutEdges() == 0) {
      return start;
    }

    start.nextVisit();
    start.setVisited();
    wl.add(start);

    // Find the block with the most "real" instructions.
    // We do not include fanout, nulls, or spill code.

    while (!wl.isEmpty()) {
      int sl = wl.size();
      for (int i = 0; i < sl; i++) {
        PredicateBlock block = wl.get(i);
        int size = 0;

        for (Instruction inst = block.getFirstInstruction(); inst != null; inst = inst.getNext()) {
          size++; // TODO?  Should we use the real size of the instruction?
        }

        if (size >= biggestSize) {
          if (block != last) {
            biggestSize = size;
            biggest = block;
          }
        }

        if (block.isSplitPoint() && (block != start)) {
          splitPoint = block;
        }
      }

      wl = hb.getNextPFGLevel(wl);
    }

    return (splitPoint != null) ? splitPoint : biggest;
  }
Beispiel #7
0
  /**
   * Create a representation of a range from min to max.
   *
   * @param min is the lower bound
   * @param max is the upper bound
   */
  public static Bound create(Expression min, Expression max) {
    if (max == null) {
      if (min == null) return noBound;
      max = LiteralMap.put(0x7ffffff, Machine.currentMachine.getIntegerCalcType());
    }

    if (bounds != null) {
      int n = bounds.size();
      for (int i = 0; i < n; i++) {
        Bound ta = bounds.elementAt(i);

        if (!min.equivalent(ta.min)) continue;

        if (!max.equivalent(ta.max)) continue;

        return ta;
      }
    }
    Bound a = new Bound(min, max);
    return a;
  }
Beispiel #8
0
  public void perform() {
    if (trace) System.out.println("** LP " + scribble.getRoutineDecl().getName());

    LoopHeaderChord lt = scribble.getLoopTree();
    Vector<LoopHeaderChord> innerLoops = lt.getInnerLoops();

    for (int li = 0; li < innerLoops.size(); li++) {
      LoopHeaderChord loop = innerLoops.elementAt(li);
      InductionVar ivar = loop.getPrimaryInductionVar();

      if (trace) System.out.println("   lp " + loop.nestedLevel() + " " + loop);

      if ((ivar == null) || !loop.isPerfectlyNested()) {
        innerLoops.addVectors(loop.getInnerLoops());
        continue;
      }

      if (loop.nestedLevel() < 2) // no need to check permutation for a simple nest
      continue;

      tryPermute(loop);
    }
  }
Beispiel #9
0
  /** Find the predicate block in a hyperblock to split. */
  private PredicateBlock findSplitPoint(Hyperblock hb) {
    Vector<PredicateBlock> wl = new Vector<PredicateBlock>();

    int totalSize = hb.getFanout() + hb.getBlockSize();
    int splits = (totalSize / Trips2Machine.maxBlockSize) + 1;
    int splitSize = totalSize / splits;
    int hbSize = 0;
    PredicateBlock start = hb.getFirstBlock();
    PredicateBlock lastUnpredicated = null;
    int lastUnpredicatedHBSize = 0;

    assert (hb.numSpills() == 0) : "This method should not be called for blocks with spills.";

    start.nextVisit();
    start.setVisited();
    wl.add(start);

    while (!wl.isEmpty()) {
      int l = wl.size();
      int levelSize = 0;
      int levelLSID = 0;

      // Compute the statistics for this level of the PFG.

      for (int i = 0; i < l; i++) {
        PredicateBlock block = wl.get(i);
        int blockSize = block.getBlockSize() + block.getFanout();
        int id = block.maxLSID();

        levelSize += blockSize;
        if (id > levelLSID) {
          levelLSID = id;
        }

        // Remember the block and the hyperblock size if this block is unpredicated
        // and not the special exit block.
        // TODO - Can we remove the restriction on being the last block now?

        if (!block.isPredicated()) {
          if (block.numOutEdges() > 0) {
            if (lastUnpredicatedHBSize < (blockSize + hbSize)) {
              lastUnpredicatedHBSize = blockSize + hbSize;
              lastUnpredicated = block;
            }
          }
        }
      }

      // Determine if all the blocks can be added to the hyperblock.

      int size = hbSize + levelSize;
      if ((size > Trips2Machine.maxBlockSize) || (levelLSID >= Trips2Machine.maxLSQEntries)) {
        break;
      }

      hbSize = size;
      wl = hb.getNextPFGLevel(wl);
    }

    assert (!wl.isEmpty()) : "This block does not need to be split?";

    // If there is only one unpredicated block in the level and it is
    // not the special exit block use it.  Or if this is the only
    // block in the PFG.

    int l = wl.size();
    if (l == 1) {
      PredicateBlock block = wl.get(0);
      if (!block.isPredicated()) {
        if ((start == block) || (block.numOutEdges() > 0)) {
          // System.out.println("block");
          return block;
        }
      }
    }

    // Is there a last known unpredicated block of adequate size use it.

    if (lastUnpredicated != null) {
      if (lastUnpredicatedHBSize >= splitSize) {
        // System.out.println("*** last unpred is greater than split sz " + splitSize);
        return lastUnpredicated;
      }
    }

    // Try to find a parent that's unpredicated unless the parent is
    // the first block.

    for (int i = 0; i < l; i++) {
      PredicateBlock block = wl.get(i);
      int pl = block.numInEdges();
      for (int j = 0; j < pl; j++) {
        PredicateBlock pred = (PredicateBlock) block.getInEdge(j);
        if (!pred.isPredicated() && pred.numInEdges() > 1) {
          // System.out.println("unpred parent not start");
          return pred;
        }
      }
    }

    // Reverse if-convert the largest block in this level which is not
    // an exit.  Although this seems like a good idea, there is not
    // always enough room in the hyperblock to fanout the live-outs to
    // the write instructions.  Don't do this for now. -- Aaron

    PredicateBlock candidate = null;
    int largest = 0;
    //     for (int i = 0; i < l; i++) {
    //       PredicateBlock block = (PredicateBlock) wl.get(i);
    //       int            bsize = block.getBlockSize() + block.getFanout() + block.getSpillSize();
    //       if ((bsize > largest) && (block.numBranches() == 0)) {
    //         largest   = bsize;
    //         candidate = block;
    //       }
    //     }

    //     if (candidate != null) {
    //       //System.out.println("level no exit");
    //       return candidate;
    //     }

    // Reverse if-convert a parent which is not start.
    // Prefer parents that are split points.

    for (int i = 0; i < l; i++) {
      PredicateBlock block = wl.get(i);
      int pl = block.numInEdges();
      for (int j = 0; j < pl; j++) {
        PredicateBlock pred = (PredicateBlock) block.getInEdge(j);
        if (pred != start) {
          if (pred.isSplitPoint()) {
            // System.out.println("pred out isSplit not start");
            return pred;
          }
          candidate = pred;
        }
      }
    }

    if (candidate != null) {
      // System.out.println("pred out not start");
      return candidate;
    }

    // Reverse if-convert the largest successor of start without an exit.

    largest = 0;
    for (int i = 0; i < start.numOutEdges(); i++) {
      PredicateBlock block = (PredicateBlock) start.getOutEdge(i);
      int bsize = block.getBlockSize() + block.getFanout() + block.getSpillSize();
      if ((bsize > largest) && !block.hasBranch()) {
        largest = bsize;
        candidate = block;
      }
    }

    if (candidate != null) {
      // System.out.println("start successor no exit");
      return candidate;
    }

    // System.out.println("1st start successor ?");
    return (PredicateBlock) start.getOutEdge(0);
  }
Beispiel #10
0
 /** Return the number of AST children of this node. */
 public int numChildren() {
   return 1 + labels.size();
 }
Beispiel #11
0
 public final int numLabels() {
   return labels.size();
 }
Beispiel #12
0
  /**
   * Compute the reference groups for this loop. Two array references are in the same group with
   * respect to this loop if - there is a loop-independent dependence between them, or - the
   * dependence distance(dependence vector entry dl) for this loop is less than some constant
   * *dist*, and all other dependence vector entries are 0. - the two array refer to the same array
   * and differ by at most *dist2* in the first subscript dimension, where d is less than or equal
   * to the cache line size in terms of array elements. All other subscripts must be identical.
   * Notes: Here we assume dist1 = dist2 = 2
   */
  private void computeRefGroups(
      int level,
      int dist1,
      int dist2,
      Table<Declaration, SubscriptExpr> arrayRefs,
      Vector<RefGroup> refGroups) {
    if (arrayRefs == null) return;

    Enumeration<Declaration> ek = arrayRefs.keys();
    while (ek.hasMoreElements()) {
      VariableDecl vd = (VariableDecl) ek.nextElement();
      String s = vd.getName(); // array name
      Object[] v = arrayRefs.getRowArray(vd); // vector of SubscriptExpr's
      int vi = v.length;

      for (int j = vi - 1; j >= 0; j--) {
        SubscriptExpr sr = (SubscriptExpr) v[j];
        Vector<LoopHeaderChord> allRelatedLoops =
            sr.allRelatedLoops(); // ** Incorrect when something like a[(j+i][j]
        int arls = allRelatedLoops.size();
        int firstsub = arls - 1; // ** Making an invalid assumption here

        // Process the list of references r' with which r has a data
        // dependence, and  r is the source(data flows from r to r').

        RefGroup rg = new RefGroup(s, sr);
        Object[] edges = graph.getEdges(sr);
        int len = edges.length;

        for (int i = 0; i < len; i++) {
          DDEdge edge = (DDEdge) edges[i];

          if (edge.isSpatial()) continue;

          // Condition(1)-(a) in McKinley's paper

          if (edge.isLoopIndependentDependency()) { // add rP to the RefGroup of r:
            rg.add(edge);
            continue;
          }

          // Condition(1)-(b) in McKinley's paper

          computeEdgeRefs(edge, rg, level, dist1);

          if (arls <= 0) continue;

          // Condition(2) in McKinley's paper
          // rlevel is the level of the loop related to the first subscript.

          int rlevel = allRelatedLoops.elementAt(firstsub).getNestedLevel();

          computeEdgeRefs(edge, rg, rlevel, dist2);
        }

        boolean isInExistingRefGroups = false;
        int rgl = refGroups.size();
        for (int i = 0; i < rgl; i++) {
          RefGroup rg2 = refGroups.elementAt(i);
          if (!rg2.getName().equals(s)) continue;

          isInExistingRefGroups = rg2.contains(rg);

          if (isInExistingRefGroups) {
            rg2.add(rg);
            break;
          }
        }

        if (!isInExistingRefGroups) refGroups.addElement(rg);
      }
    }
  }
Beispiel #13
0
 private void printRefGroups(Vector<RefGroup> refGroups) {
   for (int i = 0; i < refGroups.size(); i++) {
     RefGroup rg = refGroups.elementAt(i);
     System.out.println(rg);
   }
 }
Beispiel #14
0
    public SubscriptExpr getRepresentative() {
      if (refs.size() > 0) return (SubscriptExpr) refs.elementAt(0);

      return null;
    }
Beispiel #15
0
  /** Reverse if-convert the given predicate block from the hyperblock. */
  private void reverseIfConvert(Hyperblock hb, PredicateBlock start) {
    Stack<Node> wl = WorkArea.<Node>getStack("reverseIfConvert");
    Stack<PredicateBlock> reverse = WorkArea.<PredicateBlock>getStack("reverseIfConvert");
    Vector<PredicateBlock> blocks = new Vector<PredicateBlock>();
    Vector<Hyperblock> hbs = new Vector<Hyperblock>();

    // Find the blocks which need to be reverse if-converted.

    start.nextVisit();
    start.setVisited();
    wl.add(start);

    while (!wl.isEmpty()) {
      PredicateBlock block = (PredicateBlock) wl.pop();
      block.pushOutEdges(wl);

      for (int i = 0; i < block.numInEdges(); i++) {
        PredicateBlock pred = (PredicateBlock) block.getInEdge(i);
        if (!pred.visited()) {
          blocks.add(block);
          break;
        } else if (blocks.contains(pred) && block.numInEdges() > 1) {
          blocks.add(block);
          break;
        }
      }
    }

    // Order the blocks to reverse if-convert based on their depth from the root.

    PredicateBlock head = hb.getFirstBlock();
    Vector<PredicateBlock> wl2 = new Vector<PredicateBlock>();

    head.nextVisit();
    head.setVisited();
    wl2.add(head);

    while (!wl2.isEmpty()) {
      int l = wl2.size();

      for (int i = 0; i < l; i++) {
        PredicateBlock block = wl2.get(i);
        if (blocks.contains(block)) {
          blocks.remove(block);
          reverse.push(block);
        }
      }

      wl2 = hb.getNextPFGLevel(wl2);
    }

    // Remove the special "dummy" last block from the PFG.

    PredicateBlock last = hb.getLastBlock();
    assert (last.numOutEdges() == 0 && !last.isPredicated());

    if (last.getFirstInstruction() == null) {
      for (int i = last.numInEdges() - 1; i > -1; i--) {
        PredicateBlock pred = (PredicateBlock) last.getInEdge(i);
        pred.deleteOutEdge(last);
        last.deleteInEdge(pred);
      }
      reverse.remove(last);
    }

    // Reverse if-convert.

    while (!reverse.isEmpty()) {
      PredicateBlock block = reverse.pop();
      Hyperblock hbn = reverseIfConvertBlock(block);

      hbs.add(hbn);
      workingSet.add(hbn);
    }

    // Update the PFG.

    hb.updateLastBlock();
    hb.invalidateDomination(); // The dominators are now invalid.

    // Insert the new hyperblocks in the HFG.

    HashMap<Instruction, Hyperblock> entries = computeEntries(hb, hbs);
    hbs.add(hb);
    Hyperblock.computeHyperblockFlowGraph(hbs, entries);

    // Update the return block.  Since 'hbs' is an ordered list, the
    // first element in the list is the hyperblock with the return
    // because this was the original tail of the PFG which was reverse
    // if-converted.

    if (hb == gen.getReturnBlock()) {
      gen.setReturnBlock(hbs.firstElement());
    }

    WorkArea.<Node>returnStack(wl);
    WorkArea.<PredicateBlock>returnStack(reverse);
  }
Beispiel #16
0
  private void tryPermute(LoopHeaderChord topLoop) {
    Vector<LoopHeaderChord> loopNest = topLoop.getTightlyNestedLoops();
    if (loopNest == null) return;

    int loopDepth = loopNest.size();
    LoopHeaderChord bottom = loopNest.get(loopDepth - 1);
    if (!unsafe && !legalLoop(bottom)) return;

    // Set the loop costs for the loops in a loop nest. The cost for a loop is
    // the cost of executing the nest with that loop in the innermost nesting.

    Table<Declaration, SubscriptExpr> arrayRefs = new Table<Declaration, SubscriptExpr>();
    if (!topLoop.getSubscriptsRecursive(arrayRefs)) return;

    graph = topLoop.getDDGraph(false);
    if (graph == null) return;

    if (trace) System.out.println("     " + graph);

    int[] loopIndex = new int[loopDepth];
    Cost[] loopCostList = new Cost[loopDepth];
    Vector<RefGroup> refGroups = new Vector<RefGroup>(20);

    for (int i = 0; i < loopDepth; i++) {
      LoopHeaderChord loop = loopNest.elementAt(i);
      if (trace) System.out.println("   " + i + " " + loop);

      computeRefGroups(loop.getNestedLevel(), 2, 2, arrayRefs, refGroups);

      Cost lc = computeRefCostSum(loop, refGroups);
      if (trace) System.out.println("   " + i + " " + lc);

      loopCostList[i] = lc;
      loopIndex[i] = i; // the outtermost loop is at position 0

      Cost tp = tripProduct(loopNest, loop);
      if (trace) System.out.println("   " + i + " " + tp);
      lc.multiply(tp);
      if (trace) System.out.println("   " + i + " " + lc);
    }

    boolean permuted = sortByCost(loopCostList, loopIndex);

    if (!permuted) return;
    if (trace) {
      System.out.print("   permute " + loopDepth);
      System.out.print(":");
      for (int i = 0; i < loopIndex.length; i++) System.out.print(" " + loopIndex[i]);
      System.out.println("");
    }

    int[][] ddVec = getDDVec(arrayRefs, loopDepth);
    if (trace) printDDInfo(ddVec, loopDepth);

    if (!isLegal(loopIndex, ddVec)) return;

    if (trace) System.out.println("   permute " + loopDepth);

    int[] rank = new int[loopDepth];

    // We will do sorting on the rank vector, which corresponds to the interchange we need.

    for (int i = 0; i < loopDepth; i++) {
      int loopNum = loopIndex[i];
      rank[loopNum] = i;
    }

    if (trace) printOrder(rank);

    boolean changed = true;

    while (changed) {
      changed = false;

      for (int i = 0; i < loopDepth - 1; i++) {
        int j = i + 1;
        int outerRank = rank[i];
        int innerRank = rank[j];

        if (innerRank >= outerRank) continue;

        LoopHeaderChord innerLoop = loopNest.elementAt(j);
        LoopHeaderChord outerLoop = loopNest.elementAt(i);

        if (!outerLoop.isDDComplete() || outerLoop.inhibitLoopPermute()) continue;

        if (!innerLoop.isDDComplete() || innerLoop.inhibitLoopPermute()) continue;

        changed = true;

        rank[i] = innerRank;
        rank[j] = outerRank;

        loopNest.setElementAt(innerLoop, i);
        loopNest.setElementAt(outerLoop, j);

        performLoopInterchange(innerLoop, outerLoop);
      }
    }
  }
 /** Return the number of AST children of this node. */
 public int numChildren() {
   return 1 + argList.size();
 }