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(); }
/** * 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); } }
/** * 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; }
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; }
/** * 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; }
/** * 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; }
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); } }
/** 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); }
/** Return the number of AST children of this node. */ public int numChildren() { return 1 + labels.size(); }
public final int numLabels() { return labels.size(); }
/** * 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); } } }
private void printRefGroups(Vector<RefGroup> refGroups) { for (int i = 0; i < refGroups.size(); i++) { RefGroup rg = refGroups.elementAt(i); System.out.println(rg); } }
public SubscriptExpr getRepresentative() { if (refs.size() > 0) return (SubscriptExpr) refs.elementAt(0); return null; }
/** 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); }
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(); }