soot.toolkits.graph.CytronDominanceFrontier Maven / Gradle / Ivy
package soot.toolkits.graph;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2003 Navindra Umanee
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Class to compute the DominanceFrontier using Cytron's celebrated efficient algorithm.
*
* @author Navindra Umanee
* @see Efficiently Computing Static Single Assignment Form and
* the Control Dependence Graph
**/
public class CytronDominanceFrontier implements DominanceFrontier {
protected DominatorTree dt;
protected Map, List>> nodeToFrontier;
public CytronDominanceFrontier(DominatorTree dt) {
this.dt = dt;
nodeToFrontier = new HashMap, List>>();
for (DominatorNode head : dt.getHeads()) {
bottomUpDispatch(head);
}
for (N gode : dt.graph) {
DominatorNode dode = dt.fetchDode(gode);
if (dode == null) {
throw new RuntimeException("dode == null");
} else if (!isFrontierKnown(dode)) {
System.out.print("'");
System.out.print(dode);
System.out.println("'");
throw new RuntimeException("frontier did not have dode> ");
}
}
}
public List> getDominanceFrontierOf(DominatorNode node) {
List> frontier = nodeToFrontier.get(node);
if (frontier == null) {
throw new RuntimeException("Frontier not defined for node: " + node);
}
return new ArrayList>(frontier);
}
protected boolean isFrontierKnown(DominatorNode node) {
return nodeToFrontier.containsKey(node);
}
/**
* Make sure we visit children first. This is reverse topological order.
**/
protected void bottomUpDispatch(DominatorNode node) {
// *** FIXME: It's annoying that this algorithm is so
// *** inefficient in that in traverses the tree from the head
// *** to the tail before it does anything.
if (isFrontierKnown(node)) {
return;
}
for (DominatorNode child : dt.getChildrenOf(node)) {
if (!isFrontierKnown(child)) {
bottomUpDispatch(child);
}
}
processNode(node);
}
/**
* Calculate dominance frontier for a set of basic blocks.
*
*
* Uses the algorithm of Cytron et al., TOPLAS Oct. 91:
*
*
* for each X in a bottom-up traversal of the dominator tree do
*
* DF(X) < - null
* for each Y in Succ(X) do
* if (idom(Y)!=X) then DF(X) <- DF(X) U Y
* end
* for each Z in {idom(z) = X} do
* for each Y in DF(Z) do
* if (idom(Y)!=X) then DF(X) <- DF(X) U Y
* end
* end
*
**/
protected void processNode(DominatorNode node) {
List> dominanceFrontier = new ArrayList>();
// local
{
Iterator> succsIt = dt.getSuccsOf(node).iterator();
while (succsIt.hasNext()) {
DominatorNode succ = succsIt.next();
if (!dt.isImmediateDominatorOf(node, succ)) {
dominanceFrontier.add(succ);
}
}
}
// up
{
for (DominatorNode child : dt.getChildrenOf(node)) {
for (DominatorNode childFront : getDominanceFrontierOf(child)) {
if (!dt.isImmediateDominatorOf(node, childFront)) {
dominanceFrontier.add(childFront);
}
}
}
}
nodeToFrontier.put(node, dominanceFrontier);
}
}