Package org.renjin.compiler.ir.ssa

Source Code of org.renjin.compiler.ir.ssa.SsaTransformer

package org.renjin.compiler.ir.ssa;

import java.util.Map;
import java.util.Queue;
import java.util.Stack;

import org.renjin.compiler.cfg.BasicBlock;
import org.renjin.compiler.cfg.CfgPredicates;
import org.renjin.compiler.cfg.ControlFlowGraph;
import org.renjin.compiler.cfg.DominanceTree;
import org.renjin.compiler.ir.tac.expressions.Expression;
import org.renjin.compiler.ir.tac.expressions.Variable;
import org.renjin.compiler.ir.tac.statements.Assignment;
import org.renjin.compiler.ir.tac.statements.Statement;


import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
* Transforms three-address IR code into
* single static assignment form.
*
*/
public class SsaTransformer {

  private ControlFlowGraph cfg;
  private DominanceTree dtree;

  private Map<Variable, Integer> C = Maps.newHashMap();
  private Map<Variable, Stack<Integer>> S = Maps.newHashMap();


  public SsaTransformer(ControlFlowGraph cfg, DominanceTree dtree) {
    super();
    this.cfg = cfg;
    this.dtree = dtree;
  }
 
  public void transform() {
    insertPhiFunctions();
    renameVariables();
  }

  /**
   * Inserts PHI functions at the beginning of basic blocks.
   */
  private void insertPhiFunctions() {

    // See Figure 11
    // http://www.cs.utexas.edu/~pingali/CS380C/2010/papers/ssaCytron.pdf

    int iterCount = 0;

    Map<BasicBlock, Integer> hasAlready = Maps.newHashMap();
    Map<BasicBlock, Integer> work = Maps.newHashMap();

    for(BasicBlock X : cfg.getLiveBasicBlocks()) {
      hasAlready.put(X, 0);
      work.put(X, 0);
    }

    Queue<BasicBlock> W = Lists.newLinkedList();

    for(Variable V : cfg.variables()) {
      iterCount = iterCount + 1;

      for(BasicBlock X : Iterables.filter(cfg.getLiveBasicBlocks(), CfgPredicates.containsAssignmentTo(V))) {
        work.put(X, iterCount);
        W.add(X);
      }
      while(!W.isEmpty()) {
        BasicBlock X = W.poll();
        for(BasicBlock Y : dtree.getFrontier(X)) {
          if(X != cfg.getExit()) {
            if(hasAlready.get(Y) < iterCount) {
              Y.insertPhiFunction(V, cfg.getPredecessors(Y).size());
              // place (V <- phi(V,..., V)) at Y
              hasAlready.put(Y, iterCount);
              if(work.get(Y) < iterCount) {
                work.put(Y, iterCount);
                W.add(Y);
              }           
            }
          }
        }
      }
    }
  }

  private void renameVariables() {
    // Figure 12 in
    // http://www.cs.utexas.edu/~pingali/CS380C/2010/papers/ssaCytron.pdf

    for(Variable V : cfg.variables()) {

      // in a deviation from Cytron, et. al,
      // V_0 represents the uninitialized value
     
      C.put(V, 1);

      Stack<Integer> stack = new Stack<Integer>();
      stack.push(0);
      S.put(V, stack);
    }

    search(cfg.getEntry());
  }

  private void search(BasicBlock X) {
   
    for(Statement stmt : X.getStatements()) {
      Expression rhs = stmt.getRHS();
      if(!(rhs instanceof PhiFunction)) {
        for(Variable V : rhs.variables()) {
          int i = Top(V);
          rhs = rhs.replaceVariable(V, new SsaVariable(V, i));
        }
        stmt = X.replaceStatement(stmt, stmt.withRHS(rhs));
      }
     
      if(stmt instanceof Assignment) {
        Assignment assignment = (Assignment)stmt;
        if(assignment.getLHS() instanceof Variable) {
          Variable V = (Variable)assignment.getLHS();
          int i = C.get(V);
          X.replaceStatement(assignment, assignment.withLHS(new SsaVariable(V, i)));
          S.get(V).push(i);
          C.put(V, i + 1);
        }
      }
    }
   
    for(BasicBlock Y : cfg.getSuccessors(X)) {
      int j = whichPred(Y,X);
      for (Assignment A : Lists.newArrayList(Y.phiAssignments())) {
        PhiFunction rhs = (PhiFunction) A.getRHS();
        Variable V = rhs.getArgument(j);
        int i = Top(V);
        rhs = rhs.replaceVariable(j, i);
        Y.replaceStatement(A, new Assignment(A.getLHS(), rhs));
        // replace the j-th operand V in RHS(F) by V_i where i = Top(S(V))
      }
    }
    for(BasicBlock Y : dtree.getChildren(X)) {
      search(Y);
    }
    for(Assignment A : X.assignments()) {
      if(A.getLHS() instanceof SsaVariable) {
        SsaVariable lhs = (SsaVariable) A.getLHS();
        S.get(lhs.getInner()).pop();
      }
    }
  }

  private int Top(Variable V) {
    Stack<Integer> stack = S.get(V);
    if(stack.isEmpty()) {
      throw new IllegalStateException("Variable " + V + " has not been assigned to before its use");
    }
    return stack.peek();
  }

  /**
   * @return an integer telling which predecessor of Y in CFG is
   * X. The jth operand of a phi-function in Y corresponds to the
   * jth predecessor
   * of Y from the listing of the in edges of Y
   */
  private int whichPred(BasicBlock X, BasicBlock Y) {
    int j = 0;
    for(BasicBlock P : cfg.getPredecessors(X)) {
      if(P.equals(Y)) {
        return j;
      }
      j++;
    }
    throw new IllegalArgumentException("X is not a predecessor of Y");
  }
}
TOP

Related Classes of org.renjin.compiler.ir.ssa.SsaTransformer

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.