/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Dalvik.h"
#include "Dataflow.h"

namespace art {

// Make sure iterative dfs recording matches old recursive version
//#define TEST_DFS

inline BasicBlock* needsVisit(BasicBlock* bb) {
  if (bb != NULL) {
    if (bb->visited || bb->hidden) {
      bb = NULL;
    }
  }
  return bb;
}

BasicBlock* nextUnvisitedSuccessor(BasicBlock* bb)
{
  BasicBlock* res = needsVisit(bb->fallThrough);
  if (res == NULL) {
    res = needsVisit(bb->taken);
    if (res == NULL) {
      if (bb->successorBlockList.blockListType != kNotUsed) {
        GrowableListIterator iterator;
        oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
                                    &iterator);
        while (true) {
          SuccessorBlockInfo *sbi = (SuccessorBlockInfo*)
              oatGrowableListIteratorNext(&iterator);
          if (sbi == NULL) break;
          res = needsVisit(sbi->block);
          if (res != NULL) break;
        }
      }
    }
  }
  return res;
}

void markPreOrder(CompilationUnit* cUnit, BasicBlock* block)
{
  block->visited = true;
  /* Enqueue the preOrder block id */
  oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
}

void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
{
  std::vector<BasicBlock*> succ;
  markPreOrder(cUnit, block);
  succ.push_back(block);
  while (!succ.empty()) {
    BasicBlock* curr = succ.back();
    BasicBlock* nextSuccessor = nextUnvisitedSuccessor(curr);
    if (nextSuccessor != NULL) {
      markPreOrder(cUnit, nextSuccessor);
      succ.push_back(nextSuccessor);
      continue;
    }
    curr->dfsId = cUnit->dfsPostOrder.numUsed;
    oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, curr->id);
    succ.pop_back();
  }
}

#if defined(TEST_DFS)
/* Enter the node to the dfsOrder list then visit its successors */
void recursiveRecordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
{

  if (block->visited || block->hidden) return;
  block->visited = true;

  // Can this block be reached only via previous block fallthrough?
  if ((block->blockType == kDalvikByteCode) &&
      (block->predecessors->numUsed == 1)) {
    DCHECK_GE(cUnit->dfsOrder.numUsed, 1U);
    int prevIdx = cUnit->dfsOrder.numUsed - 1;
    int prevId = cUnit->dfsOrder.elemList[prevIdx];
    BasicBlock* predBB = (BasicBlock*)block->predecessors->elemList[0];
  }

  /* Enqueue the preOrder block id */
  oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);

  if (block->fallThrough) {
    recursiveRecordDFSOrders(cUnit, block->fallThrough);
  }
  if (block->taken) recursiveRecordDFSOrders(cUnit, block->taken);
  if (block->successorBlockList.blockListType != kNotUsed) {
    GrowableListIterator iterator;
    oatGrowableListIteratorInit(&block->successorBlockList.blocks,
                                &iterator);
    while (true) {
      SuccessorBlockInfo *successorBlockInfo =
          (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
      if (successorBlockInfo == NULL) break;
      BasicBlock* succBB = successorBlockInfo->block;
      recursiveRecordDFSOrders(cUnit, succBB);
    }
  }

  /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
  block->dfsId = cUnit->dfsPostOrder.numUsed;
  oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
  return;
}
#endif

/* Sort the blocks by the Depth-First-Search */
void computeDFSOrders(CompilationUnit* cUnit)
{
  /* Initialize or reset the DFS preOrder list */
  if (cUnit->dfsOrder.elemList == NULL) {
    oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
                        kListDfsOrder);
  } else {
    /* Just reset the used length on the counter */
    cUnit->dfsOrder.numUsed = 0;
  }

  /* Initialize or reset the DFS postOrder list */
  if (cUnit->dfsPostOrder.elemList == NULL) {
    oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
                        kListDfsPostOrder);
  } else {
    /* Just reset the used length on the counter */
    cUnit->dfsPostOrder.numUsed = 0;
  }

