/*
 * 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 "compiler_internals.h"
#include "dataflow.h"

namespace art {

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

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

static BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb)
{
  BasicBlock* res = NeedsVisit(bb->fall_through);
  if (res == NULL) {
    res = NeedsVisit(bb->taken);
    if (res == NULL) {
      if (bb->successor_block_list.block_list_type != kNotUsed) {
        GrowableListIterator iterator;
        GrowableListIteratorInit(&bb->successor_block_list.blocks,
                                    &iterator);
        while (true) {
          SuccessorBlockInfo *sbi = reinterpret_cast<SuccessorBlockInfo*>
              (GrowableListIteratorNext(&iterator));
          if (sbi == NULL) break;
          res = NeedsVisit(sbi->block);
          if (res != NULL) break;
        }
      }
    }
  }
  return res;
}

static void MarkPreOrder(CompilationUnit* cu, BasicBlock* block)
{
  block->visited = true;
  /* Enqueue the pre_order block id */
  InsertGrowableList(cu, &cu->dfs_order, block->id);
}

static void RecordDFSOrders(CompilationUnit* cu, BasicBlock* block)
{
  std::vector<BasicBlock*> succ;
  MarkPreOrder(cu, block);
  succ.push_back(block);
  while (!succ.empty()) {
    BasicBlock* curr = succ.back();
    BasicBlock* next_successor = NextUnvisitedSuccessor(curr);
    if (next_successor != NULL) {
      MarkPreOrder(cu, next_successor);
      succ.push_back(next_successor);
      continue;
    }
    curr->dfs_id = cu->dfs_post_order.num_used;
    InsertGrowableList(cu, &cu->dfs_post_order, curr->id);
    succ.pop_back();
  }
}

#if defined(TEST_DFS)
/* Enter the node to the dfs_order list then visit its successors */
static void RecursiveRecordDFSOrders(CompilationUnit* cu, BasicBlock* block)
{

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

  // Can this block be reached only via previous block fallthrough?
  if ((block->block_type == kDalvikByteCode) &&
      (block->predecessors->num_used == 1)) {
    DCHECK_GE(cu->dfs_order.num_used, 1U);
    int prev_idx = cu->dfs_order.num_used - 1;
    int prev_id = cu->dfs_order.elem_list[prev_idx];
    BasicBlock* pred_bb = (BasicBlock*)block->predecessors->elem_list[0];
  }

  /* Enqueue the pre_order block id */
  InsertGrowableList(cu, &cu->dfs_order, block->id);

  if (block->fall_through) {
    RecursiveRecordDFSOrders(cu, block->fall_through);
  }
  if (block->taken) RecursiveRecordDFSOrders(cu, block->taken);
  if (block->successor_block_list.block_list_type != kNotUsed) {
    GrowableListIterator iterator;
    GrowableListIteratorInit(&block->successor_block_list.blocks,
                                &iterator);
    while (true) {
      SuccessorBlockInfo *successor_block_info =
          (SuccessorBlockInfo *) GrowableListIteratorNext(&iterator);
      if (successor_block_info == NULL) break;
      BasicBlock* succ_bb = successor_block_info->block;
      RecursiveRecordDFSOrders(cu, succ_bb);
    }
  }

  /* Record postorder in basic block and enqueue normal id in dfs_post_order */
  block->dfs_id = cu->dfs_post_order.num_used;
  InsertGrowableList(cu, &cu->dfs_post_order, block->id);
  return;
}
#endif

