/** * 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; }
/** 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); }