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 
     20 #define NOTVISITED (-1)
     21 
     22 namespace art {
     23 
     24 void MIRGraph::ClearAllVisitedFlags() {
     25   AllNodesIterator iter(this, false /* not iterative */);
     26   for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
     27     bb->visited = false;
     28   }
     29 }
     30 
     31 BasicBlock* MIRGraph::NeedsVisit(BasicBlock* bb) {
     32   if (bb != NULL) {
     33     if (bb->visited || bb->hidden) {
     34       bb = NULL;
     35     }
     36   }
     37   return bb;
     38 }
     39 
     40 BasicBlock* MIRGraph::NextUnvisitedSuccessor(BasicBlock* bb) {
     41   BasicBlock* res = NeedsVisit(bb->fall_through);
     42   if (res == NULL) {
     43     res = NeedsVisit(bb->taken);
     44     if (res == NULL) {
     45       if (bb->successor_block_list.block_list_type != kNotUsed) {
     46         GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_block_list.blocks);
     47         while (true) {
     48           SuccessorBlockInfo *sbi = iterator.Next();
     49           if (sbi == NULL) {
     50             break;
     51           }
     52           res = NeedsVisit(sbi->block);
     53           if (res != NULL) {
     54             break;
     55           }
     56         }
     57       }
     58     }
     59   }
     60   return res;
     61 }
     62 
     63 void MIRGraph::MarkPreOrder(BasicBlock* block) {
     64   block->visited = true;
     65   /* Enqueue the pre_order block id */
     66   dfs_order_->Insert(block->id);
     67 }
     68 
     69 void MIRGraph::RecordDFSOrders(BasicBlock* block) {
     70   std::vector<BasicBlock*> succ;
     71   MarkPreOrder(block);
     72   succ.push_back(block);
     73   while (!succ.empty()) {
     74     BasicBlock* curr = succ.back();
     75     BasicBlock* next_successor = NextUnvisitedSuccessor(curr);
     76     if (next_successor != NULL) {
     77       MarkPreOrder(next_successor);
     78       succ.push_back(next_successor);
     79       continue;
     80     }
     81     curr->dfs_id = dfs_post_order_->Size();
     82     dfs_post_order_->Insert(curr->id);
     83     succ.pop_back();
     84   }
     85 }
     86 
     87 /* Sort the blocks by the Depth-First-Search */
     88 void MIRGraph::ComputeDFSOrders() {
     89   /* Initialize or reset the DFS pre_order list */
     90   if (dfs_order_ == NULL) {
     91     dfs_order_ = new (arena_) GrowableArray<int>(arena_, GetNumBlocks(), kGrowableArrayDfsOrder);
     92   } else {
     93     /* Just reset the used length on the counter */
     94     dfs_order_->Reset();
     95   }
     96 
     97   /* Initialize or reset the DFS post_order list */
     98   if (dfs_post_order_ == NULL) {
     99     dfs_post_order_ = new (arena_) GrowableArray<int>(arena_, GetNumBlocks(), kGrowableArrayDfsPostOrder);
    100   } else {
    101     /* Just reset the used length on the counter */
    102     dfs_post_order_->Reset();
    103   }
    104 
    105   // Reset visited flags from all nodes
    106   ClearAllVisitedFlags();
    107 
    108   // Record dfs orders
    109   RecordDFSOrders(GetEntryBlock());
    110 
    111   num_reachable_blocks_ = dfs_order_->Size();
    112 }
    113 
    114 /*
    115  * Mark block bit on the per-Dalvik register vector to denote that Dalvik
    116  * register idx is defined in BasicBlock bb.
    117  */
    118 bool MIRGraph::FillDefBlockMatrix(BasicBlock* bb) {
    119   if (bb->data_flow_info == NULL) {
    120     return false;
    121   }
    122 
    123   ArenaBitVector::Iterator iterator(bb->data_flow_info->def_v);
    124   while (true) {
    125     int idx = iterator.Next();
    126     if (idx == -1) {
    127       break;
    128     }
    129     /* Block bb defines register idx */
    130     def_block_matrix_[idx]->SetBit(bb->id);
    131   }
    132   return true;
    133 }
    134 
    135 void MIRGraph::ComputeDefBlockMatrix() {
    136   int num_registers = cu_->num_dalvik_registers;
    137   /* Allocate num_dalvik_registers bit vector pointers */
    138   def_block_matrix_ = static_cast<ArenaBitVector**>
    139       (arena_->Alloc(sizeof(ArenaBitVector *) * num_registers,
    140                      ArenaAllocator::kAllocDFInfo));
    141   int i;
    142 
    143   /* Initialize num_register vectors with num_blocks bits each */
    144   for (i = 0; i < num_registers; i++) {
    145     def_block_matrix_[i] =
    146         new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapBMatrix);
    147   }
    148   AllNodesIterator iter(this, false /* not iterative */);
    149   for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
    150     FindLocalLiveIn(bb);
    151   }
    152   AllNodesIterator iter2(this, false /* not iterative */);
    153   for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
    154     FillDefBlockMatrix(bb);
    155   }
    156 
    157   /*
    158    * Also set the incoming parameters as defs in the entry block.
    159    * Only need to handle the parameters for the outer method.
    160    */
    161   int num_regs = cu_->num_dalvik_registers;
    162   int in_reg = num_regs - cu_->num_ins;
    163   for (; in_reg < num_regs; in_reg++) {
    164     def_block_matrix_[in_reg]->SetBit(GetEntryBlock()->id);
    165   }
    166 }
    167 
    168 void MIRGraph::ComputeDomPostOrderTraversal(BasicBlock* bb) {
    169   if (dom_post_order_traversal_ == NULL) {
    170     // First time - create the array.
    171     dom_post_order_traversal_ =
    172         new (arena_) GrowableArray<int>(arena_, num_reachable_blocks_,
    173                                         kGrowableArrayDomPostOrderTraversal);
    174   } else {
    175     dom_post_order_traversal_->Reset();
    176   }
    177   ClearAllVisitedFlags();
    178   std::vector<std::pair<BasicBlock*, ArenaBitVector::Iterator*> > work_stack;
    179   bb->visited = true;
    180   work_stack.push_back(std::make_pair(bb, new (arena_) ArenaBitVector::Iterator(bb->i_dominated)));
    181   while (!work_stack.empty()) {
    182     std::pair<BasicBlock*, ArenaBitVector::Iterator*> curr = work_stack.back();
    183     BasicBlock* curr_bb = curr.first;
    184     ArenaBitVector::Iterator* curr_idom_iter = curr.second;
    185     int bb_idx = curr_idom_iter->Next();
    186     while ((bb_idx != -1) && (NeedsVisit(GetBasicBlock(bb_idx)) == NULL)) {
    187       bb_idx = curr_idom_iter->Next();
    188     }
    189     if (bb_idx != -1) {
    190       BasicBlock* new_bb = GetBasicBlock(bb_idx);
    191       new_bb->visited = true;
    192       work_stack.push_back(
    193           std::make_pair(new_bb, new (arena_) ArenaBitVector::Iterator(new_bb->i_dominated)));
    194     } else {
    195       // no successor/next
    196       dom_post_order_traversal_->Insert(curr_bb->id);
    197       work_stack.pop_back();
    198 
    199       /* hacky loop detection */
    200       if (curr_bb->taken && curr_bb->dominators->IsBitSet(curr_bb->taken->id)) {
    201         attributes_ |= METHOD_HAS_LOOP;
    202       }
    203     }
    204   }
    205 }
    206 
    207 void MIRGraph::CheckForDominanceFrontier(BasicBlock* dom_bb,
    208                                          const BasicBlock* succ_bb) {
    209   /*
    210    * TODO - evaluate whether phi will ever need to be inserted into exit
    211    * blocks.
    212    */
    213   if (succ_bb->i_dom != dom_bb &&
    214     succ_bb->block_type == kDalvikByteCode &&
    215     succ_bb->hidden == false) {
    216     dom_bb->dom_frontier->SetBit(succ_bb->id);
    217   }
    218 }
    219 
    220 /* Worker function to compute the dominance frontier */
    221 bool MIRGraph::ComputeDominanceFrontier(BasicBlock* bb) {
    222   /* Calculate DF_local */
    223   if (bb->taken) {
    224     CheckForDominanceFrontier(bb, bb->taken);
    225   }
    226   if (bb->fall_through) {
    227     CheckForDominanceFrontier(bb, bb->fall_through);
    228   }
    229   if (bb->successor_block_list.block_list_type != kNotUsed) {
    230     GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_block_list.blocks);
    231       while (true) {
    232         SuccessorBlockInfo *successor_block_info = iterator.Next();
    233         if (successor_block_info == NULL) {
    234           break;
    235         }
    236         BasicBlock* succ_bb = successor_block_info->block;
    237         CheckForDominanceFrontier(bb, succ_bb);
    238       }
    239   }
    240 
    241   /* Calculate DF_up */
    242   ArenaBitVector::Iterator bv_iterator(bb->i_dominated);
    243   while (true) {
    244     // TUNING: hot call to BitVectorIteratorNext
    245     int dominated_idx = bv_iterator.Next();
    246     if (dominated_idx == -1) {
    247       break;
    248     }
    249     BasicBlock* dominated_bb = GetBasicBlock(dominated_idx);
    250     ArenaBitVector::Iterator df_iterator(dominated_bb->dom_frontier);
    251     while (true) {
    252       // TUNING: hot call to BitVectorIteratorNext
    253       int df_up_idx = df_iterator.Next();
    254       if (df_up_idx == -1) {
    255         break;
    256       }
    257       BasicBlock* df_up_block = GetBasicBlock(df_up_idx);
    258       CheckForDominanceFrontier(bb, df_up_block);
    259     }
    260   }
    261 
    262   return true;
    263 }
    264 
    265 /* Worker function for initializing domination-related data structures */
    266 void MIRGraph::InitializeDominationInfo(BasicBlock* bb) {
    267   int num_total_blocks = GetBasicBlockListCount();
    268 
    269   if (bb->dominators == NULL) {
    270     bb->dominators = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    271                                                  false /* expandable */, kBitMapDominators);
    272     bb->i_dominated = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    273                                                   false /* expandable */, kBitMapIDominated);
    274     bb->dom_frontier = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    275                                                    false /* expandable */, kBitMapDomFrontier);
    276   } else {
    277     bb->dominators->ClearAllBits();
    278     bb->i_dominated->ClearAllBits();
    279     bb->dom_frontier->ClearAllBits();
    280   }
    281   /* Set all bits in the dominator vector */
    282   bb->dominators->SetInitialBits(num_total_blocks);
    283 
    284   return;
    285 }
    286 
    287 /*
    288  * Walk through the ordered i_dom list until we reach common parent.
    289  * Given the ordering of i_dom_list, this common parent represents the
    290  * last element of the intersection of block1 and block2 dominators.
    291   */
    292 int MIRGraph::FindCommonParent(int block1, int block2) {
    293   while (block1 != block2) {
    294     while (block1 < block2) {
    295       block1 = i_dom_list_[block1];
    296       DCHECK_NE(block1, NOTVISITED);
    297     }
    298     while (block2 < block1) {
    299       block2 = i_dom_list_[block2];
    300       DCHECK_NE(block2, NOTVISITED);
    301     }
    302   }
    303   return block1;
    304 }
    305 
    306 /* Worker function to compute each block's immediate dominator */
    307 bool MIRGraph::ComputeblockIDom(BasicBlock* bb) {
    308   /* Special-case entry block */
    309   if (bb == GetEntryBlock()) {
    310     return false;
    311   }
    312 
    313   /* Iterate through the predecessors */
    314   GrowableArray<BasicBlock*>::Iterator iter(bb->predecessors);
    315 
    316   /* Find the first processed predecessor */
    317   int idom = -1;
    318   while (true) {
    319     BasicBlock* pred_bb = iter.Next();
    320     CHECK(pred_bb != NULL);
    321     if (i_dom_list_[pred_bb->dfs_id] != NOTVISITED) {
    322       idom = pred_bb->dfs_id;
    323       break;
    324     }
    325   }
    326 
    327   /* Scan the rest of the predecessors */
    328   while (true) {
    329       BasicBlock* pred_bb = iter.Next();
    330       if (!pred_bb) {
    331         break;
    332       }
    333       if (i_dom_list_[pred_bb->dfs_id] == NOTVISITED) {
    334         continue;
    335       } else {
    336         idom = FindCommonParent(pred_bb->dfs_id, idom);
    337       }
    338   }
    339 
    340   DCHECK_NE(idom, NOTVISITED);
    341 
    342   /* Did something change? */
    343   if (i_dom_list_[bb->dfs_id] != idom) {
    344     i_dom_list_[bb->dfs_id] = idom;
    345     return true;
    346   }
    347   return false;
    348 }
    349 
    350 /* Worker function to compute each block's domintors */
    351 bool MIRGraph::ComputeBlockDominators(BasicBlock* bb) {
    352   if (bb == GetEntryBlock()) {
    353     bb->dominators->ClearAllBits();
    354   } else {
    355     bb->dominators->Copy(bb->i_dom->dominators);
    356   }
    357   bb->dominators->SetBit(bb->id);
    358   return false;
    359 }
    360 
    361 bool MIRGraph::SetDominators(BasicBlock* bb) {
    362   if (bb != GetEntryBlock()) {
    363     int idom_dfs_idx = i_dom_list_[bb->dfs_id];
    364     DCHECK_NE(idom_dfs_idx, NOTVISITED);
    365     int i_dom_idx = dfs_post_order_->Get(idom_dfs_idx);
    366     BasicBlock* i_dom = GetBasicBlock(i_dom_idx);
    367     bb->i_dom = i_dom;
    368     /* Add bb to the i_dominated set of the immediate dominator block */
    369     i_dom->i_dominated->SetBit(bb->id);
    370   }
    371   return false;
    372 }
    373 
    374 /* Compute dominators, immediate dominator, and dominance fronter */
    375 void MIRGraph::ComputeDominators() {
    376   int num_reachable_blocks = num_reachable_blocks_;
    377   int num_total_blocks = GetBasicBlockListCount();
    378 
    379   /* Initialize domination-related data structures */
    380   ReachableNodesIterator iter(this, false /* not iterative */);
    381   for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
    382     InitializeDominationInfo(bb);
    383   }
    384 
    385   /* Initalize & Clear i_dom_list */
    386   if (i_dom_list_ == NULL) {
    387     i_dom_list_ = static_cast<int*>(arena_->Alloc(sizeof(int) * num_reachable_blocks,
    388                                                   ArenaAllocator::kAllocDFInfo));
    389   }
    390   for (int i = 0; i < num_reachable_blocks; i++) {
    391     i_dom_list_[i] = NOTVISITED;
    392   }
    393 
    394   /* For post-order, last block is entry block.  Set its i_dom to istelf */
    395   DCHECK_EQ(GetEntryBlock()->dfs_id, num_reachable_blocks-1);
    396   i_dom_list_[GetEntryBlock()->dfs_id] = GetEntryBlock()->dfs_id;
    397 
    398   /* Compute the immediate dominators */
    399   ReversePostOrderDfsIterator iter2(this, true /* iterative */);
    400   bool change = false;
    401   for (BasicBlock* bb = iter2.Next(false); bb != NULL; bb = iter2.Next(change)) {
    402     change = ComputeblockIDom(bb);
    403   }
    404 
    405   /* Set the dominator for the root node */
    406   GetEntryBlock()->dominators->ClearAllBits();
    407   GetEntryBlock()->dominators->SetBit(GetEntryBlock()->id);
    408 
    409   if (temp_block_v_ == NULL) {
    410     temp_block_v_ = new (arena_) ArenaBitVector(arena_, num_total_blocks,
    411                                                 false /* expandable */, kBitMapTmpBlockV);
    412   } else {
    413     temp_block_v_->ClearAllBits();
    414   }
    415   GetEntryBlock()->i_dom = NULL;
    416 
    417   ReachableNodesIterator iter3(this, false /* not iterative */);
    418   for (BasicBlock* bb = iter3.Next(); bb != NULL; bb = iter3.Next()) {
    419     SetDominators(bb);
    420   }
    421 
    422   ReversePostOrderDfsIterator iter4(this, false /* not iterative */);
    423   for (BasicBlock* bb = iter4.Next(); bb != NULL; bb = iter4.Next()) {
    424     ComputeBlockDominators(bb);
    425   }
    426 
    427   // Compute the dominance frontier for each block.
    428   ComputeDomPostOrderTraversal(GetEntryBlock());
    429   PostOrderDOMIterator iter5(this, false /* not iterative */);
    430   for (BasicBlock* bb = iter5.Next(); bb != NULL; bb = iter5.Next()) {
    431     ComputeDominanceFrontier(bb);
    432   }
    433 }
    434 
    435 /*
    436  * Perform dest U= src1 ^ ~src2
    437  * This is probably not general enough to be placed in BitVector.[ch].
    438  */
    439 void MIRGraph::ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src1,
    440                                  const ArenaBitVector* src2) {
    441   if (dest->GetStorageSize() != src1->GetStorageSize() ||
    442       dest->GetStorageSize() != src2->GetStorageSize() ||
    443       dest->IsExpandable() != src1->IsExpandable() ||
    444       dest->IsExpandable() != src2->IsExpandable()) {
    445     LOG(FATAL) << "Incompatible set properties";
    446   }
    447 
    448   unsigned int idx;
    449   for (idx = 0; idx < dest->GetStorageSize(); idx++) {
    450     dest->GetRawStorage()[idx] |= src1->GetRawStorageWord(idx) & ~(src2->GetRawStorageWord(idx));
    451   }
    452 }
    453 
    454 /*
    455  * Iterate through all successor blocks and propagate up the live-in sets.
    456  * The calculated result is used for phi-node pruning - where we only need to
    457  * insert a phi node if the variable is live-in to the block.
    458  */
    459 bool MIRGraph::ComputeBlockLiveIns(BasicBlock* bb) {
    460   ArenaBitVector* temp_dalvik_register_v = temp_dalvik_register_v_;
    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   if (bb->taken && bb->taken->data_flow_info)
    467     ComputeSuccLineIn(temp_dalvik_register_v, bb->taken->data_flow_info->live_in_v,
    468                       bb->data_flow_info->def_v);
    469   if (bb->fall_through && bb->fall_through->data_flow_info)
    470     ComputeSuccLineIn(temp_dalvik_register_v, bb->fall_through->data_flow_info->live_in_v,
    471                       bb->data_flow_info->def_v);
    472   if (bb->successor_block_list.block_list_type != kNotUsed) {
    473     GrowableArray<SuccessorBlockInfo*>::Iterator iterator(bb->successor_block_list.blocks);
    474     while (true) {
    475       SuccessorBlockInfo *successor_block_info = iterator.Next();
    476       if (successor_block_info == NULL) {
    477         break;
    478       }
    479       BasicBlock* succ_bb = successor_block_info->block;
    480       if (succ_bb->data_flow_info) {
    481         ComputeSuccLineIn(temp_dalvik_register_v, succ_bb->data_flow_info->live_in_v,
    482                           bb->data_flow_info->def_v);
    483       }
    484     }
    485   }
    486   if (!temp_dalvik_register_v->Equal(bb->data_flow_info->live_in_v)) {
    487     bb->data_flow_info->live_in_v->Copy(temp_dalvik_register_v);
    488     return true;
    489   }
    490   return false;
    491 }
    492 
    493 /* Insert phi nodes to for each variable to the dominance frontiers */
    494 void MIRGraph::InsertPhiNodes() {
    495   int dalvik_reg;
    496   ArenaBitVector* phi_blocks =
    497       new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapPhi);
    498   ArenaBitVector* tmp_blocks =
    499       new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapTmpBlocks);
    500   ArenaBitVector* input_blocks =
    501       new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapInputBlocks);
    502 
    503   temp_dalvik_register_v_ =
    504       new (arena_) ArenaBitVector(arena_, cu_->num_dalvik_registers, false, kBitMapRegisterV);
    505 
    506   PostOrderDfsIterator iter(this, true /* iterative */);
    507   bool change = false;
    508   for (BasicBlock* bb = iter.Next(false); bb != NULL; bb = iter.Next(change)) {
    509     change = ComputeBlockLiveIns(bb);
    510   }
    511 
    512   /* Iterate through each Dalvik register */
    513   for (dalvik_reg = cu_->num_dalvik_registers - 1; dalvik_reg >= 0; dalvik_reg--) {
    514     bool change;
    515 
    516     input_blocks->Copy(def_block_matrix_[dalvik_reg]);
    517     phi_blocks->ClearAllBits();
    518 
    519     /* Calculate the phi blocks for each Dalvik register */
    520     do {
    521       change = false;
    522       tmp_blocks->ClearAllBits();
    523       ArenaBitVector::Iterator iterator(input_blocks);
    524 
    525       while (true) {
    526         int idx = iterator.Next();
    527         if (idx == -1) {
    528           break;
    529         }
    530         BasicBlock* def_bb = GetBasicBlock(idx);
    531 
    532         /* Merge the dominance frontier to tmp_blocks */
    533         // TUNING: hot call to Union().
    534         if (def_bb->dom_frontier != NULL) {
    535           tmp_blocks->Union(def_bb->dom_frontier);
    536         }
    537       }
    538       if (!phi_blocks->Equal(tmp_blocks)) {
    539         change = true;
    540         phi_blocks->Copy(tmp_blocks);
    541 
    542         /*
    543          * Iterate through the original blocks plus the new ones in
    544          * the dominance frontier.
    545          */
    546         input_blocks->Copy(phi_blocks);
    547         input_blocks->Union(def_block_matrix_[dalvik_reg]);
    548       }
    549     } while (change);
    550 
    551     /*
    552      * Insert a phi node for dalvik_reg in the phi_blocks if the Dalvik
    553      * register is in the live-in set.
    554      */
    555     ArenaBitVector::Iterator iterator(phi_blocks);
    556     while (true) {
    557       int idx = iterator.Next();
    558       if (idx == -1) {
    559         break;
    560       }
    561       BasicBlock* phi_bb = GetBasicBlock(idx);
    562       /* Variable will be clobbered before being used - no need for phi */
    563       if (!phi_bb->data_flow_info->live_in_v->IsBitSet(dalvik_reg)) {
    564         continue;
    565       }
    566       MIR *phi =
    567           static_cast<MIR*>(arena_->Alloc(sizeof(MIR), ArenaAllocator::kAllocDFInfo));
    568       phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpPhi);
    569       phi->dalvikInsn.vA = dalvik_reg;
    570       phi->offset = phi_bb->start_offset;
    571       phi->m_unit_index = 0;  // Arbitrarily assign all Phi nodes to outermost method.
    572       PrependMIR(phi_bb, phi);
    573     }
    574   }
    575 }
    576 
    577 /*
    578  * Worker function to insert phi-operands with latest SSA names from
    579  * predecessor blocks
    580  */
    581 bool MIRGraph::InsertPhiNodeOperands(BasicBlock* bb) {
    582   MIR *mir;
    583   std::vector<int> uses;
    584   std::vector<int> incoming_arc;
    585 
    586   /* Phi nodes are at the beginning of each block */
    587   for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
    588     if (mir->dalvikInsn.opcode != static_cast<Instruction::Code>(kMirOpPhi))
    589       return true;
    590     int ssa_reg = mir->ssa_rep->defs[0];
    591     DCHECK_GE(ssa_reg, 0);   // Shouldn't see compiler temps here
    592     int v_reg = SRegToVReg(ssa_reg);
    593 
    594     uses.clear();
    595     incoming_arc.clear();
    596 
    597     /* Iterate through the predecessors */
    598     GrowableArray<BasicBlock*>::Iterator iter(bb->predecessors);
    599     while (true) {
    600       BasicBlock* pred_bb = iter.Next();
    601       if (!pred_bb) {
    602         break;
    603       }
    604       int ssa_reg = pred_bb->data_flow_info->vreg_to_ssa_map[v_reg];
    605       uses.push_back(ssa_reg);
    606       incoming_arc.push_back(pred_bb->id);
    607     }
    608 
    609     /* Count the number of SSA registers for a Dalvik register */
    610     int num_uses = uses.size();
    611     mir->ssa_rep->num_uses = num_uses;
    612     mir->ssa_rep->uses =
    613         static_cast<int*>(arena_->Alloc(sizeof(int) * num_uses, ArenaAllocator::kAllocDFInfo));
    614     mir->ssa_rep->fp_use =
    615         static_cast<bool*>(arena_->Alloc(sizeof(bool) * num_uses, ArenaAllocator::kAllocDFInfo));
    616     int* incoming =
    617         static_cast<int*>(arena_->Alloc(sizeof(int) * num_uses, ArenaAllocator::kAllocDFInfo));
    618     // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
    619     mir->dalvikInsn.vB = reinterpret_cast<uintptr_t>(incoming);
    620 
    621     /* Set the uses array for the phi node */
    622     int *use_ptr = mir->ssa_rep->uses;
    623     for (int i = 0; i < num_uses; i++) {
    624       *use_ptr++ = uses[i];
    625       *incoming++ = incoming_arc[i];
    626     }
    627   }
    628 
    629   return true;
    630 }
    631 
    632 void MIRGraph::DoDFSPreOrderSSARename(BasicBlock* block) {
    633   if (block->visited || block->hidden) {
    634     return;
    635   }
    636   block->visited = true;
    637 
    638   /* Process this block */
    639   DoSSAConversion(block);
    640   int map_size = sizeof(int) * cu_->num_dalvik_registers;
    641 
    642   /* Save SSA map snapshot */
    643   int* saved_ssa_map =
    644       static_cast<int*>(arena_->Alloc(map_size, ArenaAllocator::kAllocDalvikToSSAMap));
    645   memcpy(saved_ssa_map, vreg_to_ssa_map_, map_size);
    646 
    647   if (block->fall_through) {
    648     DoDFSPreOrderSSARename(block->fall_through);
    649     /* Restore SSA map snapshot */
    650     memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size);
    651   }
    652   if (block->taken) {
    653     DoDFSPreOrderSSARename(block->taken);
    654     /* Restore SSA map snapshot */
    655     memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size);
    656   }
    657   if (block->successor_block_list.block_list_type != kNotUsed) {
    658     GrowableArray<SuccessorBlockInfo*>::Iterator iterator(block->successor_block_list.blocks);
    659     while (true) {
    660       SuccessorBlockInfo *successor_block_info = iterator.Next();
    661       if (successor_block_info == NULL) {
    662         break;
    663       }
    664       BasicBlock* succ_bb = successor_block_info->block;
    665       DoDFSPreOrderSSARename(succ_bb);
    666       /* Restore SSA map snapshot */
    667       memcpy(vreg_to_ssa_map_, saved_ssa_map, map_size);
    668     }
    669   }
    670   vreg_to_ssa_map_ = saved_ssa_map;
    671   return;
    672 }
    673 
    674 /* Perform SSA transformation for the whole method */
    675 void MIRGraph::SSATransformation() {
    676   /* Compute the DFS order */
    677   ComputeDFSOrders();
    678 
    679   /* Compute the dominator info */
    680   ComputeDominators();
    681 
    682   /* Allocate data structures in preparation for SSA conversion */
    683   CompilerInitializeSSAConversion();
    684 
    685   /* Find out the "Dalvik reg def x block" relation */
    686   ComputeDefBlockMatrix();
    687 
    688   /* Insert phi nodes to dominance frontiers for all variables */
    689   InsertPhiNodes();
    690 
    691   /* Rename register names by local defs and phi nodes */
    692   ClearAllVisitedFlags();
    693   DoDFSPreOrderSSARename(GetEntryBlock());
    694 
    695   /*
    696    * Shared temp bit vector used by each block to count the number of defs
    697    * from all the predecessor blocks.
    698    */
    699   temp_ssa_register_v_ =
    700       new (arena_) ArenaBitVector(arena_, GetNumSSARegs(), false, kBitMapTempSSARegisterV);
    701 
    702   /* Insert phi-operands with latest SSA names from predecessor blocks */
    703   ReachableNodesIterator iter2(this, false /* not iterative */);
    704   for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
    705     InsertPhiNodeOperands(bb);
    706   }
    707 
    708   if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
    709     DumpCFG("/sdcard/3_post_ssa_cfg/", false);
    710   }
    711   if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
    712     VerifyDataflow();
    713   }
    714 }
    715 
    716 }  // namespace art
    717