/* Sort the blocks by the Depth-First-Search */
static void ComputeDFSOrders(CompilationUnit* cu)
{
  /* Initialize or reset the DFS pre_order list */
  if (cu->dfs_order.elem_list == NULL) {
    CompilerInitGrowableList(cu, &cu->dfs_order, cu->num_blocks,
                        kListDfsOrder);
  } else {
    /* Just reset the used length on the counter */
    cu->dfs_order.num_used = 0;
  }

  /* Initialize or reset the DFS post_order list */
  if (cu->dfs_post_order.elem_list == NULL) {
    CompilerInitGrowableList(cu, &cu->dfs_post_order, cu->num_blocks,
                        kListDfsPostOrder);
  } else {
    /* Just reset the used length on the counter */
    cu->dfs_post_order.num_used = 0;
  }

#if defined(TEST_DFS)
  // Reset visited flags
  DataFlowAnalysisDispatcher(cu, ClearVisitedFlag,
                                kAllNodes, false /* is_iterative */);
  // Record pre and post order dfs
  RecursiveRecordDFSOrders(cu, cu->entry_block);
  // Copy the results for later comparison and reset the lists
  GrowableList recursive_dfs_order;
  GrowableList recursive_dfs_post_order;
  CompilerInitGrowableList(cu, &recursive_dfs_order, cu->dfs_order.num_used,
                      kListDfsOrder);
  for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
    InsertGrowableList(cu, &recursive_dfs_order,
                          cu->dfs_order.elem_list[i]);
  }
  cu->dfs_order.num_used = 0;
  CompilerInitGrowableList(cu, &recursive_dfs_post_order,
                      cu->dfs_post_order.num_used, kListDfsOrder);
  for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
    InsertGrowableList(cu, &recursive_dfs_post_order,
                          cu->dfs_post_order.elem_list[i]);
  }
  cu->dfs_post_order.num_used = 0;
#endif

  // Reset visited flags from all nodes
  DataFlowAnalysisDispatcher(cu, ClearVisitedFlag,
                                kAllNodes, false /* is_iterative */);
  // Record dfs orders
  RecordDFSOrders(cu, cu->entry_block);

#if defined(TEST_DFS)
  bool mismatch = false;
  mismatch |= (cu->dfs_order.num_used != recursive_dfs_order.num_used);
  for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
    mismatch |= (cu->dfs_order.elem_list[i] !=
                 recursive_dfs_order.elem_list[i]);
  }
  mismatch |= (cu->dfs_post_order.num_used != recursive_dfs_post_order.num_used);
  for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
    mismatch |= (cu->dfs_post_order.elem_list[i] !=
                 recursive_dfs_post_order.elem_list[i]);
  }
  if (mismatch) {
    LOG(INFO) << "Mismatch for "
              << PrettyMethod(cu->method_idx, *cu->dex_file);
    LOG(INFO) << "New dfs";
    for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
      LOG(INFO) << i << " - " << cu->dfs_order.elem_list[i];
    }
    LOG(INFO) << "Recursive dfs";
    for (unsigned int i = 0; i < recursive_dfs_order.num_used; i++) {
      LOG(INFO) << i << " - " << recursive_dfs_order.elem_list[i];
    }
    LOG(INFO) << "New post dfs";
    for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
      LOG(INFO) << i << " - " << cu->dfs_post_order.elem_list[i];
    }
    LOG(INFO) << "Recursive post dfs";
    for (unsigned int i = 0; i < recursive_dfs_post_order.num_used; i++) {
      LOG(INFO) << i << " - " << recursive_dfs_post_order.elem_list[i];
    }
  }
  CHECK_EQ(cu->dfs_order.num_used, recursive_dfs_order.num_used);
  for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
    CHECK_EQ(cu->dfs_order.elem_list[i], recursive_dfs_order.elem_list[i]);
  }
  CHECK_EQ(cu->dfs_post_order.num_used, recursive_dfs_post_order.num_used);
  for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
    CHECK_EQ(cu->dfs_post_order.elem_list[i],
             recursive_dfs_post_order.elem_list[i]);
  }
#endif

  cu->num_reachable_blocks = cu->dfs_order.num_used;
}

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

  ArenaBitVectorIterator iterator;

  BitVectorIteratorInit(bb->data_flow_info->def_v, &iterator);
  while (true) {
    int idx = BitVectorIteratorNext(&iterator);
    if (idx == -1) break;
    /* Block bb defines register idx */
    SetBit(cu, cu->def_block_matrix[idx], bb->id);
  }
  return true;
}

