/** This is the heart of the algorithm. See sources for details. */ private void step2() { if (DEBUG) { System.out.println(" ******* Beginning STEP 2 *******\n"); } // Visit each node in reverse DFS order, except for the root, which // has number 1 // for i=n downto 2 for (int i = DFSCounter; i > 1; i--) { // block = vertex[i] BasicBlock block = vertex[i]; LTDominatorInfo blockInfo = LTDominatorInfo.getInfo(block); if (DEBUG) { System.out.println(" Processing: " + block + "\n"); } // visit each predecessor BasicBlockEnumeration e = getPrevNodes(block); while (e.hasMoreElements()) { BasicBlock prev = e.next(); if (DEBUG) { System.out.println(" Inspecting prev: " + prev); } BasicBlock u = EVAL(prev); // if semi(u) < semi(block) then semi(block) = semi(u) // u may be part of infinite loop and thus, is unreachable from the exit node. // In this case, it will have a semi value of 0. Thus, we screen for it here if (getSemi(u) != 0 && getSemi(u) < getSemi(block)) { blockInfo.setSemiDominator(getSemi(u)); } } // while prev // add "block" to bucket(vertex(semi(block))); LTDominatorInfo.getInfo(vertex[blockInfo.getSemiDominator()]).addToBucket(block); // LINK(parent(block), block) LINK(blockInfo.getParent(), block); // foreach block2 in bucket(parent(block)) do java.util.Iterator<BasicBlock> bucketEnum = LTDominatorInfo.getInfo(getParent(block)).getBucketIterator(); while (bucketEnum.hasNext()) { BasicBlock block2 = bucketEnum.next(); // u = EVAL(block2) BasicBlock u = EVAL(block2); // if semi(u) < semi(block2) then // dom(block2) = u // else // dom(block2) = parent(block) if (getSemi(u) < getSemi(block2)) { LTDominatorInfo.getInfo(block2).setDominator(u); } else { LTDominatorInfo.getInfo(block2).setDominator(getParent(block)); } } // while bucket has more elements } // for DFSCounter .. 1 } // method
/** * Adds edge (block1, block2) to the forest maintained as an auxiliary data structure. This * implementation uses path compression and results in a O(e * alpha(e,n)) complexity, where e is * the number of edges in the CFG and n is the number of nodes. * * @param block1 a basic block corresponding to the source of the new edge * @param block2 a basic block corresponding to the source of the new edge */ private void LINK(BasicBlock block1, BasicBlock block2) { if (DEBUG) { System.out.println(" Linking " + block1 + " with " + block2); } BasicBlock s = block2; while (getSemi(getLabel(block2)) < getSemi(getLabel(getChild(s)))) { if (getSize(s) + getSize(getChild(getChild(s))) >= 2 * getSize(getChild(s))) { LTDominatorInfo.getInfo(getChild(s)).setAncestor(s); LTDominatorInfo.getInfo(s).setChild(getChild(getChild(s))); } else { LTDominatorInfo.getInfo(getChild(s)).setSize(getSize(s)); LTDominatorInfo.getInfo(s).setAncestor(getChild(s)); s = getChild(s); } } LTDominatorInfo.getInfo(s).setLabel(getLabel(block2)); LTDominatorInfo.getInfo(block1).setSize(getSize(block1) + getSize(block2)); if (getSize(block1) < 2 * getSize(block2)) { BasicBlock tmp = s; s = getChild(block1); LTDominatorInfo.getInfo(block1).setChild(tmp); } while (s != null) { LTDominatorInfo.getInfo(s).setAncestor(block1); s = getChild(s); } if (DEBUG) { System.out.println(" .... done"); } }
/** * Print the nodes that dominate each basic block * * @param ir the IR */ private void printResults(IR ir) { if (forward) { System.out.println( "Results of dominators computation for method " + ir.method.getName() + "\n"); System.out.println(" Here's the CFG:"); System.out.println(ir.cfg); System.out.println("\n\n Here's the Dominator Info:"); } else { System.out.println( "Results of Post-Dominators computation for method " + ir.method.getName() + "\n"); System.out.println(" Here's the CFG:"); System.out.println(ir.cfg); System.out.println("\n\n Here's the Post-Dominator Info:"); } for (Enumeration<BasicBlock> bbEnum = cfg.basicBlocks(); bbEnum.hasMoreElements(); ) { BasicBlock block = bbEnum.nextElement(); // We don't compute a result for the exit node for forward direction if (!forward || !block.isExit()) { System.out.println( "Dominators of " + block + ":" + LTDominatorInfo.getInfo(block).dominators(block, ir)); } } System.out.println("\n"); }
/** * This recursive method performs the path compression * * @param block the block of interest */ private void compress(BasicBlock block) { if (getAncestor(getAncestor(block)) != null) { compress(getAncestor(block)); LTDominatorInfo blockInfo = LTDominatorInfo.getInfo(block); if (getSemi(getLabel(getAncestor(block))) < getSemi(getLabel(block))) { blockInfo.setLabel(getLabel(getAncestor(block))); } blockInfo.setAncestor(getAncestor(getAncestor(block))); } }
/** This final step sets the final dominator information. */ private void step3() { // Visit each node in DFS order, except for the root, which has number 1 for (int i = 2; i <= DFSCounter; i++) { BasicBlock block = vertex[i]; // if dom(block) != vertex[semi(block)] if (getDom(block) != vertex[getSemi(block)]) { // dom(block) = dom(dom(block)) LTDominatorInfo.getInfo(block).setDominator(getDom(getDom(block))); } } }
/** * Get the child node for this block * * @param block * @return the child node */ private BasicBlock getChild(BasicBlock block) { return LTDominatorInfo.getInfo(block).getChild(); }
/** * returns the size associated with the block * * @param block * @return the size of the block or 0 if the block is null */ private int getSize(BasicBlock block) { if (block == null) { return 0; } return LTDominatorInfo.getInfo(block).getSize(); }
/** * returns the label for the passed block or null if the block is null * * @param block * @return the label for the passed block or null if the block is null */ private BasicBlock getLabel(BasicBlock block) { if (block == null) { return null; } return LTDominatorInfo.getInfo(block).getLabel(); }
/** * Returns the ancestor for the passed block * * @param block * @return the ancestor for the passed block */ private BasicBlock getAncestor(BasicBlock block) { return LTDominatorInfo.getInfo(block).getAncestor(); }
/** * Returns the parent for the passed block * * @param block * @return the parent for the passed block */ private BasicBlock getParent(BasicBlock block) { return LTDominatorInfo.getInfo(block).getParent(); }
/** * The non-recursive depth-first numbering code called from Step 1. The recursive version was too * costly on the toba benchmark on Linux/IA32. * * @param block the basic block to process */ protected void DFS(BasicBlock block) { // push node on to the emulated activation stack push(block); recurse: while (!empty()) { block = peek(); if (DEBUG) { System.out.println(" Processing (peek)" + block); } if (block == null) { if (DEBUG) { System.out.println(" Popping"); } pop(); // return continue; } // The current Dominance Frontier and SSA code assumes the exit // node will not be part of the (regular) dominator solution. // To avoid this from happening we screen it out here for forward CFG // // However, it really shouldn't be in the CFG, if it isn't a node! if (forward && block == cfg.exit()) { if (DEBUG) { System.out.println(" Popping"); } pop(); // return continue; } BasicBlockEnumeration e; e = LTDominatorInfo.getInfo(block).getEnum(); if (e == null) { if (DEBUG) { System.out.println(" Initial processing of " + block); } DFSCounter++; LTDominatorInfo.getInfo(block).setSemiDominator(DFSCounter); vertex[DFSCounter] = block; e = getNextNodes(block); } else { if (DEBUG) { System.out.println(" Resuming processing of " + block); } } while (e.hasMoreElements()) { BasicBlock next = e.next(); if (DEBUG) { System.out.println(" Inspecting next node: " + next); } // We treat the exit node as not being in the CFG for forward direction if (forward && next.isExit()) { continue; // inner loop } if (getSemi(next) == 0) { LTDominatorInfo.getInfo(next).setParent(block); // simulate a recursive call // save the enumeration state for resumption later LTDominatorInfo.getInfo(block).setEnum(e); if (DEBUG) { System.out.println(" Pushing" + next); } push(next); continue recurse; } } // while more nexts // "Pop" from the emulated activiation stack if (DEBUG) { System.out.println(" Popping"); } pop(); } // while stack not empty loop }