Package dk.brics.xact.analysis.transformations

Source Code of dk.brics.xact.analysis.transformations.DefUseTransformer

package dk.brics.xact.analysis.transformations;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

import dk.brics.xact.analysis.Debug;
import dk.brics.xact.analysis.dataflow.DataflowAnalyzer;
import dk.brics.xact.analysis.flowgraph.Edge;
import dk.brics.xact.analysis.flowgraph.FlowGraph;
import dk.brics.xact.analysis.flowgraph.Statement;
import dk.brics.xact.analysis.flowgraph.Variable;
import dk.brics.xact.analysis.flowgraph.VariableFilter;
import dk.brics.xact.analysis.flowgraph.statements.AnalyzeStm;
import dk.brics.xact.analysis.flowgraph.statements.ArrayReadStm;
import dk.brics.xact.analysis.flowgraph.statements.ArrayWriteStm;
import dk.brics.xact.analysis.flowgraph.statements.ArrayWriteStringStm;
import dk.brics.xact.analysis.flowgraph.statements.Assignment;
import dk.brics.xact.analysis.flowgraph.statements.CallStm;
import dk.brics.xact.analysis.flowgraph.statements.CastStm;
import dk.brics.xact.analysis.flowgraph.statements.CheckStm;
import dk.brics.xact.analysis.flowgraph.statements.ConcatStm;
import dk.brics.xact.analysis.flowgraph.statements.ConstStm;
import dk.brics.xact.analysis.flowgraph.statements.CopyStm;
import dk.brics.xact.analysis.flowgraph.statements.EmptyStm;
import dk.brics.xact.analysis.flowgraph.statements.EscapeStm;
import dk.brics.xact.analysis.flowgraph.statements.GapifyStm;
import dk.brics.xact.analysis.flowgraph.statements.GetStm;
import dk.brics.xact.analysis.flowgraph.statements.InsertStm;
import dk.brics.xact.analysis.flowgraph.statements.NodeStm;
import dk.brics.xact.analysis.flowgraph.statements.NopStm;
import dk.brics.xact.analysis.flowgraph.statements.PlugStm;
import dk.brics.xact.analysis.flowgraph.statements.RemoveStm;
import dk.brics.xact.analysis.flowgraph.statements.SetStm;
import dk.brics.xact.analysis.flowgraph.statements.StatementVisitor;
import dk.brics.xact.analysis.flowgraph.statements.UnknownStm;
import dk.brics.xact.analysis.flowgraph.statements.ValidateStm;
import dk.brics.xact.analysis.flowgraph.statements.VarStm;
import dk.brics.xact.analysis.xmlgraph.XMLGraphChecker;

/**
* Reaching definitions analysis and copy propagation.
*/
public class DefUseTransformer {

  /**
   * Constructs a new <code>DefUseTransformer</code>.
   */
  public DefUseTransformer() {}