static void ComputeDefBlockMatrix(CompilationUnit* cu)
{
  int num_registers = cu->num_dalvik_registers;
  /* Allocate num_dalvik_registers bit vector pointers */
  cu->def_block_matrix = static_cast<ArenaBitVector**>
      (NewMem(cu, sizeof(ArenaBitVector *) * num_registers, true, kAllocDFInfo));
  int i;

  /* Initialize num_register vectors with num_blocks bits each */
  for (i = 0; i < num_registers; i++) {
    cu->def_block_matrix[i] = AllocBitVector(cu, cu->num_blocks,
                                                 false, kBitMapBMatrix);
  }
  DataFlowAnalysisDispatcher(cu, FindLocalLiveIn,
                                kAllNodes, false /* is_iterative */);
  DataFlowAnalysisDispatcher(cu, FillDefBlockMatrix,
                                kAllNodes, false /* is_iterative */);

  /*
   * Also set the incoming parameters as defs in the entry block.
   * Only need to handle the parameters for the outer method.
   */
  int num_regs = cu->num_dalvik_registers;
  int in_reg = num_regs - cu->num_ins;
  for (; in_reg < num_regs; in_reg++) {
    SetBit(cu, cu->def_block_matrix[in_reg], cu->entry_block->id);
  }
}

/* Compute the post-order traversal of the CFG */
static void ComputeDomPostOrderTraversal(CompilationUnit* cu, BasicBlock* bb)
{
  ArenaBitVectorIterator bv_iterator;
  BitVectorIteratorInit(bb->i_dominated, &bv_iterator);
  GrowableList* block_list = &cu->block_list;

  /* Iterate through the dominated blocks first */
  while (true) {
    //TUNING: hot call to BitVectorIteratorNext
    int bb_idx = BitVectorIteratorNext(&bv_iterator);
    if (bb_idx == -1) break;
    BasicBlock* dominated_bb =
        reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, bb_idx));
    ComputeDomPostOrderTraversal(cu, dominated_bb);
  }

  /* Enter the current block id */
  InsertGrowableList(cu, &cu->dom_post_order_traversal, bb->id);

  /* hacky loop detection */
  if (bb->taken && IsBitSet(bb->dominators, bb->taken->id)) {
    cu->has_loop = true;
  }
}

static void CheckForDominanceFrontier(CompilationUnit* cu, BasicBlock* dom_bb,
                                      const BasicBlock* succ_bb)
{
  /*
   * TODO - evaluate whether phi will ever need to be inserted into exit
   * blocks.
   */
  if (succ_bb->i_dom != dom_bb &&
    succ_bb->block_type == kDalvikByteCode &&
    succ_bb->hidden == false) {
    SetBit(cu, dom_bb->dom_frontier, succ_bb->id);
  }
}

/* Worker function to compute the dominance frontier */
static bool ComputeDominanceFrontier(CompilationUnit* cu, BasicBlock* bb)
{
  GrowableList* block_list = &cu->block_list;

  /* Calculate DF_local */
  if (bb->taken) {
    CheckForDominanceFrontier(cu, bb, bb->taken);
  }
  if (bb->fall_through) {
    CheckForDominanceFrontier(cu, bb, bb->fall_through);
  }
  if (bb->successor_block_list.block_list_type != kNotUsed) {
    GrowableListIterator iterator;
    GrowableListIteratorInit(&bb->successor_block_list.blocks,
                                  &iterator);
      while (true) {
        SuccessorBlockInfo *successor_block_info =
            reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
        if (successor_block_info == NULL) break;
        BasicBlock* succ_bb = successor_block_info->block;
        CheckForDominanceFrontier(cu, bb, succ_bb);
      }
  }

  /* Calculate DF_up */
  ArenaBitVectorIterator bv_iterator;
  BitVectorIteratorInit(bb->i_dominated, &bv_iterator);
  while (true) {
    //TUNING: hot call to BitVectorIteratorNext
    int dominated_idx = BitVectorIteratorNext(&bv_iterator);
    if (dominated_idx == -1) break;
    BasicBlock* dominated_bb =
        reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, dominated_idx));
    ArenaBitVectorIterator df_iterator;
    BitVectorIteratorInit(dominated_bb->dom_frontier, &df_iterator);
    while (true) {
      //TUNING: hot call to BitVectorIteratorNext
      int df_up_idx = BitVectorIteratorNext(&df_iterator);
      if (df_up_idx == -1) break;
      BasicBlock* df_up_block =
          reinterpret_cast<BasicBlock*>( GrowableListGetElement(block_list, df_up_idx));
      CheckForDominanceFrontier(cu, bb, df_up_block);
    }
  }

  return true;
}