#if defined(TEST_DFS)
  // Reset visited flags
  oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
                                kAllNodes, false /* isIterative */);
  // Record pre and post order dfs
  recursiveRecordDFSOrders(cUnit, cUnit->entryBlock);
  // Copy the results for later comparison and reset the lists
  GrowableList recursiveDfsOrder;
  GrowableList recursiveDfsPostOrder;
  oatInitGrowableList(cUnit, &recursiveDfsOrder, cUnit->dfsOrder.numUsed,
                      kListDfsOrder);
  for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
    oatInsertGrowableList(cUnit, &recursiveDfsOrder,
                          cUnit->dfsOrder.elemList[i]);
  }
  cUnit->dfsOrder.numUsed = 0;
  oatInitGrowableList(cUnit, &recursiveDfsPostOrder,
                      cUnit->dfsPostOrder.numUsed, kListDfsOrder);
  for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
    oatInsertGrowableList(cUnit, &recursiveDfsPostOrder,
                          cUnit->dfsPostOrder.elemList[i]);
  }
  cUnit->dfsPostOrder.numUsed = 0;
#endif

  // Reset visited flags from all nodes
  oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
                                kAllNodes, false /* isIterative */);
  // Record dfs orders
  recordDFSOrders(cUnit, cUnit->entryBlock);

#if defined(TEST_DFS)
  bool mismatch = false;
  mismatch |= (cUnit->dfsOrder.numUsed != recursiveDfsOrder.numUsed);
  for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
    mismatch |= (cUnit->dfsOrder.elemList[i] !=
                 recursiveDfsOrder.elemList[i]);
  }
  mismatch |= (cUnit->dfsPostOrder.numUsed != recursiveDfsPostOrder.numUsed);
  for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
    mismatch |= (cUnit->dfsPostOrder.elemList[i] !=
                 recursiveDfsPostOrder.elemList[i]);
  }
  if (mismatch) {
    LOG(INFO) << "Mismatch for "
              << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
    LOG(INFO) << "New dfs";
    for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
      LOG(INFO) << i << " - " << cUnit->dfsOrder.elemList[i];
    }
    LOG(INFO) << "Recursive dfs";
    for (unsigned int i = 0; i < recursiveDfsOrder.numUsed; i++) {
      LOG(INFO) << i << " - " << recursiveDfsOrder.elemList[i];
    }
    LOG(INFO) << "New post dfs";
    for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
      LOG(INFO) << i << " - " << cUnit->dfsPostOrder.elemList[i];
    }
    LOG(INFO) << "Recursive post dfs";
    for (unsigned int i = 0; i < recursiveDfsPostOrder.numUsed; i++) {
      LOG(INFO) << i << " - " << recursiveDfsPostOrder.elemList[i];
    }
  }
  CHECK_EQ(cUnit->dfsOrder.numUsed, recursiveDfsOrder.numUsed);
  for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
    CHECK_EQ(cUnit->dfsOrder.elemList[i], recursiveDfsOrder.elemList[i]);
  }
  CHECK_EQ(cUnit->dfsPostOrder.numUsed, recursiveDfsPostOrder.numUsed);
  for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
    CHECK_EQ(cUnit->dfsPostOrder.elemList[i],
             recursiveDfsPostOrder.elemList[i]);
  }
#endif

  cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
}

/*
 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
 * register idx is defined in BasicBlock bb.
 */
bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
{
  if (bb->dataFlowInfo == NULL) return false;

  ArenaBitVectorIterator iterator;

  oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
  while (true) {
    int idx = oatBitVectorIteratorNext(&iterator);
    if (idx == -1) break;
    /* Block bb defines register idx */
    oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
  }
  return true;
}

