/** * 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; }
/** 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); } }
/** 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); }
/** 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); }
/** The constructor. */ public BlockSplitter(Trips2Generator gen) { this.gen = gen; this.regs = (Trips2RegisterSet) gen.getRegisterSet(); this.workingSet = new Vector<Hyperblock>(); }