/* Worker function for initializing domination-related data structures */
static bool InitializeDominationInfo(CompilationUnit* cu, BasicBlock* bb)
{
  int num_total_blocks = cu->block_list.num_used;

  if (bb->dominators == NULL ) {
    bb->dominators = AllocBitVector(cu, num_total_blocks,
                                       false /* expandable */,
                                       kBitMapDominators);
    bb->i_dominated = AllocBitVector(cu, num_total_blocks,
                                       false /* expandable */,
                                       kBitMapIDominated);
    bb->dom_frontier = AllocBitVector(cu, num_total_blocks,
                                        false /* expandable */,
                                        kBitMapDomFrontier);
  } else {
    ClearAllBits(bb->dominators);
    ClearAllBits(bb->i_dominated);
    ClearAllBits(bb->dom_frontier);
  }
  /* Set all bits in the dominator vector */
  SetInitialBits(bb->dominators, num_total_blocks);

  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 ComputeBlockDominiators.
 */
static bool SlowComputeBlockDominators(CompilationUnit* cu, BasicBlock* bb)
{
  GrowableList* block_list = &cu->block_list;
  int num_total_blocks = block_list->num_used;
  ArenaBitVector* temp_block_v = cu->temp_block_v;
  GrowableListIterator iter;

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

  SetInitialBits(temp_block_v, num_total_blocks);

  /* Iterate through the predecessors */
  GrowableListIteratorInit(bb->predecessors, &iter);
  while (true) {
    BasicBlock* pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
    if (!pred_bb) break;
    /* temp_block_v = temp_block_v ^ dominators */
    if (pred_bb->dominators != NULL) {
      IntersectBitVectors(temp_block_v, temp_block_v, pred_bb->dominators);
    }
  }
  SetBit(cu, temp_block_v, bb->id);
  if (CompareBitVectors(temp_block_v, bb->dominators)) {
    CopyBitVector(bb->dominators, temp_block_v);
    return true;
  }
  return false;
}

/*
 * Worker function to compute the idom.  This implementation is only
 * used when kDebugVerifyDataflow is active and should compute the
 * same i_dom as ComputeblockIDom.
 */
static bool SlowComputeBlockIDom(CompilationUnit* cu, BasicBlock* bb)
{
  GrowableList* block_list = &cu->block_list;
  ArenaBitVector* temp_block_v = cu->temp_block_v;
  ArenaBitVectorIterator bv_iterator;
  BasicBlock* i_dom;

  if (bb == cu->entry_block) return false;

  CopyBitVector(temp_block_v, bb->dominators);
  ClearBit(temp_block_v, bb->id);
  BitVectorIteratorInit(temp_block_v, &bv_iterator);

  /* Should not see any dead block */
  DCHECK_NE(CountSetBits(temp_block_v),  0);
  if (CountSetBits(temp_block_v) == 1) {
    i_dom = reinterpret_cast<BasicBlock*>
        (GrowableListGetElement(block_list, BitVectorIteratorNext(&bv_iterator)));
    bb->i_dom = i_dom;
  } else {
    int i_dom_idx = BitVectorIteratorNext(&bv_iterator);
    DCHECK_NE(i_dom_idx, -1);
    while (true) {
      int next_dom = BitVectorIteratorNext(&bv_iterator);
      if (next_dom == -1) break;
      BasicBlock* next_dom_bb =
          reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, next_dom));
      /* i_dom dominates next_dom - set new i_dom */
      if (IsBitSet(next_dom_bb->dominators, i_dom_idx)) {
          i_dom_idx = next_dom;
      }

    }
    i_dom = reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, i_dom_idx));
    /* Set the immediate dominator block for bb */
    bb->i_dom = i_dom;
  }
  /* Add bb to the i_dominated set of the immediate dominator block */
  SetBit(cu, i_dom->i_dominated, bb->id);
  return true;
}

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

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

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

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

  /* Find the first processed predecessor */
  while (true) {
    BasicBlock* pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
    CHECK(pred_bb != NULL);
    if (cu->i_dom_list[pred_bb->dfs_id] != NOTVISITED) {
      idom = pred_bb->dfs_id;
      break;
    }
  }

  /* Scan the rest of the predecessors */
  while (true) {
      BasicBlock* pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
      if (!pred_bb) break;
      if (cu->i_dom_list[pred_bb->dfs_id] == NOTVISITED) {
        continue;
      } else {
        idom = FindCommonParent(cu, pred_bb->dfs_id, idom);
      }
  }

  DCHECK_NE(idom, NOTVISITED);

  /* Did something change? */
  if (cu->i_dom_list[bb->dfs_id] != idom) {
    cu->i_dom_list[bb->dfs_id] = idom;
    return true;
  }
  return false;
}

