OSDN Git Service

Merge "Revert "ART: Better SSA Allocation when recreating SSA""
authorBill Buzbee <buzbee@android.com>
Fri, 23 May 2014 23:02:20 +0000 (23:02 +0000)
committerGerrit Code Review <noreply-gerritcodereview@google.com>
Fri, 23 May 2014 23:02:21 +0000 (23:02 +0000)
1  2 
compiler/dex/mir_dataflow.cc
compiler/dex/mir_graph.cc
compiler/dex/mir_graph.h
compiler/dex/ssa_transformation.cc

@@@ -953,30 -947,9 +953,9 @@@ void MIRGraph::HandleSSADef(int* defs, 
    defs[reg_index] = ssa_reg;
  }
  
- void MIRGraph::AllocateSSAUseData(MIR *mir, int num_uses) {
-   mir->ssa_rep->num_uses = num_uses;
-   if (mir->ssa_rep->num_uses_allocated < num_uses) {
-     mir->ssa_rep->uses = static_cast<int*>(arena_->Alloc(sizeof(int) * num_uses, kArenaAllocDFInfo));
-     // NOTE: will be filled in during type & size inference pass
-     mir->ssa_rep->fp_use = static_cast<bool*>(arena_->Alloc(sizeof(bool) * num_uses, kArenaAllocDFInfo));
-   }
- }
- void MIRGraph::AllocateSSADefData(MIR *mir, int num_defs) {
-   mir->ssa_rep->num_defs = num_defs;
-   if (mir->ssa_rep->num_defs_allocated < num_defs) {
-     mir->ssa_rep->defs = static_cast<int*>(arena_->Alloc(sizeof(int) * num_defs,
-           kArenaAllocDFInfo));
-     mir->ssa_rep->fp_def = static_cast<bool*>(arena_->Alloc(sizeof(bool) * num_defs,
-           kArenaAllocDFInfo));
-   }
- }
  /* Look up new SSA names for format_35c instructions */
  void MIRGraph::DataFlowSSAFormat35C(MIR* mir) {
 -  DecodedInstruction *d_insn = &mir->dalvikInsn;
 +  MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
    int num_uses = d_insn->vA;
    int i;
  
@@@ -1016,9 -993,8 +999,8 @@@ bool MIRGraph::DoSSAConversion(BasicBlo
      mir->ssa_rep =
          static_cast<struct SSARepresentation *>(arena_->Alloc(sizeof(SSARepresentation),
                                                                kArenaAllocDFInfo));
-     memset(mir->ssa_rep, 0, sizeof(*mir->ssa_rep));
  
 -    uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
 +    uint64_t df_attributes = GetDataFlowAttributes(mir);
  
        // If not a pseudo-op, note non-leaf or can throw
      if (static_cast<int>(mir->dalvikInsn.opcode) <
        }
      }
  
-     AllocateSSADefData(mir, num_defs);
+     if (num_defs) {
+       mir->ssa_rep->num_defs = num_defs;
+       mir->ssa_rep->defs = static_cast<int*>(arena_->Alloc(sizeof(int) * num_defs,
+                                                            kArenaAllocDFInfo));
+       mir->ssa_rep->fp_def = static_cast<bool*>(arena_->Alloc(sizeof(bool) * num_defs,
+                                                               kArenaAllocDFInfo));
+     }
  
 -    DecodedInstruction *d_insn = &mir->dalvikInsn;
 +    MIR::DecodedInstruction* d_insn = &mir->dalvikInsn;
  
      if (df_attributes & DF_HAS_USES) {
        num_uses = 0;
@@@ -1436,482 -1237,6 +1435,479 @@@ void MIRGraph::SSATransformationStart(
    /* Rename register names by local defs and phi nodes */
    ClearAllVisitedFlags();
    DoDFSPreOrderSSARename(GetEntryBlock());
-   // Update the maximum number of reachable blocks.
-   max_num_reachable_blocks_ = num_reachable_blocks_;
  }
  
 +void MIRGraph::SSATransformationEnd() {
 +  // Verify the dataflow information after the pass.
 +  if (cu_->enable_debug & (1 << kDebugVerifyDataflow)) {
 +    VerifyDataflow();
 +  }
 +
 +  temp_bit_vector_size_ = 0u;
 +  temp_bit_vector_ = nullptr;
 +  DCHECK(temp_scoped_alloc_.get() != nullptr);
 +  temp_scoped_alloc_.reset();
 +}
 +
 +void MIRGraph::ComputeTopologicalSortOrder() {
 +  std::queue<BasicBlock *> q;
 +  std::map<int, int> visited_cnt_values;
 +
 +  // Clear the nodes.
 +  ClearAllVisitedFlags();
 +
 +  // Create the topological order if need be.
 +  if (topological_order_ != nullptr) {
 +    topological_order_ = new (arena_) GrowableArray<BasicBlockId>(arena_, 0);
 +  }
 +  topological_order_->Reset();
 +
 +  // Set up visitedCntValues map for all BB. The default value for this counters in the map is zero.
 +  // also fill initial queue.
 +  GrowableArray<BasicBlock*>::Iterator iterator(&block_list_);
 +
 +  while (true) {
 +    BasicBlock* bb = iterator.Next();
 +
 +    if (bb == nullptr) {
 +      break;
 +    }
 +
 +    if (bb->hidden == true) {
 +      continue;
 +    }
 +
 +    visited_cnt_values[bb->id] = bb->predecessors->Size();
 +
 +    GrowableArray<BasicBlockId>::Iterator pred_iterator(bb->predecessors);
 +    // To process loops we should not wait for dominators.
 +    while (true) {
 +      BasicBlock* pred_bb = GetBasicBlock(pred_iterator.Next());
 +
 +      if (pred_bb == nullptr) {
 +        break;
 +      }
 +
 +      if (pred_bb->dominators == nullptr || pred_bb->hidden == true) {
 +        continue;
 +      }
 +
 +      // Skip the backward branch.
 +      if (pred_bb->dominators->IsBitSet(bb->id) != 0) {
 +        visited_cnt_values[bb->id]--;
 +      }
 +    }
 +
 +    // Add entry block to queue.
 +    if (visited_cnt_values[bb->id] == 0) {
 +      q.push(bb);
 +    }
 +  }
 +
 +  while (q.size() > 0) {
 +    // Get top.
 +    BasicBlock *bb = q.front();
 +    q.pop();
 +
 +    DCHECK_EQ(bb->hidden, false);
 +
 +    if (bb->IsExceptionBlock() == true) {
 +      continue;
 +    }
 +
 +    // We've visited all the predecessors. So, we can visit bb.
 +    if (bb->visited == false) {
 +      bb->visited = true;
 +
 +      // Now add the basic block.
 +      topological_order_->Insert(bb->id);
 +
 +      // Reduce visitedCnt for all the successors and add into the queue ones with visitedCnt equals to zero.
 +      ChildBlockIterator succIter(bb, this);
 +      BasicBlock *successor = succIter.Next();
 +      while (successor != nullptr) {
 +        // one more predecessor was visited.
 +        visited_cnt_values[successor->id]--;
 +
 +        if (visited_cnt_values[successor->id] <= 0 && successor->visited == false && successor->hidden == false) {
 +          q.push(successor);
 +        }
 +
 +        // Take next successor.
 +        successor = succIter.Next();
 +      }
 +    }
 +  }
 +}
 +
 +bool BasicBlock::IsExceptionBlock() const {
 +  if (block_type == kExceptionHandling) {
 +    return true;
 +  }
 +  return false;
 +}
 +
 +ChildBlockIterator::ChildBlockIterator(BasicBlock* bb, MIRGraph* mir_graph)
 +    : basic_block_(bb), mir_graph_(mir_graph), visited_fallthrough_(false),
 +      visited_taken_(false), have_successors_(false) {
 +  // Check if we actually do have successors.
 +  if (basic_block_ != 0 && basic_block_->successor_block_list_type != kNotUsed) {
 +    have_successors_ = true;
 +    successor_iter_.Reset(basic_block_->successor_blocks);
 +  }
 +}
 +
 +BasicBlock* ChildBlockIterator::Next() {
 +  // We check if we have a basic block. If we don't we cannot get next child.
 +  if (basic_block_ == nullptr) {
 +    return nullptr;
 +  }
 +
 +  // If we haven't visited fallthrough, return that.
 +  if (visited_fallthrough_ == false) {
 +    visited_fallthrough_ = true;
 +
 +    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->fall_through);
 +    if (result != nullptr) {
 +      return result;
 +    }
 +  }
 +
 +  // If we haven't visited taken, return that.
 +  if (visited_taken_ == false) {
 +    visited_taken_ = true;
 +
 +    BasicBlock* result = mir_graph_->GetBasicBlock(basic_block_->taken);
 +    if (result != nullptr) {
 +      return result;
 +    }
 +  }
 +
 +  // We visited both taken and fallthrough. Now check if we have successors we need to visit.
 +  if (have_successors_ == true) {
 +    // Get information about next successor block.
 +    SuccessorBlockInfo* successor_block_info = successor_iter_.Next();
 +
 +    // If we don't have anymore successors, return nullptr.
 +    if (successor_block_info != nullptr) {
 +      return mir_graph_->GetBasicBlock(successor_block_info->block);
 +    }
 +  }
 +
 +  // We do not have anything.
 +  return nullptr;
 +}
 +
 +BasicBlock* BasicBlock::Copy(CompilationUnit* c_unit) {
 +  MIRGraph* mir_graph = c_unit->mir_graph.get();
 +  return Copy(mir_graph);
 +}
 +
 +BasicBlock* BasicBlock::Copy(MIRGraph* mir_graph) {
 +  BasicBlock* result_bb = mir_graph->CreateNewBB(block_type);
 +
 +  // We don't do a memcpy style copy here because it would lead to a lot of things
 +  // to clean up. Let us do it by hand instead.
 +  // Copy in taken and fallthrough.
 +  result_bb->fall_through = fall_through;
 +  result_bb->taken = taken;
 +
 +  // Copy successor links if needed.
 +  ArenaAllocator* arena = mir_graph->GetArena();
 +
 +  result_bb->successor_block_list_type = successor_block_list_type;
 +  if (result_bb->successor_block_list_type != kNotUsed) {
 +    size_t size = successor_blocks->Size();
 +    result_bb->successor_blocks = new (arena) GrowableArray<SuccessorBlockInfo*>(arena, size, kGrowableArraySuccessorBlocks);
 +    GrowableArray<SuccessorBlockInfo*>::Iterator iterator(successor_blocks);
 +    while (true) {
 +      SuccessorBlockInfo* sbi_old = iterator.Next();
 +      if (sbi_old == nullptr) {
 +        break;
 +      }
 +      SuccessorBlockInfo* sbi_new = static_cast<SuccessorBlockInfo*>(arena->Alloc(sizeof(SuccessorBlockInfo), kArenaAllocSuccessor));
 +      memcpy(sbi_new, sbi_old, sizeof(SuccessorBlockInfo));
 +      result_bb->successor_blocks->Insert(sbi_new);
 +    }
 +  }
 +
 +  // Copy offset, method.
 +  result_bb->start_offset = start_offset;
 +
 +  // Now copy instructions.
 +  for (MIR* mir = first_mir_insn; mir != 0; mir = mir->next) {
 +    // Get a copy first.
 +    MIR* copy = mir->Copy(mir_graph);
 +
 +    // Append it.
 +    result_bb->AppendMIR(copy);
 +  }
 +
 +  return result_bb;
 +}
 +
 +MIR* MIR::Copy(MIRGraph* mir_graph) {
 +  MIR* res = mir_graph->NewMIR();
 +  *res = *this;
 +
 +  // Remove links
 +  res->next = nullptr;
 +  res->bb = NullBasicBlockId;
 +  res->ssa_rep = nullptr;
 +
 +  return res;
 +}
 +
 +MIR* MIR::Copy(CompilationUnit* c_unit) {
 +  return Copy(c_unit->mir_graph.get());
 +}
 +
 +uint32_t SSARepresentation::GetStartUseIndex(Instruction::Code opcode) {
 +  // Default result.
 +  int res = 0;
 +
 +  // We are basically setting the iputs to their igets counterparts.
 +  switch (opcode) {
 +    case Instruction::IPUT:
 +    case Instruction::IPUT_OBJECT:
 +    case Instruction::IPUT_BOOLEAN:
 +    case Instruction::IPUT_BYTE:
 +    case Instruction::IPUT_CHAR:
 +    case Instruction::IPUT_SHORT:
 +    case Instruction::IPUT_QUICK:
 +    case Instruction::IPUT_OBJECT_QUICK:
 +    case Instruction::APUT:
 +    case Instruction::APUT_OBJECT:
 +    case Instruction::APUT_BOOLEAN:
 +    case Instruction::APUT_BYTE:
 +    case Instruction::APUT_CHAR:
 +    case Instruction::APUT_SHORT:
 +    case Instruction::SPUT:
 +    case Instruction::SPUT_OBJECT:
 +    case Instruction::SPUT_BOOLEAN:
 +    case Instruction::SPUT_BYTE:
 +    case Instruction::SPUT_CHAR:
 +    case Instruction::SPUT_SHORT:
 +      // Skip the VR containing what to store.
 +      res = 1;
 +      break;
 +    case Instruction::IPUT_WIDE:
 +    case Instruction::IPUT_WIDE_QUICK:
 +    case Instruction::APUT_WIDE:
 +    case Instruction::SPUT_WIDE:
 +      // Skip the two VRs containing what to store.
 +      res = 2;
 +      break;
 +    default:
 +      // Do nothing in the general case.
 +      break;
 +  }
 +
 +  return res;
 +}
 +
 +/**
 + * @brief Given a decoded instruction, it checks whether the instruction
 + * sets a constant and if it does, more information is provided about the
 + * constant being set.
 + * @param ptr_value pointer to a 64-bit holder for the constant.
 + * @param wide Updated by function whether a wide constant is being set by bytecode.
 + * @return Returns false if the decoded instruction does not represent a constant bytecode.
 + */
 +bool MIR::DecodedInstruction::GetConstant(int64_t* ptr_value, bool* wide) const {
 +  bool sets_const = true;
 +  int64_t value = vB;
 +
 +  DCHECK(ptr_value != nullptr);
 +  DCHECK(wide != nullptr);
 +
 +  switch (opcode) {
 +    case Instruction::CONST_4:
 +    case Instruction::CONST_16:
 +    case Instruction::CONST:
 +      *wide = false;
 +      value <<= 32;      // In order to get the sign extend.
 +      value >>= 32;
 +      break;
 +    case Instruction::CONST_HIGH16:
 +      *wide = false;
 +      value <<= 48;      // In order to get the sign extend.
 +      value >>= 32;
 +      break;
 +    case Instruction::CONST_WIDE_16:
 +    case Instruction::CONST_WIDE_32:
 +      *wide = true;
 +      value <<= 32;      // In order to get the sign extend.
 +      value >>= 32;
 +      break;
 +    case Instruction::CONST_WIDE:
 +      *wide = true;
 +      value = vB_wide;
 +      break;
 +    case Instruction::CONST_WIDE_HIGH16:
 +      *wide = true;
 +      value <<= 48;      // In order to get the sign extend.
 +      break;
 +    default:
 +      sets_const = false;
 +      break;
 +  }
 +
 +  if (sets_const) {
 +    *ptr_value = value;
 +  }
 +
 +  return sets_const;
 +}
 +
 +void BasicBlock::ResetOptimizationFlags(uint16_t reset_flags) {
 +  // Reset flags for all MIRs in bb.
 +  for (MIR* mir = first_mir_insn; mir != NULL; mir = mir->next) {
 +    mir->optimization_flags &= (~reset_flags);
 +  }
 +}
 +
 +void BasicBlock::Hide(CompilationUnit* c_unit) {
 +  // First lets make it a dalvik bytecode block so it doesn't have any special meaning.
 +  block_type = kDalvikByteCode;
 +
 +  // Mark it as hidden.
 +  hidden = true;
 +
 +  // Detach it from its MIRs so we don't generate code for them. Also detached MIRs
 +  // are updated to know that they no longer have a parent.
 +  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
 +    mir->bb = NullBasicBlockId;
 +  }
 +  first_mir_insn = nullptr;
 +  last_mir_insn = nullptr;
 +
 +  GrowableArray<BasicBlockId>::Iterator iterator(predecessors);
 +
 +  MIRGraph* mir_graph = c_unit->mir_graph.get();
 +  while (true) {
 +    BasicBlock* pred_bb = mir_graph->GetBasicBlock(iterator.Next());
 +    if (pred_bb == nullptr) {
 +      break;
 +    }
 +
 +    // Sadly we have to go through the children by hand here.
 +    pred_bb->ReplaceChild(id, NullBasicBlockId);
 +  }
 +
 +  // Iterate through children of bb we are hiding.
 +  ChildBlockIterator successorChildIter(this, mir_graph);
 +
 +  for (BasicBlock* childPtr = successorChildIter.Next(); childPtr != 0; childPtr = successorChildIter.Next()) {
 +    // Replace child with null child.
 +    childPtr->predecessors->Delete(id);
 +  }
 +}
 +
 +bool BasicBlock::IsSSALiveOut(const CompilationUnit* c_unit, int ssa_reg) {
 +  // In order to determine if the ssa reg is live out, we scan all the MIRs. We remember
 +  // the last SSA number of the same dalvik register. At the end, if it is different than ssa_reg,
 +  // then it is not live out of this BB.
 +  int dalvik_reg = c_unit->mir_graph->SRegToVReg(ssa_reg);
 +
 +  int last_ssa_reg = -1;
 +
 +  // Walk through the MIRs backwards.
 +  for (MIR* mir = first_mir_insn; mir != nullptr; mir = mir->next) {
 +    // Get ssa rep.
 +    SSARepresentation *ssa_rep = mir->ssa_rep;
 +
 +    // Go through the defines for this MIR.
 +    for (int i = 0; i < ssa_rep->num_defs; i++) {
 +      DCHECK(ssa_rep->defs != nullptr);
 +
 +      // Get the ssa reg.
 +      int def_ssa_reg = ssa_rep->defs[i];
 +
 +      // Get dalvik reg.
 +      int def_dalvik_reg = c_unit->mir_graph->SRegToVReg(def_ssa_reg);
 +
 +      // Compare dalvik regs.
 +      if (dalvik_reg == def_dalvik_reg) {
 +        // We found a def of the register that we are being asked about.
 +        // Remember it.
 +        last_ssa_reg = def_ssa_reg;
 +      }
 +    }
 +  }
 +
 +  if (last_ssa_reg == -1) {
 +    // If we get to this point we couldn't find a define of register user asked about.
 +    // Let's assume the user knows what he's doing so we can be safe and say that if we
 +    // couldn't find a def, it is live out.
 +    return true;
 +  }
 +
 +  // If it is not -1, we found a match, is it ssa_reg?
 +  return (ssa_reg == last_ssa_reg);
 +}
 +
 +bool BasicBlock::ReplaceChild(BasicBlockId old_bb, BasicBlockId new_bb) {
 +  // We need to check taken, fall_through, and successor_blocks to replace.
 +  bool found = false;
 +  if (taken == old_bb) {
 +    taken = new_bb;
 +    found = true;
 +  }
 +
 +  if (fall_through == old_bb) {
 +    fall_through = new_bb;
 +    found = true;
 +  }
 +
 +  if (successor_block_list_type != kNotUsed) {
 +    GrowableArray<SuccessorBlockInfo*>::Iterator iterator(successor_blocks);
 +    while (true) {
 +      SuccessorBlockInfo* successor_block_info = iterator.Next();
 +      if (successor_block_info == nullptr) {
 +        break;
 +      }
 +      if (successor_block_info->block == old_bb) {
 +        successor_block_info->block = new_bb;
 +        found = true;
 +      }
 +    }
 +  }
 +
 +  return found;
 +}
 +
 +void BasicBlock::UpdatePredecessor(BasicBlockId old_parent, BasicBlockId new_parent) {
 +  GrowableArray<BasicBlockId>::Iterator iterator(predecessors);
 +  bool found = false;
 +
 +  while (true) {
 +    BasicBlockId pred_bb_id = iterator.Next();
 +
 +    if (pred_bb_id == NullBasicBlockId) {
 +      break;
 +    }
 +
 +    if (pred_bb_id == old_parent) {
 +      size_t idx = iterator.GetIndex() - 1;
 +      predecessors->Put(idx, new_parent);
 +      found = true;
 +      break;
 +    }
 +  }
 +
 +  // If not found, add it.
 +  if (found == false) {
 +    predecessors->Insert(new_parent);
 +  }
 +}
 +
 +// Create a new basic block with block_id as num_blocks_ that is
 +// post-incremented.
 +BasicBlock* MIRGraph::CreateNewBB(BBType block_type) {
 +  BasicBlock* res = NewMemBB(block_type, num_blocks_++);
 +  block_list_.Insert(res);
 +  return res;
 +}
 +
  }  // namespace art
Simple merge
Simple merge