void computeDefBlockMatrix(CompilationUnit* cUnit)
{
  int numRegisters = cUnit->numDalvikRegisters;
  /* Allocate numDalvikRegisters bit vector pointers */
  cUnit->defBlockMatrix = (ArenaBitVector **)
      oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
             kAllocDFInfo);
  int i;

  /* Initialize numRegister vectors with numBlocks bits each */
  for (i = 0; i < numRegisters; i++) {
    cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
                                                 false, kBitMapBMatrix);
  }
  oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
                                kAllNodes, false /* isIterative */);
  oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
                                kAllNodes, false /* isIterative */);

  /*
   * Also set the incoming parameters as defs in the entry block.
   * Only need to handle the parameters for the outer method.
   */
  int numRegs = cUnit->numDalvikRegisters;
  int inReg = numRegs - cUnit->numIns;
  for (; inReg < numRegs; inReg++) {
    oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
  }
}

/* Compute the post-order traversal of the CFG */
void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
{
  ArenaBitVectorIterator bvIterator;
  oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
  GrowableList* blockList = &cUnit->blockList;

  /* Iterate through the dominated blocks first */
  while (true) {
    //TUNING: hot call to oatBitVectorIteratorNext
    int bbIdx = oatBitVectorIteratorNext(&bvIterator);
    if (bbIdx == -1) break;
    BasicBlock* dominatedBB =
        (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
    computeDomPostOrderTraversal(cUnit, dominatedBB);
  }

  /* Enter the current block id */
  oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);

  /* hacky loop detection */
  if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
    cUnit->hasLoop = true;
  }
}

void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
                             const BasicBlock* succBB)
{
  /*
   * TODO - evaluate whether phi will ever need to be inserted into exit
   * blocks.
   */
  if (succBB->iDom != domBB &&
    succBB->blockType == kDalvikByteCode &&
    succBB->hidden == false) {
    oatSetBit(cUnit, domBB->domFrontier, succBB->id);
  }
}

/* Worker function to compute the dominance frontier */
bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
{
  GrowableList* blockList = &cUnit->blockList;

  /* Calculate DF_local */
  if (bb->taken) {
    checkForDominanceFrontier(cUnit, bb, bb->taken);
  }
  if (bb->fallThrough) {
    checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
  }
  if (bb->successorBlockList.blockListType != kNotUsed) {
    GrowableListIterator iterator;
    oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
                                  &iterator);
      while (true) {
        SuccessorBlockInfo *successorBlockInfo =
            (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
        if (successorBlockInfo == NULL) break;
        BasicBlock* succBB = successorBlockInfo->block;
        checkForDominanceFrontier(cUnit, bb, succBB);
      }
  }

  /* Calculate DF_up */
  ArenaBitVectorIterator bvIterator;
  oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
  while (true) {
    //TUNING: hot call to oatBitVectorIteratorNext
    int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
    if (dominatedIdx == -1) break;
    BasicBlock* dominatedBB = (BasicBlock* )
        oatGrowableListGetElement(blockList, dominatedIdx);
    ArenaBitVectorIterator dfIterator;
    oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
    while (true) {
      //TUNING: hot call to oatBitVectorIteratorNext
      int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
      if (dfUpIdx == -1) break;
      BasicBlock* dfUpBlock = (BasicBlock* )
          oatGrowableListGetElement(blockList, dfUpIdx);
      checkForDominanceFrontier(cUnit, bb, dfUpBlock);
    }
  }

  return true;
}

/* Worker function for initializing domination-related data structures */
bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
{
  int numTotalBlocks = cUnit->blockList.numUsed;

  if (bb->dominators == NULL ) {
    bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
                                       false /* expandable */,
                                       kBitMapDominators);
    bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
                                       false /* expandable */,
                                       kBitMapIDominated);
    bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
                                        false /* expandable */,
                                        kBitMapDomFrontier);
  } else {
    oatClearAllBits(bb->dominators);
    oatClearAllBits(bb->iDominated);
    oatClearAllBits(bb->domFrontier);
  }
  /* Set all bits in the dominator vector */
  oatSetInitialBits(bb->dominators, numTotalBlocks);

  return true;
}

