graph.clearEdges();
// put def-use edges
for (Statement s : graph.getNodes()) {
final Map<Variable,Set<Assignment>> var_defs = rda.getFlowIn(s);
s.visitBy(new StatementVisitor() {
private void linkdefs(Statement use, Variable var) {
Set<Assignment> defs = var_defs.get(var);
if (defs != null)
for (Assignment def : defs)
graph.addEdge(def, use, new VariableFilter(var));
}
// statements that contain a definition but no uses - these always become entry nodes
public void visitConstStm(ConstStm s) {
graph.addEntry(s);
}
public void visitUnknownStm(UnknownStm s) {
graph.addEntry(s);
}
public void visitEmptyStm(EmptyStm s) {
graph.addEntry(s); // actually, no need to make this an entry since the value is empty anyway
}
// statements that contain some uses - make def-use edges
public void visitAnalyzeStm(AnalyzeStm s) {
linkdefs(s, s.getBase());
}
public void visitCheckStm(CheckStm s) {
if (s.getBase() != null)
linkdefs(s, s.getBase());
else
graph.addEntry(s);
}
public void visitPlugStm(PlugStm s) {
linkdefs(s, s.getBase());
if (s.getXMLSource() != null)
linkdefs(s, s.getXMLSource());
else
graph.addEntry(s);
}
public void visitInsertStm(InsertStm s) {
linkdefs(s, s.getBase());
if (s.getXMLSource() != null)
linkdefs(s, s.getXMLSource());
else
graph.addEntry(s);
}
public void visitGapifyStm(GapifyStm s) {
linkdefs(s, s.getBase());
}
public void visitValidateStm(ValidateStm s) {
if (s.getBase() != null)
linkdefs(s, s.getBase());
else
graph.addEntry(s);
}
public void visitVarStm(VarStm s) {
linkdefs(s, s.getSource());
}
public void visitGetStm(GetStm s) {
linkdefs(s, s.getBase());
}
public void visitConcatStm(ConcatStm s) {
linkdefs(s, s.getXMLSource());
}
public void visitCopyStm(CopyStm s) {
linkdefs(s, s.getBase());
if (s.getFirstChild() != null)
linkdefs(s, s.getFirstChild());
if (s.getFirstAttr() != null)
linkdefs(s, s.getFirstAttr());
if (s.getNextNode() != null)
linkdefs(s, s.getNextNode());
if (s.getFirstChild() == null && s.getFirstAttr() == null && s.getNextNode() == null)
graph.addEntry(s);
}
public void visitCastStm(CastStm s) {
linkdefs(s, s.getBase());
}
public void visitNodeStm(NodeStm s) {
if (s.getFirstChild() != null)
linkdefs(s, s.getFirstChild());
if (s.getFirstAttr() != null)
linkdefs(s, s.getFirstAttr());
if (s.getNextNode() != null)
linkdefs(s, s.getNextNode());
if (s.getFirstChild() == null && s.getFirstAttr() == null && s.getNextNode() == null)
graph.addEntry(s);
}
public void visitRemoveStm(RemoveStm s) {
linkdefs(s, s.getBase());
}
public void visitSetStm(SetStm s) {
linkdefs(s, s.getBase());
if (s.getXMLSource() != null)
linkdefs(s, s.getXMLSource());
else
graph.addEntry(s);
}
// statements that contain no definitions and no uses
public void visitNopStm(NopStm s) {
// do nothing
}
// not in this phase
public void visitArrayReadStm(ArrayReadStm s) {
}
public void visitArrayWriteStm(ArrayWriteStm s) {
}
public void visitCallStm(CallStm s) {
}
public void visitEscapeStm(EscapeStm s) {
}
public void visitArrayWriteStringStm(ArrayWriteStringStm s) {
}
});
}
// copy propagation
for (Statement s : new LinkedHashSet<Statement>(graph.getNodes())) {
if (s instanceof VarStm) {
VarStm vs = (VarStm)s;
if (graph.getInEdges(vs).size() == 1) {
Assignment pred = (Assignment)(graph.getInEdges(vs).iterator().next()).getFrom();
if (graph.getOutEdges(pred).size()==1) {
// variable assignment with unique predecessor node that has no other successors - bypass this assignment
pred.setDest(vs.getDest());
for (Edge<Statement,VariableFilter> e : graph.getOutEdges(vs))
graph.addEdge(pred, e.getTo(), e.getData()); // XXX: ok to lose some edge info?
graph.removeNode(vs);
}
} else if (graph.getOutEdges(vs).size() == 1) {
Statement succ = graph.getOutEdges(vs).iterator().next().getTo();
if (graph.getInEdges(succ).size()==1) { // TODO: copy propagation could be improved by not requiring "no other predecessors"
// variable assignment with unique successor node that has no other predecessors - bypass this assignment
final Variable vsrc = vs.getSource();
succ.visitBy(new StatementVisitor() {
public void visitAnalyzeStm(AnalyzeStm s) {
s.setBase(vsrc);
}