diff options
Diffstat (limited to 'compiler/optimizing/nodes.cc')
| -rw-r--r-- | compiler/optimizing/nodes.cc | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index ca48e08a7c..ddd798b4a5 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -90,7 +90,8 @@ void HGraph::FindBackEdges(ArenaBitVector* visited) { } } -static void RemoveEnvironmentUses(HInstruction* instruction) { +// Remove the environment use records of the instruction for users. +void RemoveEnvironmentUses(HInstruction* instruction) { for (HEnvironment* environment = instruction->GetEnvironment(); environment != nullptr; environment = environment->GetParent()) { @@ -102,6 +103,35 @@ static void RemoveEnvironmentUses(HInstruction* instruction) { } } +// Return whether the instruction has an environment and it's used by others. +bool HasEnvironmentUsedByOthers(HInstruction* instruction) { + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { + for (size_t i = 0, e = environment->Size(); i < e; ++i) { + HInstruction* user = environment->GetInstructionAt(i); + if (user != nullptr) { + return true; + } + } + } + return false; +} + +// Reset environment records of the instruction itself. +void ResetEnvironmentInputRecords(HInstruction* instruction) { + for (HEnvironment* environment = instruction->GetEnvironment(); + environment != nullptr; + environment = environment->GetParent()) { + for (size_t i = 0, e = environment->Size(); i < e; ++i) { + DCHECK(environment->GetHolder() == instruction); + if (environment->GetInstructionAt(i) != nullptr) { + environment->SetRawEnvAt(i, nullptr); + } + } + } +} + static void RemoveAsUser(HInstruction* instruction) { instruction->RemoveAsUserOfAllInputs(); RemoveEnvironmentUses(instruction); @@ -328,6 +358,35 @@ void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) { } } +// Reorder phi inputs to match reordering of the block's predecessors. +static void FixPhisAfterPredecessorsReodering(HBasicBlock* block, size_t first, size_t second) { + for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { + HPhi* phi = it.Current()->AsPhi(); + HInstruction* first_instr = phi->InputAt(first); + HInstruction* second_instr = phi->InputAt(second); + phi->ReplaceInput(first_instr, second); + phi->ReplaceInput(second_instr, first); + } +} + +// Make sure that the first predecessor of a loop header is the incoming block. +void HGraph::OrderLoopHeaderPredecessors(HBasicBlock* header) { + DCHECK(header->IsLoopHeader()); + HLoopInformation* info = header->GetLoopInformation(); + 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->GetPredecessors()[pred]; + if (!info->IsBackEdge(*predecessor)) { + header->predecessors_[pred] = to_swap; + header->predecessors_[0] = predecessor; + FixPhisAfterPredecessorsReodering(header, 0, pred); + break; + } + } + } +} + void HGraph::SimplifyLoop(HBasicBlock* header) { HLoopInformation* info = header->GetLoopInformation(); @@ -351,18 +410,7 @@ void HGraph::SimplifyLoop(HBasicBlock* header) { pre_header->AddSuccessor(header); } - // Make sure the first predecessor of a loop header is the incoming block. - 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->GetPredecessors()[pred]; - if (!info->IsBackEdge(*predecessor)) { - header->predecessors_[pred] = to_swap; - header->predecessors_[0] = predecessor; - break; - } - } - } + OrderLoopHeaderPredecessors(header); HInstruction* first_instruction = header->GetFirstInstruction(); if (first_instruction != nullptr && first_instruction->IsSuspendCheck()) { |