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