/*
 * Worker function to compute each block's dominators.  This implementation
 * is only used when kDebugVerifyDataflow is active and should compute
 * the same dominator sets as computeBlockDominators.
 */
bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
{
  GrowableList* blockList = &cUnit->blockList;
  int numTotalBlocks = blockList->numUsed;
  ArenaBitVector* tempBlockV = cUnit->tempBlockV;
  GrowableListIterator iter;

  /*
   * The dominator of the entry block has been preset to itself and we need
   * to skip the calculation here.
   */
  if (bb == cUnit->entryBlock) return false;

  oatSetInitialBits(tempBlockV, numTotalBlocks);

  /* Iterate through the predecessors */
  oatGrowableListIteratorInit(bb->predecessors, &iter);
  while (true) {
    BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
    if (!predBB) break;
    /* tempBlockV = tempBlockV ^ dominators */
    if (predBB->dominators != NULL) {
      oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
    }
  }
  oatSetBit(cUnit, tempBlockV, bb->id);
  if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
    oatCopyBitVector(bb->dominators, tempBlockV);
    return true;
  }
  return false;
}

/*
 * Worker function to compute the idom.  This implementation is only
 * used when kDebugVerifyDataflow is active and should compute the
 * same iDom as computeBlockIDom.
 */
bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
{
  GrowableList* blockList = &cUnit->blockList;
  ArenaBitVector* tempBlockV = cUnit->tempBlockV;
  ArenaBitVectorIterator bvIterator;
  BasicBlock* iDom;

  if (bb == cUnit->entryBlock) return false;

  oatCopyBitVector(tempBlockV, bb->dominators);
  oatClearBit(tempBlockV, bb->id);
  oatBitVectorIteratorInit(tempBlockV, &bvIterator);

  /* Should not see any dead block */
  DCHECK_NE(oatCountSetBits(tempBlockV),  0);
  if (oatCountSetBits(tempBlockV) == 1) {
    iDom = (BasicBlock* )
        oatGrowableListGetElement(blockList,
                                  oatBitVectorIteratorNext(&bvIterator));
    bb->iDom = iDom;
  } else {
    int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
    DCHECK_NE(iDomIdx, -1);
    while (true) {
      int nextDom = oatBitVectorIteratorNext(&bvIterator);
      if (nextDom == -1) break;
      BasicBlock* nextDomBB = (BasicBlock* )
          oatGrowableListGetElement(blockList, nextDom);
      /* iDom dominates nextDom - set new iDom */
      if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
          iDomIdx = nextDom;
      }

    }
    iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
    /* Set the immediate dominator block for bb */
    bb->iDom = iDom;
  }
  /* Add bb to the iDominated set of the immediate dominator block */
  oatSetBit(cUnit, iDom->iDominated, bb->id);
  return true;
}

/*
 * Walk through the ordered iDom list until we reach common parent.
 * Given the ordering of iDomList, this common parent represents the
 * last element of the intersection of block1 and block2 dominators.
  */
int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
{
  while (block1 != block2) {
    while (block1 < block2) {
      block1 = cUnit->iDomList[block1];
      DCHECK_NE(block1, NOTVISITED);
    }
    while (block2 < block1) {
      block2 = cUnit->iDomList[block2];
      DCHECK_NE(block2, NOTVISITED);
    }
  }
  return block1;
}

/* Worker function to compute each block's immediate dominator */
bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
{
  GrowableListIterator iter;
  int idom = -1;

  /* Special-case entry block */
  if (bb == cUnit->entryBlock) {
    return false;
  }

  /* Iterate through the predecessors */
  oatGrowableListIteratorInit(bb->predecessors, &iter);

  /* Find the first processed predecessor */
  while (true) {
    BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
    CHECK(predBB != NULL);
    if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
      idom = predBB->dfsId;
      break;
    }
  }

  /* Scan the rest of the predecessors */
  while (true) {
      BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
      if (!predBB) break;
      if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
        continue;
      } else {
        idom = findCommonParent(cUnit, predBB->dfsId, idom);
      }
  }

  DCHECK_NE(idom, NOTVISITED);

  /* Did something change? */
  if (cUnit->iDomList[bb->dfsId] != idom) {
    cUnit->iDomList[bb->dfsId] = idom;
    return true;
  }
  return false;
}