/* Worker function to compute each block's domintors */
static bool ComputeBlockDominiators(CompilationUnit* cu, BasicBlock* bb)
{
  if (bb == cu->entry_block) {
    ClearAllBits(bb->dominators);
  } else {
    CopyBitVector(bb->dominators, bb->i_dom->dominators);
  }
  SetBit(cu, bb->dominators, bb->id);
  return false;
}

static bool SetDominators(CompilationUnit* cu, BasicBlock* bb)
{
  if (bb != cu->entry_block) {
    int idom_dfs_idx = cu->i_dom_list[bb->dfs_id];
    DCHECK_NE(idom_dfs_idx, NOTVISITED);
    int i_dom_idx = cu->dfs_post_order.elem_list[idom_dfs_idx];
    BasicBlock* i_dom =
        reinterpret_cast<BasicBlock*>(GrowableListGetElement(&cu->block_list, i_dom_idx));
    if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
      DCHECK_EQ(bb->i_dom->id, i_dom->id);
    }
    bb->i_dom = i_dom;
    /* Add bb to the i_dominated set of the immediate dominator block */
    SetBit(cu, i_dom->i_dominated, bb->id);
  }
  return false;
}

/* Compute dominators, immediate dominator, and dominance fronter */
static void ComputeDominators(CompilationUnit* cu)
{
  int num_reachable_blocks = cu->num_reachable_blocks;
  int num_total_blocks = cu->block_list.num_used;

  /* Initialize domination-related data structures */
  DataFlowAnalysisDispatcher(cu, InitializeDominationInfo,
                                kReachableNodes, false /* is_iterative */);

  /* Initalize & Clear i_dom_list */
  if (cu->i_dom_list == NULL) {
    cu->i_dom_list = static_cast<int*>(NewMem(cu, sizeof(int) * num_reachable_blocks,
                                               false, kAllocDFInfo));
  }
  for (int i = 0; i < num_reachable_blocks; i++) {
    cu->i_dom_list[i] = NOTVISITED;
  }

  /* For post-order, last block is entry block.  Set its i_dom to istelf */
  DCHECK_EQ(cu->entry_block->dfs_id, num_reachable_blocks-1);
  cu->i_dom_list[cu->entry_block->dfs_id] = cu->entry_block->dfs_id;

  /* Compute the immediate dominators */
  DataFlowAnalysisDispatcher(cu, ComputeblockIDom,
                                kReversePostOrderTraversal,
                                true /* is_iterative */);

  /* Set the dominator for the root node */
  ClearAllBits(cu->entry_block->dominators);
  SetBit(cu, cu->entry_block->dominators, cu->entry_block->id);

  if (cu->temp_block_v == NULL) {
    cu->temp_block_v = AllocBitVector(cu, num_total_blocks,
                                          false /* expandable */,
                                          kBitMapTmpBlockV);
  } else {
    ClearAllBits(cu->temp_block_v);
  }
  cu->entry_block->i_dom = NULL;

  /* For testing, compute sets using alternate mechanism */
  if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
    // Use alternate mechanism to compute dominators for comparison
    DataFlowAnalysisDispatcher(cu, SlowComputeBlockDominators,
                                  kPreOrderDFSTraversal,
                                  true /* is_iterative */);

   DataFlowAnalysisDispatcher(cu, SlowComputeBlockIDom,
                                 kReachableNodes,
                                 false /* is_iterative */);
  }

  DataFlowAnalysisDispatcher(cu, SetDominators,
                                kReachableNodes,
                                false /* is_iterative */);

  DataFlowAnalysisDispatcher(cu, ComputeBlockDominiators,
                                kReversePostOrderTraversal,
                                false /* is_iterative */);

  /*
   * Now go ahead and compute the post order traversal based on the
   * i_dominated sets.
   */
  if (cu->dom_post_order_traversal.elem_list == NULL) {
    CompilerInitGrowableList(cu, &cu->dom_post_order_traversal,
                        num_reachable_blocks, kListDomPostOrderTraversal);
  } else {
    cu->dom_post_order_traversal.num_used = 0;
  }

  ComputeDomPostOrderTraversal(cu, cu->entry_block);
  DCHECK_EQ(cu->dom_post_order_traversal.num_used, static_cast<unsigned>(cu->num_reachable_blocks));

  /* Now compute the dominance frontier for each block */
  DataFlowAnalysisDispatcher(cu, ComputeDominanceFrontier,
                                        kPostOrderDOMTraversal,
                                        false /* is_iterative */);
}

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

  unsigned int idx;
  for (idx = 0; idx < dest->storage_size; 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.
 */
static bool ComputeBlockLiveIns(CompilationUnit* cu, BasicBlock* bb)
{
  ArenaBitVector* temp_dalvik_register_v = cu->temp_dalvik_register_v;

  if (bb->data_flow_info == NULL) return false;
  CopyBitVector(temp_dalvik_register_v, bb->data_flow_info->live_in_v);
  if (bb->taken && bb->taken->data_flow_info)
    ComputeSuccLineIn(temp_dalvik_register_v, bb->taken->data_flow_info->live_in_v,
                      bb->data_flow_info->def_v);
  if (bb->fall_through && bb->fall_through->data_flow_info)
    ComputeSuccLineIn(temp_dalvik_register_v,
                      bb->fall_through->data_flow_info->live_in_v,
                      bb->data_flow_info->def_v);
  if (bb->successor_block_list.block_list_type != kNotUsed) {
    GrowableListIterator iterator;
    GrowableListIteratorInit(&bb->successor_block_list.blocks,
                                &iterator);
    while (true) {
      SuccessorBlockInfo *successor_block_info =
          reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
      if (successor_block_info == NULL) break;
      BasicBlock* succ_bb = successor_block_info->block;
      if (succ_bb->data_flow_info) {
        ComputeSuccLineIn(temp_dalvik_register_v,
                          succ_bb->data_flow_info->live_in_v,
                          bb->data_flow_info->def_v);
      }
    }
  }
  if (CompareBitVectors(temp_dalvik_register_v, bb->data_flow_info->live_in_v)) {
    CopyBitVector(bb->data_flow_info->live_in_v, temp_dalvik_register_v);
    return true;
  }
  return false;
}

/* Insert phi nodes to for each variable to the dominance frontiers */
static void InsertPhiNodes(CompilationUnit* cu)
{
  int dalvik_reg;
  const GrowableList* block_list = &cu->block_list;
  ArenaBitVector* phi_blocks =
      AllocBitVector(cu, cu->num_blocks, false, kBitMapPhi);
  ArenaBitVector* tmp_blocks =
      AllocBitVector(cu, cu->num_blocks, false, kBitMapTmpBlocks);
  ArenaBitVector* input_blocks =
      AllocBitVector(cu, cu->num_blocks, false, kBitMapInputBlocks);

  cu->temp_dalvik_register_v =
      AllocBitVector(cu, cu->num_dalvik_registers, false,
                        kBitMapRegisterV);

  DataFlowAnalysisDispatcher(cu, ComputeBlockLiveIns,
                                kPostOrderDFSTraversal, true /* is_iterative */);

  /* Iterate through each Dalvik register */
  for (dalvik_reg = cu->num_dalvik_registers - 1; dalvik_reg >= 0; dalvik_reg--) {
    bool change;
    ArenaBitVectorIterator iterator;

    CopyBitVector(input_blocks, cu->def_block_matrix[dalvik_reg]);
    ClearAllBits(phi_blocks);

    /* Calculate the phi blocks for each Dalvik register */
    do {
      change = false;
      ClearAllBits(tmp_blocks);
      BitVectorIteratorInit(input_blocks, &iterator);

      while (true) {
        int idx = BitVectorIteratorNext(&iterator);
        if (idx == -1) break;
          BasicBlock* def_bb =
              reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, idx));

          /* Merge the dominance frontier to tmp_blocks */
          //TUNING: hot call to UnifyBitVetors
          if (def_bb->dom_frontier != NULL) {
            UnifyBitVetors(tmp_blocks, tmp_blocks, def_bb->dom_frontier);
          }
        }
        if (CompareBitVectors(phi_blocks, tmp_blocks)) {
          change = true;
          CopyBitVector(phi_blocks, tmp_blocks);

          /*
           * Iterate through the original blocks plus the new ones in
           * the dominance frontier.
           */
          CopyBitVector(input_blocks, phi_blocks);
          UnifyBitVetors(input_blocks, input_blocks,
                             cu->def_block_matrix[dalvik_reg]);
      }
    } while (change);

    /*
     * Insert a phi node for dalvik_reg in the phi_blocks if the Dalvik
     * register is in the live-in set.
     */
    BitVectorIteratorInit(phi_blocks, &iterator);
    while (true) {
      int idx = BitVectorIteratorNext(&iterator);
      if (idx == -1) break;
      BasicBlock* phi_bb =
          reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, idx));
      /* Variable will be clobbered before being used - no need for phi */
      if (!IsBitSet(phi_bb->data_flow_info->live_in_v, dalvik_reg)) continue;
      MIR *phi = static_cast<MIR*>(NewMem(cu, sizeof(MIR), true, kAllocDFInfo));
      phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpPhi);
      phi->dalvikInsn.vA = dalvik_reg;
      phi->offset = phi_bb->start_offset;
      PrependMIR(phi_bb, phi);
    }
  }
}

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

  /* Phi nodes are at the beginning of each block */
  for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
    if (mir->dalvikInsn.opcode != static_cast<Instruction::Code>(kMirOpPhi))
      return true;
    int ssa_reg = mir->ssa_rep->defs[0];
    DCHECK_GE(ssa_reg, 0);   // Shouldn't see compiler temps here
    int v_reg = SRegToVReg(cu, ssa_reg);

    uses.clear();
    incoming_arc.clear();

    /* Iterate through the predecessors */
    GrowableListIteratorInit(bb->predecessors, &iter);
    while (true) {
      BasicBlock* pred_bb =
         reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
      if (!pred_bb) break;
      int ssa_reg = pred_bb->data_flow_info->vreg_to_ssa_map[v_reg];
      uses.push_back(ssa_reg);
      incoming_arc.push_back(pred_bb->id);
    }

    /* Count the number of SSA registers for a Dalvik register */
    int num_uses = uses.size();
    mir->ssa_rep->num_uses = num_uses;
    mir->ssa_rep->uses =
        static_cast<int*>(NewMem(cu, sizeof(int) * num_uses, false, kAllocDFInfo));
    mir->ssa_rep->fp_use =
        static_cast<bool*>(NewMem(cu, sizeof(bool) * num_uses, true, kAllocDFInfo));
    int* incoming =
        static_cast<int*>(NewMem(cu, sizeof(int) * num_uses, false, kAllocDFInfo));
    // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
    mir->dalvikInsn.vB = reinterpret_cast<uintptr_t>(incoming);

    /* Set the uses array for the phi node */
    int *use_ptr = mir->ssa_rep->uses;
    for (int i = 0; i < num_uses; i++) {
      *use_ptr++ = uses[i];
      *incoming++ = incoming_arc[i];
    }
  }

  return true;
}

