/**
*
*/
package soottocfg.cfg.optimization;
import java.util.HashSet;
import org.jgrapht.Graphs;
import soottocfg.cfg.method.CfgBlock;
import soottocfg.cfg.method.CfgEdge;
import soottocfg.cfg.method.Method;
import soottocfg.cfg.statement.Statement;
/**
* @author schaef
*
*/
public class FoldStraighLineSeq {
/**
*
*/
public FoldStraighLineSeq() {
// TODO Auto-generated constructor stub
}
/**
* Searches for two blocks b1 -> b2 s.t. there is
* exactly one edge between b1 and b2. Then it folds
* b2 into b1, by copying all its statements and outgoing
* edges.
* @param m
*/
public void fold(Method m) {
boolean fixedpoint = false;
while (!fixedpoint) {
fixedpoint = true;
for (CfgBlock b : new HashSet<CfgBlock>(m.vertexSet())) {
if (m.outDegreeOf(b)==1) {
CfgBlock suc = Graphs.successorListOf(m, b).get(0);
if (foldIfPossible(m, b, suc)) {
m.removeVertex(suc);
fixedpoint = false;
break;
}
}
}
}
}
private boolean foldIfPossible(Method m, CfgBlock b1, CfgBlock b2) {
if (m.outDegreeOf(b1)==1 && Graphs.successorListOf(m, b1).contains(b2)) {
if (m.inDegreeOf(b2)==1 && Graphs.predecessorListOf(m, b2).contains(b1)) {
//there is exactly one edge between b1 and b2
for (Statement s : b2.getStatements()) {
b1.addStatement(s.deepCopy());
}
for (CfgBlock suc : Graphs.successorListOf(m, b2)) {
CfgEdge newEdge = new CfgEdge();
CfgEdge oldEdge = m.getEdge(b2, suc);
if (oldEdge.getLabel().isPresent()) {
newEdge.setLabel(oldEdge.getLabel().get().deepCopy());
}
m.addEdge(b1, suc, newEdge);
m.removeEdge(b2, suc);
}
return true;
}
}
return false;
}
}