/* Worker function to compute each block's domintors */
bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
{
  if (bb == cUnit->entryBlock) {
    oatClearAllBits(bb->dominators);
  } else {
    oatCopyBitVector(bb->dominators, bb->iDom->dominators);
  }
  oatSetBit(cUnit, bb->dominators, bb->id);
  return false;
}

bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
{
  if (bb != cUnit->entryBlock) {
    int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
    DCHECK_NE(iDomDFSIdx, NOTVISITED);
    int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
    BasicBlock* iDom = (BasicBlock*)
          oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
    if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
      DCHECK_EQ(bb->iDom->id, iDom->id);
    }
    bb->iDom = iDom;
    /* Add bb to the iDominated set of the immediate dominator block */
    oatSetBit(cUnit, iDom->iDominated, bb->id);
  }
  return false;
}

/* Compute dominators, immediate dominator, and dominance fronter */
void computeDominators(CompilationUnit* cUnit)
{
  int numReachableBlocks = cUnit->numReachableBlocks;
  int numTotalBlocks = cUnit->blockList.numUsed;

  /* Initialize domination-related data structures */
  oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
                                kReachableNodes, false /* isIterative */);

  /* Initalize & Clear iDomList */
  if (cUnit->iDomList == NULL) {
    cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
                                   false, kAllocDFInfo);
  }
  for (int i = 0; i < numReachableBlocks; i++) {
    cUnit->iDomList[i] = NOTVISITED;
  }

  /* For post-order, last block is entry block.  Set its iDom to istelf */
  DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
  cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;

  /* Compute the immediate dominators */
  oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
                                kReversePostOrderTraversal,
                                true /* isIterative */);

  /* Set the dominator for the root node */
  oatClearAllBits(cUnit->entryBlock->dominators);
  oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);

  if (cUnit->tempBlockV == NULL) {
    cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
                                          false /* expandable */,
                                          kBitMapTmpBlockV);
  } else {
    oatClearAllBits(cUnit->tempBlockV);
  }
  cUnit->entryBlock->iDom = NULL;

  /* For testing, compute sets using alternate mechanism */
  if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
    // Use alternate mechanism to compute dominators for comparison
    oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
                                  kPreOrderDFSTraversal,
                                  true /* isIterative */);

   oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
                                 kReachableNodes,
                                 false /* isIterative */);
  }

  oatDataFlowAnalysisDispatcher(cUnit, setDominators,
                                kReachableNodes,
                                false /* isIterative */);

  oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
                                kReversePostOrderTraversal,
                                false /* isIterative */);

  /*
   * Now go ahead and compute the post order traversal based on the
   * iDominated sets.
   */
  if (cUnit->domPostOrderTraversal.elemList == NULL) {
    oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
                        numReachableBlocks, kListDomPostOrderTraversal);
  } else {
    cUnit->domPostOrderTraversal.numUsed = 0;
  }

  computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
  DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
         (unsigned) cUnit->numReachableBlocks);

  /* Now compute the dominance frontier for each block */
  oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
                                        kPostOrderDOMTraversal,
                                        false /* isIterative */);
}

/*
 * Perform dest U= src1 ^ ~src2
 * This is probably not general enough to be placed in BitVector.[ch].
 */
void computeSuccLiveIn(ArenaBitVector* dest,
                            const ArenaBitVector* src1,
                            const ArenaBitVector* src2)
{
  if (dest->storageSize != src1->storageSize ||
    dest->storageSize != src2->storageSize ||
    dest->expandable != src1->expandable ||
    dest->expandable != src2->expandable) {
    LOG(FATAL) << "Incompatible set properties";
  }

  unsigned int idx;
  for (idx = 0; idx < dest->storageSize; idx++) {
    dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
  }
}