static void DoDFSPreOrderSSARename(CompilationUnit* cu, BasicBlock* block)
{

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

  /* Process this block */
  DoSSAConversion(cu, block);
  int map_size = sizeof(int) * cu->num_dalvik_registers;

  /* Save SSA map snapshot */
  int* saved_ssa_map = static_cast<int*>(NewMem(cu, map_size, false, kAllocDalvikToSSAMap));
  memcpy(saved_ssa_map, cu->vreg_to_ssa_map, map_size);

  if (block->fall_through) {
    DoDFSPreOrderSSARename(cu, block->fall_through);
    /* Restore SSA map snapshot */
    memcpy(cu->vreg_to_ssa_map, saved_ssa_map, map_size);
  }
  if (block->taken) {
    DoDFSPreOrderSSARename(cu, block->taken);
    /* Restore SSA map snapshot */
    memcpy(cu->vreg_to_ssa_map, saved_ssa_map, map_size);
  }
  if (block->successor_block_list.block_list_type != kNotUsed) {
    GrowableListIterator iterator;
    GrowableListIteratorInit(&block->successor_block_list.blocks, &iterator);
    while (true) {
      SuccessorBlockInfo *successor_block_info =
          reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
      if (successor_block_info == NULL) break;
      BasicBlock* succ_bb = successor_block_info->block;
      DoDFSPreOrderSSARename(cu, succ_bb);
      /* Restore SSA map snapshot */
      memcpy(cu->vreg_to_ssa_map, saved_ssa_map, map_size);
    }
  }
  cu->vreg_to_ssa_map = saved_ssa_map;
  return;
}