  /**
   * Transforms the given flow graph.
   */
  public void run(final FlowGraph graph) {
    // run reaching definitions analysis
    DataflowAnalyzer<Map<Variable,Set<Assignment>>> rda =
      new DataflowAnalyzer<Map<Variable,Set<Assignment>>>(graph, new ReachingDefinitionsAnalysis());
    Debug.println(2, true, "Performing reaching definitions analysis");
    rda.run();

    // remove nop nodes and all edges, find new entries
    Set<Statement> nodes = graph.getNodes();
    for (Statement s : new HashSet<Statement>(nodes))
      if (s instanceof NopStm) {
        /*// alternative to setting entries as below
        if (graph.getEntries().contains(s)) {
          for (Edge<Statement,VariableFilter> e : graph.getOutEdges(s))
            graph.addEntry(e.getTo());
        }
        for (Edge<Statement,VariableFilter> in : graph.getInEdges(s))
          for (Edge<Statement,VariableFilter> out : graph.getOutEdges(s))
            graph.addEdge(in.getFrom(), out.getTo(), out.getData());
         */
        graph.removeNode(s); // TODO: retain hotspots?
      }
    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);
              }

              public void visitGapifyStm(GapifyStm s) {
                s.setBase(vsrc);
              }

              public void visitGetStm(GetStm s) {
                s.setBase(vsrc);
              }

              public void visitRemoveStm(RemoveStm s) {
                s.setBase(vsrc);
              }

              public void visitValidateStm(ValidateStm s) {
                if (s.getBase() != null)
                  s.setBase(vsrc);
              }

              public void visitVarStm(VarStm s) {
                s.setSource(vsrc);
              }

              public void visitPlugStm(PlugStm s) {
                s.setBase(vsrc);
                if (s.getXMLSource() != null)
                  s.setXMLSource(vsrc);
              }

              public void visitCheckStm(CheckStm s) {
                if (s.getBase() != null)
                  s.setBase(vsrc);
              }

              public void visitSetStm(SetStm s) {
                s.setBase(vsrc);
                if (s.getXMLSource() != null)
                  s.setXMLSource(vsrc);
              }

              public void visitInsertStm(InsertStm s) {
                s.setBase(vsrc);
                if (s.getXMLSource() != null)
                  s.setXMLSource(vsrc);
              }

              public void visitConcatStm(ConcatStm s) {
                s.setXMLSource(vsrc);
              }

              public void visitCopyStm(CopyStm s) {
                s.setBase(vsrc);
                if (s.getFirstChild() != null)
                  s.setFirstChild(vsrc);
                if (s.getFirstAttr() != null)
                  s.setFirstAttr(vsrc);
                if (s.getNextNode() != null)
                  s.setNextNode(vsrc);
              }

              public void visitCastStm(CastStm s) {
                s.setBase(vsrc);
              }

              public void visitNodeStm(NodeStm s) {
                if (s.getFirstChild() != null)
                  s.setFirstChild(vsrc);
                if (s.getFirstAttr() != null)
                  s.setFirstAttr(vsrc);
                if (s.getNextNode() != null)
                  s.setNextNode(vsrc);
              }

              // unreachable cases (these nodes cannot be def-use graph successors)

              public void visitConstStm(ConstStm s) {}

              public void visitEmptyStm(EmptyStm s) {}

              public void visitNopStm(NopStm s) {}

              public void visitUnknownStm(UnknownStm s) {}

              // 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) {
              }
            });
            for (Edge<Statement,VariableFilter> e : graph.getInEdges(vs))
              graph.addEdge(e.getFrom(), succ, e.getData()); // XXX: ok to lose some edge info?
            graph.removeNode(vs);
          }
        }
      }
    }
   
    // find unreachable nodes
    Set<Statement> reachable = new HashSet<Statement>(graph.getEntries());
    LinkedList<Statement> queue = new LinkedList<Statement>(graph.getEntries());
    while (!queue.isEmpty()) {
      Statement stm = queue.removeFirst();
      for (Edge<Statement,VariableFilter> edge : graph.getOutEdges(stm)) {
        if (!reachable.contains(edge.getTo())) {
          reachable.add(edge.getTo());
          queue.add(edge.getTo());
        }
      }
    }
    // find used nodes
    Set<Statement> used = new HashSet<Statement>();
    queue.clear();
    for (Statement stm : graph.getNodes()) {
      if (XMLGraphChecker.isStatementChecked(stm)) {
        queue.add(stm);
        used.add(stm);
      }
    }
    while (!queue.isEmpty()) {
      Statement stm = queue.removeFirst();
      for (Edge<Statement,VariableFilter> edge : graph.getInEdges(stm)) {
        if (!used.contains(edge.getFrom())) {
          used.add(edge.getFrom());
          queue.add(edge.getFrom());
        }
      }
    }
    for (Statement stm : new ArrayList<Statement>(graph.getNodes())) {
      if (!reachable.contains(stm) || !used.contains(stm))
        graph.removeNode(stm);
    }
  }
}
TOP

Related Classes of dk.brics.xact.analysis.transformations.DefUseTransformer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.