/** * 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; }
/** * Return the location in the block to split. Use the last spill store point found as the location * to split. If no spill store is found, use the last instruction that does not cause a violation. * This method will throw an exception if not split location is found. */ private final Instruction findSplitLocation(Hyperblock hb, PredicateBlock block, int chunkSize) { int cLSID = 0; int cSize = 0; Instruction splitLocation = null; boolean foundSpillPoint = false; BitVect mov3 = new BitVect(); Stack<Node> wl = new Stack<Node>(); IntMap<Integer> uses = new IntMap<Integer>(37); IntMap<Vector<Integer>> targets = hb.computeTargets(wl, mov3); for (Instruction inst = block.getFirstInstruction(); inst != null; inst = inst.getNext()) { if (inst.isMarker()) { continue; } if (inst.isLoad() || inst.isStore()) { int id = (inst.isLoad() ? ((LoadInstruction) inst).getLSQid() : ((StoreInstruction) inst).getLSQid()); if (id > cLSID) { cLSID = id; } } cSize += block.estimateNumInstructions(inst); cSize += block.estimateFanout(inst, targets, uses, mov3); if ((cLSID >= Trips2Machine.maxLSQEntries) || (cSize >= chunkSize)) { if (splitLocation == null) { splitLocation = inst; // Possible when splitting because of spills. } assert (splitLocation != block.getLastInstruction()) : "How is the last instruction the split location?"; return splitLocation; } if (inst.isSpillStorePoint()) { splitLocation = inst; foundSpillPoint = true; } if (!foundSpillPoint) { splitLocation = inst; } } throw new scale.common.InternalError("Could not find a location to split the predicate block."); }
/** Split a hyperblock. */ private void splitHyperblock(Hyperblock hb) { PredicateBlock block = (hb.numSpills() > 0) ? findSplitPointSpills(hb) : findSplitPoint(hb); if (block.isPredicated()) { reverseIfConvert(hb, block); return; } int bsize = block.getBlockSize() + block.getFanout() + block.getSpillSize(); if (bsize > Trips2Machine.maxBlockSize) { splitBlock(hb, block); return; } if (block.maxLSID() >= Trips2Machine.maxLSQEntries) { splitBlock(hb, block); return; } if (block.numInEdges() == 0) { splitBlock(hb, block); return; } reverseIfConvert(hb, block); }
/** Split an unpredicated predicate block. */ private void splitBlock(Hyperblock hb, PredicateBlock block) { int chunkSize = (block.getBlockSize() + block.getFanout()) / 2; int maxChunk = (int) (Trips2Machine.maxBlockSize * MAXFILL); if (chunkSize > maxChunk) { chunkSize = maxChunk; } Instruction splitLocation = findSplitLocation(hb, block, chunkSize); PredicateBlock start = block.cut(splitLocation, gen); Hyperblock nhb = new Hyperblock(start, regs); // Insert the new hyperblock into the HFG. for (int i = hb.numOutEdges() - 1; i > -1; i--) { Hyperblock out = (Hyperblock) hb.getOutEdge(i); out.replaceInEdge(hb, nhb); hb.deleteOutEdge(out); nhb.addOutEdge(out); } hb.addOutEdge(nhb); nhb.addInEdge(hb); workingSet.add(nhb); hb.invalidateDomination(); hb.findLastBlock(); hb.determinePredicatesBranches(); nhb.findLastBlock(); nhb.determinePredicatesBranches(); // Update the return block if it has changed. if (gen.getReturnBlock() == hb) { gen.setReturnBlock(nhb); } }
/** * 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; }
/** 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); }
/** Remove all the predicates which are not defined in the hyperblock. */ private BitVect removePredicates(PredicateBlock start) { BitVect predicates = new BitVect(); Stack<Node> wl = new Stack<Node>(); // Determine all the predicates defined outside this hyperblock. start.nextVisit(); start.setVisited(); wl.add(start); while (!wl.isEmpty()) { PredicateBlock block = (PredicateBlock) wl.pop(); block.pushOutEdges(wl); for (Instruction inst = block.getFirstInstruction(); inst != null; inst = inst.getNext()) { if (inst.isMarker()) { continue; } if (inst.isBranch()) { continue; } if (((TripsInstruction) inst).definesPredicate()) { predicates.set(inst.getDestRegister()); } } } // Remove the predicates. start.nextVisit(); start.setVisited(); wl.add(start); while (!wl.isEmpty()) { PredicateBlock block = (PredicateBlock) wl.pop(); block.pushOutEdges(wl); if (!block.isPredicated()) { continue; } int rp = block.getPredicate(); if (predicates.get(rp)) { continue; } block.removePredicates(); for (Instruction inst = block.getFirstInstruction(); inst != null; inst = inst.getNext()) { inst.removePredicates(); } } return predicates; }
/** * Reverse if-convert a block. Return a new hyperblock starting with the reverse if-converted * block or null. */ private Hyperblock reverseIfConvertBlock(PredicateBlock block) { int rp = block.getPredicate(); boolean sense = block.isPredicatedOnTrue(); // Insert a label at the beginning of the block. TripsLabel lab = (TripsLabel) gen.createLabel(); gen.updateLabelIndex(lab); block.insertInstructionAtHead(lab); // Insert a branch to this block in its predecessors. for (int i = block.numInEdges() - 1; i > -1; i--) { PredicateBlock pred = (PredicateBlock) block.getInEdge(i); int rpPred = pred.getPredicate(); boolean sensePred = pred.isPredicatedOnTrue(); boolean needThunk = true; // Check if we need a thunk. if (!block.isPredicated()) { needThunk = false; } else if (pred.numOutEdges() == 1) { needThunk = false; } else if ((rp == rpPred) && (sense == sensePred)) { needThunk = false; } // Create a branch to the label and insert it. if (needThunk) { TripsBranch br = new TripsBranch(Opcodes.BRO, lab, 1, rp, sense); PredicateBlock thunk = new PredicateBlock(rp, sense); br.addTarget(lab, 0); thunk.appendInstruction(br); pred.addOutEdge(thunk); thunk.addInEdge(pred); } else { TripsBranch br = new TripsBranch(Opcodes.BRO, lab, 1, rpPred, sensePred); br.addTarget(lab, 0); pred.appendInstruction(br); } pred.deleteOutEdge(block); block.deleteInEdge(pred); } blocksReverseIfConvertedCount++; // Create the new hyperblock. BitVect predicates = removePredicates(block); Hyperblock hnew = new Hyperblock(block, predicates, regs); hnew.updateLastBlock(); return hnew; }
/** 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); }