Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "compiler_internals.h"
     18 #include "dataflow_iterator-inl.h"
     19 #include "utils/scoped_arena_containers.h"
     20 
     21 #define NOTVISITED (-1)
     22 
     23 namespace art {
     24 
     25 void MIRGraph::ClearAllVisitedFlags() {
     26   AllNodesIterator iter(this);
     27   for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
     28     bb->visited = false;
     29   }
     30 }
     31 
     32 BasicBlock* MIRGraph::NeedsVisit(BasicBlock* bb) {
     33   if (bb != NULL) {
     34     if (bb->visited || bb->hidden) {
     35       bb = NULL;
     36     }
     37   }
     38   return bb;
     39 }
     40 
     41 BasicBlock* MIRGraph::NextUnvisitedSuccessor(BasicBlock* bb) {
     42   BasicBlock* res = NeedsVisit(GetBasicBlock(bb->fall_through));
     43   if (res == NULL) {
     44     res = NeedsVisit(GetBasicBlock(bb->taken));
     45     if (res == NULL) {
     46       if (bb->successor_block_list_type != kNotUsed) {
     47         GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks);
     48         while (true) {
     49           SuccessorBlockInfo *sbi = iterator.Next();
     50           if (sbi == NULL) {
     51             break;
     52           }
     53           res = NeedsVisit(GetBasicBlock(sbi->block));
     54           if (res != NULL) {
     55             break;
     56           }
     57         }
     58       }
     59     }
     60   }
     61   return res;
     62 }
     63 
     64 void MIRGraph::MarkPreOrder(BasicBlock* block) {
     65   block->visited = true;
     66   /* Enqueue the pre_order block id */
     67   if (block->id != NullBasicBlockId) {
     68     dfs_order_->Insert(block->id);
     69   }
     70 }
     71 
     72 void MIRGraph::RecordDFSOrders(BasicBlock* block) {
     73   DCHECK(temp_scoped_alloc_.get() != nullptr);
     74   ScopedArenaVector<BasicBlock*> succ(temp_scoped_alloc_->Adapter());
     75   MarkPreOrder(block);
     76   succ.push_back(block);
     77   while (!succ.empty()) {
     78     BasicBlock* curr = succ.back();
     79     BasicBlock* next_successor = NextUnvisitedSuccessor(curr);
     80     if (next_successor != NULL) {
     81       MarkPreOrder(next_successor);
     82       succ.push_back(next_successor);
     83       continue;
     84     }
     85     curr->dfs_id = dfs_post_order_->Size();
     86     if (curr->id != NullBasicBlockId) {
     87       dfs_post_order_->Insert(curr->id);
     88     }
     89     succ.pop_back();
     90   }
     91 }
     92 
     93 /* Sort the blocks by the Depth-First-Search */
     94 void MIRGraph::ComputeDFSOrders() {
     95   /* Initialize or reset the DFS pre_order list */
     96   if (dfs_order_ == NULL) {
     97     dfs_order_ = new (arena_) GrowableArray<BasicBlockId>(arena_, GetNumBlocks(),
     98                                                           kGrowableArrayDfsOrder);
     99   } else {
    100     /* Just reset the used length on the counter */
    101     dfs_order_->Reset();
    102   }
    103 
    104   /* Initialize or reset the DFS post_order list */
    105   if (dfs_post_order_ == NULL) {
    106     dfs_post_order_ = new (arena_) GrowableArray<BasicBlockId>(arena_, GetNumBlocks(),
    107                                                                kGrowableArrayDfsPostOrder);
    108   } else {
    109     /* Just reset the used length on the counter */
    110     dfs_post_order_->Reset();
    111   }
    112 
    113   // Reset visited flags from all nodes
    114   ClearAllVisitedFlags();
    115 
    116   // Record dfs orders
    117   RecordDFSOrders(GetEntryBlock());
    118 
    119   num_reachable_blocks_ = dfs_order_->Size();
    120 
    121   if (num_reachable_blocks_ != num_blocks_) {
    122     // Hide all unreachable blocks.
    123     AllNodesIterator iter(this);
    124     for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
    125       if (!bb->visited) {
    126         bb->Hide(cu_);
    127       }
    128     }
    129   }
    130 }
    131 
    132 /*
    133  * Mark block bit on the per-Dalvik register vector to denote that Dalvik
    134  * register idx is defined in BasicBlock bb.
    135  */
    136 bool MIRGraph::FillDefBlockMatrix(BasicBlock* bb) {
    137   if (bb->data_flow_info == NULL) {
    138     return false;
    139   }
    140 
    141   for (uint32_t idx : bb->data_flow_info->def_v->Indexes()) {
    142     /* Block bb defines register idx */
    143     def_block_matrix_[idx]->SetBit(bb->id);
    144   }
    145   return true;
    146 }
    147 
    148 void MIRGraph::ComputeDefBlockMatrix() {
    149   int num_registers = cu_->num_dalvik_registers;
    150   /* Allocate num_dalvik_registers bit vector pointers */
    151   def_block_matrix_ = static_cast<ArenaBitVector**>
    152       (arena_->Alloc(sizeof(ArenaBitVector *) * num_registers,
    153                      kArenaAllocDFInfo));
    154   int i;
    155 
    156   /* Initialize num_register vectors with num_blocks bits each */
    157   for (i = 0; i < num_registers; i++) {
    158     def_block_matrix_[i] =
    159         new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapBMatrix);
    160   }
    161   AllNodesIterator iter(this);
    162   for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
    163     FindLocalLiveIn(bb);
    164   }
    165   AllNodesIterator iter2(this);
    166   for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
    167     FillDefBlockMatrix(bb);
    168   }
    169 
    170   /*
    171    * Also set the incoming parameters as defs in the entry block.
    172    * Only need to handle the parameters for the outer method.
    173    */
    174   int num_regs = cu_->num_dalvik_registers;
    175   int in_reg = num_regs - cu_->num_ins;
    176   for (; in_reg < num_regs; in_reg++) {
    177     def_block_matrix_[in_reg]->SetBit(GetEntryBlock()->id);
    178   }
    179 }
    180 
    181 void MIRGraph::ComputeDomPostOrderTraversal(BasicBlock* bb) {
    182   if (dom_post_order_traversal_ == NULL || max_num_reachable_blocks_ < num_reachable_blocks_) {
    183     // First time or too small - create the array.
    184     dom_post_order_traversal_ =
    185         new (arena_) GrowableArray<BasicBlockId>(arena_, num_reachable_blocks_,
    186                                         kGrowableArrayDomPostOrderTraversal);
    187   } else {
    188     dom_post_order_traversal_->Reset();
    189   }
    190   ClearAllVisitedFlags();
    191   DCHECK(temp_scoped_alloc_.get() != nullptr);
    192   ScopedArenaVector<std::pair<BasicBlock*, ArenaBitVector::IndexIterator>> work_stack(
    193       temp_scoped_alloc_->Adapter());
    194   bb->visited = true;
    195   work_stack.push_back(std::make_pair(bb, bb->i_dominated->Indexes().begin()));
    196   while (!work_stack.empty()) {
    197     std::pair<BasicBlock*, ArenaBitVector::IndexIterator>* curr = &work_stack.back();
    198     BasicBlock* curr_bb = curr->first;
    199     ArenaBitVector::IndexIterator* curr_idom_iter = &curr->second;
    200     while (!curr_idom_iter->Done() && (NeedsVisit(GetBasicBlock(**curr_idom_iter)) == nullptr)) {
    201       ++*curr_idom_iter;
    202     }
    203     // NOTE: work_stack.push_back()/pop_back() invalidate curr and curr_idom_iter.
    204     if (!curr_idom_iter->Done()) {
    205       BasicBlock* new_bb = GetBasicBlock(**curr_idom_iter);
    206       ++*curr_idom_iter;
    207       new_bb->visited = true;
    208       work_stack.push_back(std::make_pair(new_bb, new_bb->i_dominated->Indexes().begin()));
    209     } else {
    210       // no successor/next
    211       if (curr_bb->id != NullBasicBlockId) {
    212         dom_post_order_traversal_->Insert(curr_bb->id);
    213       }
    214       work_stack.pop_back();
    215 
    216       /* hacky loop detection */
    217       if ((curr_bb->taken != NullBasicBlockId) && curr_bb->dominators->IsBitSet(curr_bb->taken)) {
    218         curr_bb->nesting_depth++;
    219         attributes_ |= METHOD_HAS_LOOP;
    220       }
    221     }
    222   }
    223 }
    224 
    225 void MIRGraph::CheckForDominanceFrontier(BasicBlock* dom_bb,
    226                                          const BasicBlock* succ_bb) {
    227   /*
    228    * TODO - evaluate whether phi will ever need to be inserted into exit
    229    * blocks.
    230    */
    231   if (succ_bb->i_dom != dom_bb->id &&
    232     succ_bb->block_type == kDalvikByteCode &&
    233     succ_bb->hidden == false) {
    234     dom_bb->dom_frontier->SetBit(succ_bb->id);
    235   }
    236 }
    237 
    238 /* Worker function to compute the dominance frontier */
    239 bool MIRGraph::ComputeDominanceFrontier(BasicBlock* bb) {
    240   /* Calculate DF_local */
    241   if (bb->taken != NullBasicBlockId) {
    242     CheckForDominanceFrontier(bb, GetBasicBlock(bb->taken));
    243   }
    244   if (bb->fall_through != NullBasicBlockId) {
    245     CheckForDominanceFrontier(bb, GetBasicBlock(bb->fall_through));
    246   }
    247   if (bb->successor_block_list_type != kNotUsed) {
    248     GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks);
    249       while (true) {
    250         SuccessorBlockInfo *successor_block_info = iterator.Next();
    251         if (successor_block_info == NULL) {
    252           break;
    253         }
    254         BasicBlock* succ_bb = GetBasicBlock(successor_block_info->block);
    255         CheckForDominanceFrontier(bb, succ_bb);
    256       }
    257   }
    258 
    259   /* Calculate DF_up */
    260   for (uint32_t dominated_idx : bb->i_dominated->Indexes()) {
    261     BasicBlock* dominated_bb = GetBasicBlock(dominated_idx);
    262     for (uint32_t df_up_block_idx : dominated_bb->dom_frontier->Indexes()) {
    263       BasicBlock* df_up_block = GetBasicBlock(df_up_block_idx);
    264       CheckForDominanceFrontier(bb, df_up_block);
    265     }
    266   }
    267 
    268   return true;
    269 }
    270 
    271 /* Worker function for initializing domination-related data structures */
    272 void MIRGraph::InitializeDominationInfo(BasicBlock* bb) {
    273   int num_total_blocks = GetBasicBlockListCount();
    274 
    275   if (bb->dominators == NULL) {
    276     bb->dominators = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    277                                                  false /* expandable */, kBitMapDominators);
    278     bb->i_dominated = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    279                                                   false /* expandable */, kBitMapIDominated);
    280     bb->dom_frontier = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    281                                                    false /* expandable */, kBitMapDomFrontier);
    282   } else {
    283     bb->dominators->ClearAllBits();
    284     bb->i_dominated->ClearAllBits();
    285     bb->dom_frontier->ClearAllBits();
    286   }
    287   /* Set all bits in the dominator vector */
    288   bb->dominators->SetInitialBits(num_total_blocks);
    289 
    290   return;
    291 }
    292 
    293 /*
    294  * Walk through the ordered i_dom list until we reach common parent.
    295  * Given the ordering of i_dom_list, this common parent represents the
    296  * last element of the intersection of block1 and block2 dominators.
    297   */
    298 int MIRGraph::FindCommonParent(int block1, int block2) {
    299   while (block1 != block2) {
    300     while (block1 < block2) {
    301       block1 = i_dom_list_[block1];
    302       DCHECK_NE(block1, NOTVISITED);
    303     }
    304     while (block2 < block1) {
    305       block2 = i_dom_list_[block2];
    306       DCHECK_NE(block2, NOTVISITED);
    307     }
    308   }
    309   return block1;
    310 }
    311 
    312 /* Worker function to compute each block's immediate dominator */
    313 bool MIRGraph::ComputeblockIDom(BasicBlock* bb) {
    314   /* Special-case entry block */
    315   if ((bb->id == NullBasicBlockId) || (bb == GetEntryBlock())) {
    316     return false;
    317   }
    318 
    319   /* Iterate through the predecessors */
    320   GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors);
    321 
    322   /* Find the first processed predecessor */
    323   int idom = -1;
    324   while (true) {
    325     BasicBlock* pred_bb = GetBasicBlock(iter.Next());
    326     CHECK(pred_bb != NULL);
    327     if (i_dom_list_[pred_bb->dfs_id] != NOTVISITED) {
    328       idom = pred_bb->dfs_id;
    329       break;
    330     }
    331   }
    332 
    333   /* Scan the rest of the predecessors */
    334   while (true) {
    335       BasicBlock* pred_bb = GetBasicBlock(iter.Next());
    336       if (!pred_bb) {
    337         break;
    338       }
    339       if (i_dom_list_[pred_bb->dfs_id] == NOTVISITED) {
    340         continue;
    341       } else {
    342         idom = FindCommonParent(pred_bb->dfs_id, idom);
    343       }
    344   }
    345 
    346   DCHECK_NE(idom, NOTVISITED);
    347 
    348   /* Did something change? */
    349   if (i_dom_list_[bb->dfs_id] != idom) {
    350     i_dom_list_[bb->dfs_id] = idom;
    351     return true;
    352   }
    353   return false;
    354 }
    355 
    356 /* Worker function to compute each block's domintors */
    357 bool MIRGraph::ComputeBlockDominators(BasicBlock* bb) {
    358   if (bb == GetEntryBlock()) {
    359     bb->dominators->ClearAllBits();
    360   } else {
    361     bb->dominators->Copy(GetBasicBlock(bb->i_dom)->dominators);
    362   }
    363   bb->dominators->SetBit(bb->id);
    364   return false;
    365 }
    366 
    367 bool MIRGraph::SetDominators(BasicBlock* bb) {
    368   if (bb != GetEntryBlock()) {
    369     int idom_dfs_idx = i_dom_list_[bb->dfs_id];
    370     DCHECK_NE(idom_dfs_idx, NOTVISITED);
    371     int i_dom_idx = dfs_post_order_->Get(idom_dfs_idx);
    372     BasicBlock* i_dom = GetBasicBlock(i_dom_idx);
    373     bb->i_dom = i_dom->id;
    374     /* Add bb to the i_dominated set of the immediate dominator block */
    375     i_dom->i_dominated->SetBit(bb->id);
    376   }
    377   return false;
    378 }
    379 
    380 /* Compute dominators, immediate dominator, and dominance fronter */
    381 void MIRGraph::ComputeDominators() {
    382   int num_reachable_blocks = num_reachable_blocks_;
    383 
    384   /* Initialize domination-related data structures */
    385   PreOrderDfsIterator iter(this);
    386   for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
    387     InitializeDominationInfo(bb);
    388   }
    389 
    390   /* Initialize & Clear i_dom_list */
    391   if (max_num_reachable_blocks_ < num_reachable_blocks_) {
    392     i_dom_list_ = static_cast<int*>(arena_->Alloc(sizeof(int) * num_reachable_blocks,
    393                                                   kArenaAllocDFInfo));
    394   }
    395   for (int i = 0; i < num_reachable_blocks; i++) {
    396     i_dom_list_[i] = NOTVISITED;
    397   }
    398 
    399   /* For post-order, last block is entry block.  Set its i_dom to istelf */
    400   DCHECK_EQ(GetEntryBlock()->dfs_id, num_reachable_blocks-1);
    401   i_dom_list_[GetEntryBlock()->dfs_id] = GetEntryBlock()->dfs_id;
    402 
    403   /* Compute the immediate dominators */
    404   RepeatingReversePostOrderDfsIterator iter2(this);
    405   bool change = false;
    406   for (BasicBlock* bb = iter2.Next(false); bb != NULL; bb = iter2.Next(change)) {
    407     change = ComputeblockIDom(bb);
    408   }
    409 
    410   /* Set the dominator for the root node */
    411   GetEntryBlock()->dominators->ClearAllBits();
    412   GetEntryBlock()->dominators->SetBit(GetEntryBlock()->id);
    413 
    414   GetEntryBlock()->i_dom = 0;
    415 
    416   PreOrderDfsIterator iter3(this);
    417   for (BasicBlock* bb = iter3.Next(); bb != NULL; bb = iter3.Next()) {
    418     SetDominators(bb);
    419   }
    420 
    421   ReversePostOrderDfsIterator iter4(this);
    422   for (BasicBlock* bb = iter4.Next(); bb != NULL; bb = iter4.Next()) {
    423     ComputeBlockDominators(bb);
    424   }
    425 
    426   // Compute the dominance frontier for each block.
    427   ComputeDomPostOrderTraversal(GetEntryBlock());
    428   PostOrderDOMIterator iter5(this);
    429   for (BasicBlock* bb = iter5.Next(); bb != NULL; bb = iter5.Next()) {
    430     ComputeDominanceFrontier(bb);
    431   }
    432 }
    433 
    434 /*
    435  * Perform dest U= src1 ^ ~src2
    436  * This is probably not general enough to be placed in BitVector.[ch].
    437  */
    438 void MIRGraph::ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src1,
    439                                  const ArenaBitVector* src2) {
    440   if (dest->GetStorageSize() != src1->GetStorageSize() ||
    441       dest->GetStorageSize() != src2->GetStorageSize() ||
    442       dest->IsExpandable() != src1->IsExpandable() ||
    443       dest->IsExpandable() != src2->IsExpandable()) {
    444     LOG(FATAL) << "Incompatible set properties";
    445   }
    446 
    447   unsigned int idx;
    448   for (idx = 0; idx < dest->GetStorageSize(); idx++) {
    449     dest->GetRawStorage()[idx] |= src1->GetRawStorageWord(idx) & ~(src2->GetRawStorageWord(idx));
    450   }
    451 }
    452 
    453 /*
    454  * Iterate through all successor blocks and propagate up the live-in sets.
    455  * The calculated result is used for phi-node pruning - where we only need to
    456  * insert a phi node if the variable is live-in to the block.
    457  */
    458 bool MIRGraph::ComputeBlockLiveIns(BasicBlock* bb) {
    459   DCHECK_EQ(temp_bit_vector_size_, cu_->num_dalvik_registers);
    460   ArenaBitVector* temp_dalvik_register_v = temp_bit_vector_;
    461 
    462   if (bb->data_flow_info == NULL) {
    463     return false;
    464   }
    465   temp_dalvik_register_v->Copy(bb->data_flow_info->live_in_v);
    466   BasicBlock* bb_taken = GetBasicBlock(bb->taken);
    467   BasicBlock* bb_fall_through = GetBasicBlock(bb->fall_through);
    468   if (bb_taken && bb_taken->data_flow_info)
    469     ComputeSuccLineIn(temp_dalvik_register_v, bb_taken->data_flow_info->live_in_v,
    470                       bb->data_flow_info->def_v);
    471   if (bb_fall_through && bb_fall_through->data_flow_info)
    472     ComputeSuccLineIn(temp_dalvik_register_v, bb_fall_through->data_flow_info->live_in_v,
    473                       bb->data_flow_info->def_v);
    474   if (bb->successor_block_list_type != kNotUsed) {
    475     GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_blocks);
    476     while (true) {
    477       SuccessorBlockInfo *successor_block_info = iterator.Next();
    478       if (successor_block_info == NULL) {
    479         break;
    480       }
    481       BasicBlock* succ_bb = GetBasicBlock(successor_block_info->block);
    482       if (succ_bb->data_flow_info) {
    483         ComputeSuccLineIn(temp_dalvik_register_v, succ_bb->data_flow_info->live_in_v,
    484                           bb->data_flow_info->def_v);
    485       }
    486     }
    487   }
    488   if (!temp_dalvik_register_v->Equal(bb->data_flow_info->live_in_v)) {
    489     bb->data_flow_info->live_in_v->Copy(temp_dalvik_register_v);
    490     return true;
    491   }
    492   return false;
    493 }
    494 
    495 /* Insert phi nodes to for each variable to the dominance frontiers */
    496 void MIRGraph::InsertPhiNodes() {
    497   int dalvik_reg;
    498   ArenaBitVector* phi_blocks = new (temp_scoped_alloc_.get()) ArenaBitVector(
    499       temp_scoped_alloc_.get(), GetNumBlocks(), false, kBitMapPhi);
    500   ArenaBitVector* input_blocks = new (temp_scoped_alloc_.get()) ArenaBitVector(
    501       temp_scoped_alloc_.get(), GetNumBlocks(), false, kBitMapInputBlocks);
    502 
    503   RepeatingPostOrderDfsIterator iter(this);
    504   bool change = false;
    505   for (BasicBlock* bb = iter.Next(false); bb != NULL; bb = iter.Next(change)) {
    506     change = ComputeBlockLiveIns(bb);
    507   }
    508 
    509   /* Iterate through each Dalvik register */
    510   for (dalvik_reg = cu_->num_dalvik_registers - 1; dalvik_reg >= 0; dalvik_reg--) {
    511     input_blocks->Copy(def_block_matrix_[dalvik_reg]);
    512     phi_blocks->ClearAllBits();
    513     do {
    514       // TUNING: When we repeat this, we could skip indexes from the previous pass.
    515       for (uint32_t idx : input_blocks->Indexes()) {
    516         BasicBlock* def_bb = GetBasicBlock(idx);
    517         if (def_bb->dom_frontier != nullptr) {
    518           phi_blocks->Union(def_bb->dom_frontier);
    519         }
    520       }
    521     } while (input_blocks->Union(phi_blocks));
    522 
    523     /*
    524      * Insert a phi node for dalvik_reg in the phi_blocks if the Dalvik
    525      * register is in the live-in set.
    526      */
    527     for (uint32_t idx : phi_blocks->Indexes()) {
    528       BasicBlock* phi_bb = GetBasicBlock(idx);
    529       /* Variable will be clobbered before being used - no need for phi */
    530       if (!phi_bb->data_flow_info->live_in_v->IsBitSet(dalvik_reg)) {
    531         continue;
    532       }
    533       MIR *phi = NewMIR();
    534       phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpPhi);
    535       phi->dalvikInsn.vA = dalvik_reg;
    536       phi->offset = phi_bb->start_offset;
    537       phi->m_unit_index = 0;  // Arbitrarily assign all Phi nodes to outermost method.
    538       phi_bb->PrependMIR(phi);
    539     }
    540   }
    541 }
    542 
    543 /*
    544  * Worker function to insert phi-operands with latest SSA names from
    545  * predecessor blocks
    546  */
    547 bool MIRGraph::InsertPhiNodeOperands(BasicBlock* bb) {
    548   /* Phi nodes are at the beginning of each block */
    549   for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
    550     if (mir->dalvikInsn.opcode != static_cast<Instruction::Code>(kMirOpPhi))
    551       return true;
    552     int ssa_reg = mir->ssa_rep->defs[0];
    553     DCHECK_GE(ssa_reg, 0);   // Shouldn't see compiler temps here
    554     int v_reg = SRegToVReg(ssa_reg);
    555 
    556     /* Iterate through the predecessors */
    557     GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors);
    558     size_t num_uses = bb->predecessors->Size();
    559     AllocateSSAUseData(mir, num_uses);
    560     int* uses = mir->ssa_rep->uses;
    561     BasicBlockId* incoming =
    562         static_cast<BasicBlockId*>(arena_->Alloc(sizeof(BasicBlockId) * num_uses,
    563                                                  kArenaAllocDFInfo));
    564     mir->meta.phi_incoming = incoming;
    565     int idx = 0;
    566     while (true) {
    567       BasicBlock* pred_bb = GetBasicBlock(iter.Next());
    568       if (!pred_bb) {
    569        break;
    570       }
    571       int ssa_reg = pred_bb->data_flow_info->vreg_to_ssa_map_exit[v_reg];
    572       uses[idx] = ssa_reg;
    573       incoming[idx] = pred_bb->id;
    574       idx++;
    575     }
    576   }
    577 
    578   return true;
    579 }
    580 
    581 void MIRGraph::DoDFSPreOrderSSARename(BasicBlock* block) {
    582   if (block->visited || block->hidden) {
    583     return;
    584   }
    585   block->visited = true;
    586 
    587   /* Process this block */
    588   DoSSAConversion(block);
    589   int map_size = sizeof(int) * cu_->num_dalvik_registers;
    590 
    591   /* Save SSA map snapshot */
    592   ScopedArenaAllocator allocator(&cu_->arena_stack);
    593   int* saved_ssa_map =
    594       static_cast<int*>(allocator.Alloc(map_size, kArenaAllocDalvikToSSAMap));
    595   memcpy(saved_ssa_map, vreg_to_ssa_map_, map_size);
    596 
    597   if (block->fall_through != NullBasicBlockId) {
    598     DoDFSPreOrderSSARename(GetBasicBlock(block->fall_through));
    599     /* Restore SSA map snapshot */
    600     memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size);
    601   }
    602   if (block->taken != NullBasicBlockId) {
    603     DoDFSPreOrderSSARename(GetBasicBlock(block->taken));
    604     /* Restore SSA map snapshot */
    605     memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size);
    606   }
    607   if (block->successor_block_list_type != kNotUsed) {
    608     GrowableArray<SuccessorBlockInfo*>::Iterator iterator(block->successor_blocks);
    609     while (true) {
    610       SuccessorBlockInfo *successor_block_info = iterator.Next();
    611       if (successor_block_info == NULL) {
    612         break;
    613       }
    614       BasicBlock* succ_bb = GetBasicBlock(successor_block_info->block);
    615       DoDFSPreOrderSSARename(succ_bb);
    616       /* Restore SSA map snapshot */
    617       memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size);
    618     }
    619   }
    620   return;
    621 }
    622 
    623 }  // namespace art
    624