diff options
Diffstat (limited to 'compiler/optimizing/nodes.cc')
-rw-r--r-- | compiler/optimizing/nodes.cc | 95 |
1 files changed, 68 insertions, 27 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 989970fb49..ed401b67c5 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -21,6 +21,7 @@ #include "base/bit_vector-inl.h" #include "base/bit_utils.h" #include "base/stl_util.h" +#include "intrinsics.h" #include "mirror/class-inl.h" #include "scoped_thread_state_change.h" @@ -54,7 +55,6 @@ void HGraph::FindBackEdges(ArenaBitVector* visited) { visiting.ClearBit(current_id); worklist.pop_back(); } else { - DCHECK_LT(successors_visited[current_id], current->GetSuccessors().size()); HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++]; uint32_t successor_id = successor->GetBlockId(); if (visiting.IsBitSet(successor_id)) { @@ -88,7 +88,7 @@ static void RemoveAsUser(HInstruction* instruction) { void HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const { for (size_t i = 0; i < blocks_.size(); ++i) { if (!visited.IsBitSet(i)) { - HBasicBlock* block = GetBlock(i); + HBasicBlock* block = blocks_[i]; DCHECK(block->GetPhis().IsEmpty()) << "Phis are not inserted at this stage"; for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) { RemoveAsUser(it.Current()); @@ -100,7 +100,7 @@ void HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visit void HGraph::RemoveDeadBlocks(const ArenaBitVector& visited) { for (size_t i = 0; i < blocks_.size(); ++i) { if (!visited.IsBitSet(i)) { - HBasicBlock* block = GetBlock(i); + HBasicBlock* block = blocks_[i]; // We only need to update the successor, which might be live. for (HBasicBlock* successor : block->GetSuccessors()) { successor->RemovePredecessor(block); @@ -174,7 +174,6 @@ void HGraph::ComputeDominanceInformation() { if (successors_visited[current_id] == current->GetSuccessors().size()) { worklist.pop_back(); } else { - DCHECK_LT(successors_visited[current_id], current->GetSuccessors().size()); HBasicBlock* successor = current->GetSuccessors()[successors_visited[current_id]++]; if (successor->GetDominator() == nullptr) { @@ -185,7 +184,6 @@ void HGraph::ComputeDominanceInformation() { // Once all the forward edges have been visited, we know the immediate // dominator of the block. We can then start visiting its successors. - DCHECK_LT(successor->GetBlockId(), visits.size()); if (++visits[successor->GetBlockId()] == successor->GetPredecessors().size() - successor->NumberOfBackEdges()) { successor->GetDominator()->AddDominatedBlock(successor); @@ -257,7 +255,7 @@ void HGraph::SimplifyLoop(HBasicBlock* header) { pre_header->AddInstruction(new (arena_) HGoto(header->GetDexPc())); for (size_t pred = 0; pred < header->GetPredecessors().size(); ++pred) { - HBasicBlock* predecessor = header->GetPredecessor(pred); + HBasicBlock* predecessor = header->GetPredecessors()[pred]; if (!info->IsBackEdge(*predecessor)) { predecessor->ReplaceSuccessor(header, pre_header); pred--; @@ -267,10 +265,10 @@ void HGraph::SimplifyLoop(HBasicBlock* header) { } // Make sure the first predecessor of a loop header is the incoming block. - if (info->IsBackEdge(*header->GetPredecessor(0))) { - HBasicBlock* to_swap = header->GetPredecessor(0); + if (info->IsBackEdge(*header->GetPredecessors()[0])) { + HBasicBlock* to_swap = header->GetPredecessors()[0]; for (size_t pred = 1, e = header->GetPredecessors().size(); pred < e; ++pred) { - HBasicBlock* predecessor = header->GetPredecessor(pred); + HBasicBlock* predecessor = header->GetPredecessors()[pred]; if (!info->IsBackEdge(*predecessor)) { header->predecessors_[pred] = to_swap; header->predecessors_[0] = predecessor; @@ -293,7 +291,7 @@ void HGraph::SimplifyLoop(HBasicBlock* header) { } static bool CheckIfPredecessorAtIsExceptional(const HBasicBlock& block, size_t pred_idx) { - HBasicBlock* predecessor = block.GetPredecessor(pred_idx); + HBasicBlock* predecessor = block.GetPredecessors()[pred_idx]; if (!predecessor->EndsWithTryBoundary()) { // Only edges from HTryBoundary can be exceptional. return false; @@ -343,7 +341,7 @@ void HGraph::SimplifyCatchBlocks() { HBasicBlock* normal_block = catch_block->SplitBefore(catch_block->GetFirstInstruction()); for (size_t j = 0; j < catch_block->GetPredecessors().size(); ++j) { if (!CheckIfPredecessorAtIsExceptional(*catch_block, j)) { - catch_block->GetPredecessor(j)->ReplaceSuccessor(catch_block, normal_block); + catch_block->GetPredecessors()[j]->ReplaceSuccessor(catch_block, normal_block); --j; } } @@ -365,7 +363,7 @@ void HGraph::ComputeTryBlockInformation() { // Infer try membership from the first predecessor. Having simplified loops, // the first predecessor can never be a back edge and therefore it must have // been visited already and had its try membership set. - HBasicBlock* first_predecessor = block->GetPredecessor(0); + HBasicBlock* first_predecessor = block->GetPredecessors()[0]; DCHECK(!block->IsLoopHeader() || !block->GetLoopInformation()->IsBackEdge(*first_predecessor)); const HTryBoundary* try_entry = first_predecessor->ComputeTryEntryOfSuccessors(); if (try_entry != nullptr) { @@ -385,7 +383,7 @@ void HGraph::SimplifyCFG() { if (block == nullptr) continue; if (block->NumberOfNormalSuccessors() > 1) { for (size_t j = 0; j < block->GetSuccessors().size(); ++j) { - HBasicBlock* successor = block->GetSuccessor(j); + HBasicBlock* successor = block->GetSuccessors()[j]; DCHECK(!successor->IsCatchBlock()); if (successor->GetPredecessors().size() > 1) { SplitCriticalEdge(block, successor); @@ -534,7 +532,7 @@ bool HLoopInformation::Populate() { void HLoopInformation::Update() { HGraph* graph = header_->GetGraph(); for (uint32_t id : blocks_.Indexes()) { - HBasicBlock* block = graph->GetBlock(id); + HBasicBlock* block = graph->GetBlocks()[id]; // Reset loop information of non-header blocks inside the loop, except // members of inner nested loops because those should already have been // updated by their own LoopInformation. @@ -608,8 +606,23 @@ static void UpdateInputsUsers(HInstruction* instruction) { void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial, HInstruction* replacement) { DCHECK(initial->GetBlock() == this); - InsertInstructionBefore(replacement, initial); - initial->ReplaceWith(replacement); + if (initial->IsControlFlow()) { + // We can only replace a control flow instruction with another control flow instruction. + DCHECK(replacement->IsControlFlow()); + DCHECK_EQ(replacement->GetId(), -1); + DCHECK_EQ(replacement->GetType(), Primitive::kPrimVoid); + DCHECK_EQ(initial->GetBlock(), this); + DCHECK_EQ(initial->GetType(), Primitive::kPrimVoid); + DCHECK(initial->GetUses().IsEmpty()); + DCHECK(initial->GetEnvUses().IsEmpty()); + replacement->SetBlock(this); + replacement->SetId(GetGraph()->GetNextInstructionId()); + instructions_.InsertInstructionBefore(replacement, initial); + UpdateInputsUsers(replacement); + } else { + InsertInstructionBefore(replacement, initial); + initial->ReplaceWith(replacement); + } RemoveInstruction(initial); } @@ -743,7 +756,6 @@ void HEnvironment::CopyFromWithLoopPhiAdjustment(HEnvironment* env, } void HEnvironment::RemoveAsUserOfInput(size_t index) const { - DCHECK_LT(index, Size()); const HUserRecord<HEnvironment*>& user_record = vregs_[index]; user_record.GetInstruction()->RemoveEnvironmentUser(user_record.GetUseNode()); } @@ -1435,7 +1447,7 @@ void HBasicBlock::MergeWith(HBasicBlock* other) { // Update links to the successors of `other`. successors_.clear(); while (!other->successors_.empty()) { - HBasicBlock* successor = other->GetSuccessor(0); + HBasicBlock* successor = other->GetSuccessors()[0]; successor->ReplacePredecessor(other, this); } @@ -1472,7 +1484,7 @@ void HBasicBlock::MergeWithInlined(HBasicBlock* other) { // Update links to the successors of `other`. successors_.clear(); while (!other->successors_.empty()) { - HBasicBlock* successor = other->GetSuccessor(0); + HBasicBlock* successor = other->GetSuccessors()[0]; successor->ReplacePredecessor(other, this); } @@ -1488,11 +1500,11 @@ void HBasicBlock::MergeWithInlined(HBasicBlock* other) { void HBasicBlock::ReplaceWith(HBasicBlock* other) { while (!GetPredecessors().empty()) { - HBasicBlock* predecessor = GetPredecessor(0); + HBasicBlock* predecessor = GetPredecessors()[0]; predecessor->ReplaceSuccessor(this, other); } while (!GetSuccessors().empty()) { - HBasicBlock* successor = GetSuccessor(0); + HBasicBlock* successor = GetSuccessors()[0]; successor->ReplacePredecessor(this, other); } for (HBasicBlock* dominated : GetDominatedBlocks()) { @@ -1567,9 +1579,9 @@ HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { if (GetBlocks().size() == 3) { // Simple case of an entry block, a body block, and an exit block. // Put the body block's instruction into `invoke`'s block. - HBasicBlock* body = GetBlock(1); - DCHECK(GetBlock(0)->IsEntryBlock()); - DCHECK(GetBlock(2)->IsExitBlock()); + HBasicBlock* body = GetBlocks()[1]; + DCHECK(GetBlocks()[0]->IsEntryBlock()); + DCHECK(GetBlocks()[2]->IsExitBlock()); DCHECK(!body->IsExitBlock()); HInstruction* last = body->GetLastInstruction(); @@ -1594,16 +1606,16 @@ HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { HBasicBlock* at = invoke->GetBlock(); HBasicBlock* to = at->SplitAfter(invoke); - HBasicBlock* first = entry_block_->GetSuccessor(0); + HBasicBlock* first = entry_block_->GetSuccessors()[0]; DCHECK(!first->IsInLoop()); at->MergeWithInlined(first); exit_block_->ReplaceWith(to); // Update all predecessors of the exit block (now the `to` block) // to not `HReturn` but `HGoto` instead. - bool returns_void = to->GetPredecessor(0)->GetLastInstruction()->IsReturnVoid(); + bool returns_void = to->GetPredecessors()[0]->GetLastInstruction()->IsReturnVoid(); if (to->GetPredecessors().size() == 1) { - HBasicBlock* predecessor = to->GetPredecessor(0); + HBasicBlock* predecessor = to->GetPredecessors()[0]; HInstruction* last = predecessor->GetLastInstruction(); if (!returns_void) { return_value = last->InputAt(0); @@ -1873,6 +1885,35 @@ bool HInstruction::HasAnyEnvironmentUseBefore(HInstruction* other) { return false; } +void HInvoke::SetIntrinsic(Intrinsics intrinsic, + IntrinsicNeedsEnvironmentOrCache needs_env_or_cache) { + intrinsic_ = intrinsic; + IntrinsicOptimizations opt(this); + if (needs_env_or_cache == kNoEnvironmentOrCache) { + opt.SetDoesNotNeedDexCache(); + opt.SetDoesNotNeedEnvironment(); + } +} + +bool HInvoke::NeedsEnvironment() const { + if (!IsIntrinsic()) { + return true; + } + IntrinsicOptimizations opt(*this); + return !opt.GetDoesNotNeedEnvironment(); +} + +bool HInvokeStaticOrDirect::NeedsDexCache() const { + if (IsRecursive() || IsStringInit()) { + return false; + } + if (!IsIntrinsic()) { + return true; + } + IntrinsicOptimizations opt(*this); + return !opt.GetDoesNotNeedDexCache(); +} + void HInstruction::RemoveEnvironmentUsers() { for (HUseIterator<HEnvironment*> use_it(GetEnvUses()); !use_it.Done(); use_it.Advance()) { HUseListNode<HEnvironment*>* user_node = use_it.Current(); |