/*
 * Iterate through all successor blocks and propagate up the live-in sets.
 * The calculated result is used for phi-node pruning - where we only need to
 * insert a phi node if the variable is live-in to the block.
 */
bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
{
  ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;

  if (bb->dataFlowInfo == NULL) return false;
  oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
  if (bb->taken && bb->taken->dataFlowInfo)
    computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
                      bb->dataFlowInfo->defV);
  if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
    computeSuccLiveIn(tempDalvikRegisterV,
                      bb->fallThrough->dataFlowInfo->liveInV,
                      bb->dataFlowInfo->defV);
  if (bb->successorBlockList.blockListType != kNotUsed) {
    GrowableListIterator iterator;
    oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
                                &iterator);
    while (true) {
      SuccessorBlockInfo *successorBlockInfo =
          (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
      if (successorBlockInfo == NULL) break;
      BasicBlock* succBB = successorBlockInfo->block;
      if (succBB->dataFlowInfo) {
        computeSuccLiveIn(tempDalvikRegisterV,
                          succBB->dataFlowInfo->liveInV,
                          bb->dataFlowInfo->defV);
      }
    }
  }
  if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
    oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
    return true;
  }
  return false;
}

/* Insert phi nodes to for each variable to the dominance frontiers */
void insertPhiNodes(CompilationUnit* cUnit)
{
  int dalvikReg;
  const GrowableList* blockList = &cUnit->blockList;
  ArenaBitVector* phiBlocks =
      oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
  ArenaBitVector* tmpBlocks =
      oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
  ArenaBitVector* inputBlocks =
      oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);

  cUnit->tempDalvikRegisterV =
      oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
                        kBitMapRegisterV);

  oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
                                kPostOrderDFSTraversal, true /* isIterative */);

  /* Iterate through each Dalvik register */
  for (dalvikReg = cUnit->numDalvikRegisters - 1; dalvikReg >= 0; dalvikReg--) {
    bool change;
    ArenaBitVectorIterator iterator;

    oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
    oatClearAllBits(phiBlocks);

    /* Calculate the phi blocks for each Dalvik register */
    do {
      change = false;
      oatClearAllBits(tmpBlocks);
      oatBitVectorIteratorInit(inputBlocks, &iterator);

      while (true) {
        int idx = oatBitVectorIteratorNext(&iterator);
        if (idx == -1) break;
          BasicBlock* defBB =
              (BasicBlock* ) oatGrowableListGetElement(blockList, idx);

          /* Merge the dominance frontier to tmpBlocks */
          //TUNING: hot call to oatUnifyBitVectors
          if (defBB->domFrontier != NULL) {
            oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
          }
        }
        if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
          change = true;
          oatCopyBitVector(phiBlocks, tmpBlocks);

          /*
           * Iterate through the original blocks plus the new ones in
           * the dominance frontier.
           */
          oatCopyBitVector(inputBlocks, phiBlocks);
          oatUnifyBitVectors(inputBlocks, inputBlocks,
                             cUnit->defBlockMatrix[dalvikReg]);
      }
    } while (change);

    /*
     * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
     * register is in the live-in set.
     */
    oatBitVectorIteratorInit(phiBlocks, &iterator);
    while (true) {
      int idx = oatBitVectorIteratorNext(&iterator);
      if (idx == -1) break;
      BasicBlock* phiBB =
          (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
      /* Variable will be clobbered before being used - no need for phi */
      if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
      MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
      phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
      phi->dalvikInsn.vA = dalvikReg;
      phi->offset = phiBB->startOffset;
      phi->meta.phiNext = cUnit->phiList;
      cUnit->phiList = phi;
      oatPrependMIR(phiBB, phi);
    }
  }
}

/*
 * Worker function to insert phi-operands with latest SSA names from
 * predecessor blocks
 */
bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
{
  GrowableListIterator iter;
  MIR *mir;
  std::vector<int> uses;
  std::vector<int> incomingArc;

  /* Phi nodes are at the beginning of each block */
  for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
    if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
      return true;
    int ssaReg = mir->ssaRep->defs[0];
    DCHECK_GE(ssaReg, 0);   // Shouldn't see compiler temps here
    int vReg = SRegToVReg(cUnit, ssaReg);

    uses.clear();
    incomingArc.clear();

    /* Iterate through the predecessors */
    oatGrowableListIteratorInit(bb->predecessors, &iter);
    while (true) {
      BasicBlock* predBB =
         (BasicBlock*)oatGrowableListIteratorNext(&iter);
      if (!predBB) break;
      int ssaReg = predBB->dataFlowInfo->vRegToSSAMap[vReg];
      uses.push_back(ssaReg);
      incomingArc.push_back(predBB->id);
    }

    /* Count the number of SSA registers for a Dalvik register */
    int numUses = uses.size();
    mir->ssaRep->numUses = numUses;
    mir->ssaRep->uses =
        (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
    mir->ssaRep->fpUse =
        (bool*) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
    int* incoming =
        (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
    // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
    mir->dalvikInsn.vB = (intptr_t) incoming;

    /* Set the uses array for the phi node */
    int *usePtr = mir->ssaRep->uses;
    for (int i = 0; i < numUses; i++) {
      *usePtr++ = uses[i];
      *incoming++ = incomingArc[i];
    }
  }

  return true;
}

void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
{

  if (block->visited || block->hidden) return;
  block->visited = true;

  /* Process this block */
  oatDoSSAConversion(cUnit, block);
  int mapSize = sizeof(int) * cUnit->numDalvikRegisters;

  /* Save SSA map snapshot */
  int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
                                  kAllocDalvikToSSAMap);
  memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);

  if (block->fallThrough) {
    doDFSPreOrderSSARename(cUnit, block->fallThrough);
    /* Restore SSA map snapshot */
    memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
  }
  if (block->taken) {
    doDFSPreOrderSSARename(cUnit, block->taken);
    /* Restore SSA map snapshot */
    memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
  }
  if (block->successorBlockList.blockListType != kNotUsed) {
    GrowableListIterator iterator;
    oatGrowableListIteratorInit(&block->successorBlockList.blocks,
                                &iterator);
    while (true) {
      SuccessorBlockInfo *successorBlockInfo =
          (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
      if (successorBlockInfo == NULL) break;
      BasicBlock* succBB = successorBlockInfo->block;
      doDFSPreOrderSSARename(cUnit, succBB);
      /* Restore SSA map snapshot */
      memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
    }
  }
  cUnit->vRegToSSAMap = savedSSAMap;
  return;
}

/* Perform SSA transformation for the whole method */
void oatMethodSSATransformation(CompilationUnit* cUnit)
{
  /* Compute the DFS order */
  computeDFSOrders(cUnit);

  if (!cUnit->disableDataflow) {
    /* Compute the dominator info */
    computeDominators(cUnit);
  }

  /* Allocate data structures in preparation for SSA conversion */
  oatInitializeSSAConversion(cUnit);

  if (!cUnit->disableDataflow) {
    /* Find out the "Dalvik reg def x block" relation */
    computeDefBlockMatrix(cUnit);

    /* Insert phi nodes to dominance frontiers for all variables */
    insertPhiNodes(cUnit);
  }

  /* Rename register names by local defs and phi nodes */
  oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
                                kAllNodes, false /* isIterative */);
  doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);

  if (!cUnit->disableDataflow) {
    /*
     * Shared temp bit vector used by each block to count the number of defs
     * from all the predecessor blocks.
     */
    cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
         false, kBitMapTempSSARegisterV);

    cUnit->tempSSABlockIdV =
        (int*)oatNew(cUnit, sizeof(int) * cUnit->numSSARegs, false,
                     kAllocDFInfo);

    /* Insert phi-operands with latest SSA names from predecessor blocks */
    oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
                                  kReachableNodes, false /* isIterative */);
  }
}

}  // namespace art