/* Perform SSA transformation for the whole method */
void SSATransformation(CompilationUnit* cu)
{
  /* Compute the DFS order */
  ComputeDFSOrders(cu);

  if (!cu->disable_dataflow) {
    /* Compute the dominator info */
    ComputeDominators(cu);
  }

  /* Allocate data structures in preparation for SSA conversion */
  CompilerInitializeSSAConversion(cu);

  if (!cu->disable_dataflow) {
    /* Find out the "Dalvik reg def x block" relation */
    ComputeDefBlockMatrix(cu);

    /* Insert phi nodes to dominance frontiers for all variables */
    InsertPhiNodes(cu);
  }

  /* Rename register names by local defs and phi nodes */
  DataFlowAnalysisDispatcher(cu, ClearVisitedFlag,
                                kAllNodes, false /* is_iterative */);
  DoDFSPreOrderSSARename(cu, cu->entry_block);

  if (!cu->disable_dataflow) {
    /*
     * Shared temp bit vector used by each block to count the number of defs
     * from all the predecessor blocks.
     */
    cu->temp_ssa_register_v = AllocBitVector(cu, cu->num_ssa_regs,
         false, kBitMapTempSSARegisterV);

    cu->temp_ssa_block_id_v =
        static_cast<int*>(NewMem(cu, sizeof(int) * cu->num_ssa_regs, false, kAllocDFInfo));

    /* Insert phi-operands with latest SSA names from predecessor blocks */
    DataFlowAnalysisDispatcher(cu, InsertPhiNodeOperands,
                                  kReachableNodes, false /* is_iterative */);
  }
}

}  // namespace art
