/* ---------------------------------------------------------------------
%   Copyright (C) 2007 Association for the COINS Compiler Infrastructure
%       (Read COPYING for detailed information.)
--------------------------------------------------------------------- */
/*
 * FindDEGen.java
 *
 * Created on March 13, 2003, 5:53 PM
 */
package coins.aflow;

import coins.aflow.util.FAList;          //##56
import coins.aflow.util.FAListIterator;  //##56
import coins.ir.hir.HIR;                 //##56
import coins.alias.RecordAlias;  //##53
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;


/**
 *
 * @author  hasegawa
 */
public class FindDEGen extends FindEGen {
    /** Creates a new instance of FindDEGen */
    public FindDEGen(FlowResults pResults) {
        super(pResults);
    }

//##56 BEGIN
/** addEGenExpId
 * EGen computation by using ExpId.
 * @param pEGenSet accumulated set of EGen ExpIds in the current BBlock.
 * @param pEKillSet accumulated set of EKill ExpIds in the current BBlock.
 * @param pSetRefRepr SetRefRepr of an expression.
 */
protected void addEGenExpId(Set pEGenSet,
  Set pEKillSet, SetRefRepr pSetRefRepr)
{
  Set lGenerated = (Set)fResults.get("UseFlowExpIdsForSetRefRepr",
    pSetRefRepr); // ExpIds generated by expression represented
  // by pSetRefRepr.
  HIR lHir = (HIR)pSetRefRepr.getIR(); //##57
  flow.dbg(5, "\n addEGenExpId", lHir.toStringShort() +
           " generates " + lGenerated); //##57
  flow.dbg(5, " kill", pEKillSet);
  //##57 lGenerated.removeAll(pEKillSet); // Remove killed subexpressions.
  pEGenSet.addAll(lGenerated); // Add subexpressions generated by this expression.
  pEKillSet.removeAll(lGenerated); // Remove the generated expression.
  Set lModSyms = new HashSet(); // Symbols modified by the statement
  // including the expression corresponding to pSetRefRepr
  // considering alias.
  lModSyms.addAll(pSetRefRepr.modSyms00());
  if (pSetRefRepr instanceof SetRefReprHirEImpl)
    lModSyms.addAll(((SetRefReprHirEImpl)pSetRefRepr).modSymsStmt());
  flow.dbg(6, "addEGen lModSyms", lModSyms);
  if (flow.fSubpFlow != null) {
    RecordAlias lRecordAlias = flow.fSubpFlow.getRecordAlias();
    if (lRecordAlias != null) {
      Set lModAlias = lRecordAlias.aliasSymGroup(lModSyms);
      lModSyms.addAll(lModAlias);
      flow.dbg(6, " modAlias ", lModSyms); // Symbols aliased with
      // the modified symbols.
    }
  }
  // Remove symbols that are computed using the operands whose value
  // is modified by the statement including this expression.
  for (Iterator lIt = pEGenSet.iterator(); lIt.hasNext(); ) {
    FlowExpId lFlowExpId = (FlowExpId)lIt.next();
    for (Iterator lOperandIt = lFlowExpId.getOperandSet0().iterator();
         lOperandIt.hasNext(); ) {
      if (lModSyms.contains(lOperandIt.next())) {
        lIt.remove(); // Remove the symbol whose operand is modified
        // by this statement considering alias.
        break;
      }
    }
  }
  // Add expressions killed by lModSyms to pEKillSet.
  FlowExpId lExpId;
  if (flow.fSubpFlow != null) { //##57
    FAList lFlowExpIdTable = flow.fSubpFlow.getFlowExpIdTable();
    for (Iterator lIterator2 = lFlowExpIdTable.iterator();
         lIterator2.hasNext(); ) {
      lExpId = (FlowExpId)lIterator2.next();
      if (lExpId != null) {
        for (Iterator lOperandIt = lExpId.getOperandSet0().iterator();
             lOperandIt.hasNext(); ) {
          if (lModSyms.contains(lOperandIt.next())) {
            pEKillSet.add(lExpId);
            flow.dbg(6, " add-to-EKill ", lExpId);
          }
        }
      }
    }
    flow.dbg(5, "\n  pEKillSet", pEKillSet);
    flow.dbg(6, " addEGen-result=", pEGenSet);
  } //##57
} // addEGenExpId

//##56 END

protected void addEGen(Set pEGenSet, SetRefRepr pSetRefRepr)
{
  Set s = (Set)(Set)fResults.get("UseFlowExpIdsForSetRefRepr",
    pSetRefRepr);
  flow.dbg(6, "\n addEGen", s);
  pEGenSet.addAll(s);

  //##53 Set lSyms = pSetRefRepr.modSyms00();
  //##53 BEGIN
  Set lModSyms = new HashSet();
  lModSyms.addAll(pSetRefRepr.modSyms00());
  if (pSetRefRepr instanceof SetRefReprHirEImpl)
    lModSyms.addAll(((SetRefReprHirEImpl)pSetRefRepr).modSymsStmt());
  flow.dbg(5, "addEGen lModSyms", lModSyms);
  if (flow.fSubpFlow != null) {
    RecordAlias lRecordAlias = flow.fSubpFlow.getRecordAlias();
    if (lRecordAlias != null) {
      Set lModAlias = lRecordAlias.aliasSymGroup(lModSyms);
      lModSyms.addAll(lModAlias);
      flow.dbg(6, " modAlias ", lModSyms);
    }
  }
  //##53 END
  for (Iterator lIt = pEGenSet.iterator(); lIt.hasNext(); ) {
    FlowExpId lFlowExpId = (FlowExpId)lIt.next();

    for (Iterator lOperandIt = lFlowExpId.getOperandSet0().iterator();
         lOperandIt.hasNext(); )
      if (lModSyms.contains(lOperandIt.next())) {
        lIt.remove();

        break;
      }
  }
  flow.dbg(6, " addEGen-result=", pEGenSet);
}

    protected void register(BBlock pBBlock, ExpVector pEGen) {
        flow.dbg(2, " setDEGen " + pBBlock, pEGen); //##56 not called ?
        pBBlock.setDEGen(pEGen);
    }

    public void find(SetRefRepr pSetRefRepr) {
        Set s = (Set) (Set) fResults.get("UseFlowExpIdsForSetRefRepr",
                pSetRefRepr);
        //		flow.dbg(5, "addEGen", s);
        //		pEGenSet.addAll((Set)fResults.get("UseFlowExpIdsForSetRefRepr", pSetRefRepr));
        //		pEGenSet.addAll(s);
        Set lSyms = pSetRefRepr.modSyms00();
        flow.dbg(5, "FindDEgen " + s + " modSyms00", lSyms);  //##53

        for (Iterator lIt = s.iterator(); lIt.hasNext();) {
            FlowExpId lFlowExpId = (FlowExpId) lIt.next();
            flow.dbg(5, " ", lFlowExpId);                     //##53

            for (Iterator lOperandIt = lFlowExpId.getOperandSet0().iterator();
                    lOperandIt.hasNext();)
                 if (lSyms.contains(lOperandIt.next())) {
                   lIt.remove();

                   break;
               }
        }
        flow.dbg(5, " FindDEGen-result", s);  //##53 not called ?

        fResults.put("DEGen", pSetRefRepr,
            ExpVectorImpl.forSet(s, pSetRefRepr.getBBlock().getSubpFlow()));
    }
}
