diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 249 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 8 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.cc | 6 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 28 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_mips64.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_mips64.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 21 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 37 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 66 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 108 |
18 files changed, 98 insertions, 539 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 742429cc55..e527e8bc7c 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -259,165 +259,6 @@ bool HGraphBuilder::SkipCompilation(const DexFile::CodeItem& code_item, return false; } -bool HGraphBuilder::IsBlockInPcRange(HBasicBlock* block, - uint32_t dex_pc_start, - uint32_t dex_pc_end) { - uint32_t dex_pc = block->GetDexPc(); - return block != entry_block_ - && block != exit_block_ - && dex_pc >= dex_pc_start - && dex_pc < dex_pc_end; -} - -void HGraphBuilder::CreateBlocksForTryCatch(const DexFile::CodeItem& code_item) { - if (code_item.tries_size_ == 0) { - return; - } - - // Create branch targets at the start/end of the TryItem range. These are - // places where the program might fall through into/out of the a block and - // where TryBoundary instructions will be inserted later. Other edges which - // enter/exit the try blocks are a result of branches/switches. - for (size_t idx = 0; idx < code_item.tries_size_; ++idx) { - const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx); - uint32_t dex_pc_start = try_item->start_addr_; - uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_; - FindOrCreateBlockStartingAt(dex_pc_start); - if (dex_pc_end < code_item.insns_size_in_code_units_) { - // TODO: Do not create block if the last instruction cannot fall through. - FindOrCreateBlockStartingAt(dex_pc_end); - } else { - // The TryItem spans until the very end of the CodeItem (or beyond if - // invalid) and therefore cannot have any code afterwards. - } - } - - // Create branch targets for exception handlers. - const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0); - uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); - for (uint32_t idx = 0; idx < handlers_size; ++idx) { - CatchHandlerIterator iterator(handlers_ptr); - for (; iterator.HasNext(); iterator.Next()) { - uint32_t address = iterator.GetHandlerAddress(); - HBasicBlock* block = FindOrCreateBlockStartingAt(address); - block->SetIsCatchBlock(); - } - handlers_ptr = iterator.EndDataPointer(); - } -} - -void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item) { - if (code_item.tries_size_ == 0) { - return; - } - - for (size_t idx = 0; idx < code_item.tries_size_; ++idx) { - const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item, idx); - uint32_t try_start = try_item->start_addr_; - uint32_t try_end = try_start + try_item->insn_count_; - - // Iterate over all blocks in the dex pc range of the TryItem and: - // (a) split edges which enter/exit the try range, - // (b) create TryBoundary instructions in the new blocks, - // (c) link the new blocks to corresponding exception handlers. - for (uint32_t inner_pc = try_start; inner_pc < try_end; ++inner_pc) { - HBasicBlock* try_block = FindBlockStartingAt(inner_pc); - if (try_block == nullptr) { - continue; - } - - // Find predecessors which are not covered by the same TryItem range. Such - // edges enter the try block and will have a TryBoundary inserted. - for (size_t i = 0; i < try_block->GetPredecessors().Size(); ++i) { - HBasicBlock* predecessor = try_block->GetPredecessors().Get(i); - HTryBoundary* try_boundary = nullptr; - if (predecessor->IsSingleTryBoundary()) { - try_boundary = predecessor->GetLastInstruction()->AsTryBoundary(); - if (try_boundary->GetNormalFlowSuccessor() == try_block - && try_block->IsFirstIndexOfPredecessor(predecessor, i)) { - // The edge was already split because of an exit from a neighbouring - // TryItem and `predecessor` is the block with a TryBoundary created - // between the two original blocks. We do not split the edge again. - DCHECK(!IsBlockInPcRange(predecessor->GetSinglePredecessor(), try_start, try_end)); - DCHECK(try_boundary->IsTryExit()); - DCHECK(!try_boundary->IsTryEntry()); - try_boundary->SetIsTryEntry(); - } else { - // This is an edge between a previously created TryBoundary and its - // handler. We skip it because it is exceptional flow. - DCHECK(try_block->IsCatchBlock()); - DCHECK(try_boundary->HasExceptionHandler(try_block)); - continue; - } - } else if (!IsBlockInPcRange(predecessor, try_start, try_end)) { - // This is an entry point into the TryItem and the edge has not been - // split yet. That means that either `predecessor` is not in a TryItem, - // or it is in a different TryItem and we happened to iterate over - // this block first. We split the edge and `predecessor` may add its - // own exception handlers later. - try_boundary = new (arena_) HTryBoundary(/* is_entry */ true, /* is_exit */ false); - HBasicBlock* try_entry_block = graph_->SplitEdge(predecessor, try_block); - try_entry_block->AddInstruction(try_boundary); - } else { - // Not an edge on the boundary of the try block. - continue; - } - DCHECK(try_boundary != nullptr); - - // Link the TryBoundary block to the handlers of this TryItem. - for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) { - try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress())); - } - } - - // Find successors which are not covered by the same TryItem range. Such - // edges exit the try block and will have a TryBoundary inserted. - for (size_t i = 0; i < try_block->GetSuccessors().Size(); ++i) { - HBasicBlock* successor = try_block->GetSuccessors().Get(i); - HTryBoundary* try_boundary = nullptr; - if (successor->IsSingleTryBoundary()) { - // The edge was already split because of an entry into a neighbouring - // TryItem. We do not split the edge again. - try_boundary = successor->GetLastInstruction()->AsTryBoundary(); - DCHECK_EQ(try_block, successor->GetSinglePredecessor()); - DCHECK(try_boundary->IsTryEntry()); - DCHECK(!try_boundary->IsTryExit()); - DCHECK(!IsBlockInPcRange(try_boundary->GetNormalFlowSuccessor(), try_start, try_end)); - try_boundary->SetIsTryExit(); - } else if (!IsBlockInPcRange(successor, try_start, try_end)) { - // This is an exit out of the TryItem and the edge has not been split - // yet. That means that either `successor` is not in a TryItem, or it - // is in a different TryItem and we happened to iterate over this - // block first. We split the edge and `successor` may add its own - // exception handlers later. - HInstruction* last_instruction = try_block->GetLastInstruction(); - if (last_instruction->IsReturn() || last_instruction->IsReturnVoid()) { - DCHECK_EQ(successor, exit_block_); - // Control flow exits the try block with a Return(Void). Because - // splitting the edge would invalidate the invariant that Return - // always jumps to Exit, we move the Return outside the try block. - HBasicBlock* return_block = try_block->SplitBefore(last_instruction); - graph_->AddBlock(return_block); - successor = return_block; - } - try_boundary = new (arena_) HTryBoundary(/* is_entry */ false, /* is_exit */ true); - HBasicBlock* try_exit_block = graph_->SplitEdge(try_block, successor); - try_exit_block->AddInstruction(try_boundary); - } else { - // Not an edge on the boundary of the try block. - continue; - } - DCHECK(try_boundary != nullptr); - - // Link the TryBoundary block to the handlers of this TryItem. - for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) { - try_boundary->AddExceptionHandler(FindBlockStartingAt(it.GetHandlerAddress())); - } - } - } - } -} - bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { DCHECK(graph_->GetBlocks().IsEmpty()); @@ -451,7 +292,24 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { return false; } - CreateBlocksForTryCatch(code_item); + // Also create blocks for catch handlers. + if (code_item.tries_size_ != 0) { + const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item, 0); + uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); + for (uint32_t idx = 0; idx < handlers_size; ++idx) { + CatchHandlerIterator iterator(handlers_ptr); + for (; iterator.HasNext(); iterator.Next()) { + uint32_t address = iterator.GetHandlerAddress(); + HBasicBlock* block = FindBlockStartingAt(address); + if (block == nullptr) { + block = new (arena_) HBasicBlock(graph_, address); + branch_targets_.Put(address, block); + } + block->SetIsCatchBlock(); + } + handlers_ptr = iterator.EndDataPointer(); + } + } InitializeParameters(code_item.ins_size_); @@ -467,24 +325,18 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { code_ptr += instruction.SizeInCodeUnits(); } + // Add the exit block at the end to give it the highest id. + graph_->AddBlock(exit_block_); + exit_block_->AddInstruction(new (arena_) HExit()); // Add the suspend check to the entry block. entry_block_->AddInstruction(new (arena_) HSuspendCheck(0)); entry_block_->AddInstruction(new (arena_) HGoto()); - // Add Exit to the exit block. - exit_block_->AddInstruction(new (arena_) HExit()); - - // Iterate over blocks covered by TryItems and insert TryBoundaries at entry - // and exit points. This requires all control-flow instructions and - // non-exceptional edges to have been created. - InsertTryBoundaryBlocks(code_item); - // Add the exit block at the end to give it the highest id. - graph_->AddBlock(exit_block_); return true; } -void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) { - HBasicBlock* block = FindBlockStartingAt(dex_pc); +void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) { + HBasicBlock* block = FindBlockStartingAt(index); if (block == nullptr) { return; } @@ -519,8 +371,10 @@ bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, (*number_of_branches)++; int32_t target = instruction.GetTargetOffset() + dex_pc; // Create a block for the target instruction. - FindOrCreateBlockStartingAt(target); - + if (FindBlockStartingAt(target) == nullptr) { + block = new (arena_) HBasicBlock(graph_, target); + branch_targets_.Put(target, block); + } dex_pc += instruction.SizeInCodeUnits(); code_ptr += instruction.SizeInCodeUnits(); @@ -529,8 +383,9 @@ bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, // In the normal case we should never hit this but someone can artificially forge a dex // file to fall-through out the method code. In this case we bail out compilation. return false; - } else { - FindOrCreateBlockStartingAt(dex_pc); + } else if (FindBlockStartingAt(dex_pc) == nullptr) { + block = new (arena_) HBasicBlock(graph_, dex_pc); + branch_targets_.Put(dex_pc, block); } } } else if (instruction.IsSwitch()) { @@ -546,7 +401,10 @@ bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, for (size_t i = 0; i < num_entries; ++i) { // The target of the case. uint32_t target = dex_pc + table.GetEntryAt(i + offset); - FindOrCreateBlockStartingAt(target); + if (FindBlockStartingAt(target) == nullptr) { + block = new (arena_) HBasicBlock(graph_, target); + branch_targets_.Put(target, block); + } // The next case gets its own block. if (i < num_entries) { @@ -563,8 +421,9 @@ bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, // file to fall-through out the method code. In this case we bail out compilation. // (A switch can fall-through so we don't need to check CanFlowThrough().) return false; - } else { - FindOrCreateBlockStartingAt(dex_pc); + } else if (FindBlockStartingAt(dex_pc) == nullptr) { + block = new (arena_) HBasicBlock(graph_, dex_pc); + branch_targets_.Put(dex_pc, block); } } else { code_ptr += instruction.SizeInCodeUnits(); @@ -574,19 +433,9 @@ bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, return true; } -HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t dex_pc) const { - DCHECK_GE(dex_pc, 0); - DCHECK_LT(static_cast<size_t>(dex_pc), branch_targets_.Size()); - return branch_targets_.Get(dex_pc); -} - -HBasicBlock* HGraphBuilder::FindOrCreateBlockStartingAt(int32_t dex_pc) { - HBasicBlock* block = FindBlockStartingAt(dex_pc); - if (block == nullptr) { - block = new (arena_) HBasicBlock(graph_, dex_pc); - branch_targets_.Put(dex_pc, block); - } - return block; +HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const { + DCHECK_GE(index, 0); + return branch_targets_.Get(index); } template<typename T> @@ -2259,29 +2108,15 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 case Instruction::MOVE_RESULT: case Instruction::MOVE_RESULT_WIDE: - case Instruction::MOVE_RESULT_OBJECT: { + case Instruction::MOVE_RESULT_OBJECT: if (latest_result_ == nullptr) { // Only dead code can lead to this situation, where the verifier // does not reject the method. } else { - // An Invoke/FilledNewArray and its MoveResult could have landed in - // different blocks if there was a try/catch block boundary between - // them. We need to insert the StoreLocal after the result definition - // but before any potential Temporaries. - HStoreLocal* update_local = - new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_); - HBasicBlock* block = latest_result_->GetBlock(); - if (latest_result_->IsInvoke()) { - block->InsertInstructionAfter(update_local, latest_result_); - } else { - DCHECK(latest_result_->IsNewArray()); - DCHECK(latest_result_->GetNext()->IsTemporary()); - block->InsertInstructionAfter(update_local, latest_result_->GetNext()); - } + UpdateLocal(instruction.VRegA(), latest_result_); latest_result_ = nullptr; } break; - } case Instruction::CMP_LONG: { Binop_23x_cmp(instruction, Primitive::kPrimLong, HCompare::kNoBias, dex_pc); diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 58d85e9ef1..052aaf8b42 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -94,12 +94,8 @@ class HGraphBuilder : public ValueObject { bool ComputeBranchTargets(const uint16_t* start, const uint16_t* end, size_t* number_of_branches); - void MaybeUpdateCurrentBlock(size_t dex_pc); - HBasicBlock* FindBlockStartingAt(int32_t dex_pc) const; - HBasicBlock* FindOrCreateBlockStartingAt(int32_t dex_pc); - bool IsBlockInPcRange(HBasicBlock* block, uint32_t dex_pc_start, uint32_t dex_pc_end); - void CreateBlocksForTryCatch(const DexFile::CodeItem& code_item); - void InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item); + void MaybeUpdateCurrentBlock(size_t index); + HBasicBlock* FindBlockStartingAt(int32_t index) const; void InitializeLocals(uint16_t count); HLocal* GetLocalAt(int register_index) const; diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 4607ebe548..cd10935806 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -146,7 +146,7 @@ bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) con HBasicBlock* CodeGenerator::GetNextBlockToEmit() const { for (size_t i = current_block_index_ + 1; i < block_order_->Size(); ++i) { HBasicBlock* block = block_order_->Get(i); - if (!block->IsSingleJump()) { + if (!block->IsSingleGoto()) { return block; } } @@ -154,7 +154,7 @@ HBasicBlock* CodeGenerator::GetNextBlockToEmit() const { } HBasicBlock* CodeGenerator::FirstNonEmptyBlock(HBasicBlock* block) const { - while (block->IsSingleJump()) { + while (block->IsSingleGoto()) { block = block->GetSuccessors().Get(0); } return block; @@ -214,7 +214,7 @@ void CodeGenerator::CompileInternal(CodeAllocator* allocator, bool is_baseline) // Don't generate code for an empty block. Its predecessors will branch to its successor // directly. Also, the label of that block will not be emitted, so this helps catch // errors where we reference that label. - if (block->IsSingleJump()) continue; + if (block->IsSingleGoto()) continue; Bind(block); for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) { HInstruction* current = it.Current(); diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index ff9373ab00..9abe2e7be4 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -431,7 +431,7 @@ void CodeGeneratorARM::Finalize(CodeAllocator* allocator) { // FirstNonEmptyBlock() which could lead to adjusting a label more than once. DCHECK_LT(static_cast<size_t>(block->GetBlockId()), block_labels_.Size()); Label* block_label = &block_labels_.GetRawStorage()[block->GetBlockId()]; - DCHECK_EQ(block_label->IsBound(), !block->IsSingleJump()); + DCHECK_EQ(block_label->IsBound(), !block->IsSingleGoto()); if (block_label->IsBound()) { __ AdjustLabelPosition(block_label); } @@ -962,7 +962,12 @@ void CodeGeneratorARM::InvokeRuntime(int32_t entry_point_offset, || !IsLeafMethod()); } -void InstructionCodeGeneratorARM::HandleGoto(HInstruction* got, HBasicBlock* successor) { +void LocationsBuilderARM::VisitGoto(HGoto* got) { + got->SetLocations(nullptr); +} + +void InstructionCodeGeneratorARM::VisitGoto(HGoto* got) { + HBasicBlock* successor = got->GetSuccessor(); DCHECK(!successor->IsExitBlock()); HBasicBlock* block = got->GetBlock(); @@ -983,25 +988,6 @@ void InstructionCodeGeneratorARM::HandleGoto(HInstruction* got, HBasicBlock* suc } } -void LocationsBuilderARM::VisitGoto(HGoto* got) { - got->SetLocations(nullptr); -} - -void InstructionCodeGeneratorARM::VisitGoto(HGoto* got) { - HandleGoto(got, got->GetSuccessor()); -} - -void LocationsBuilderARM::VisitTryBoundary(HTryBoundary* try_boundary) { - try_boundary->SetLocations(nullptr); -} - -void InstructionCodeGeneratorARM::VisitTryBoundary(HTryBoundary* try_boundary) { - HBasicBlock* successor = try_boundary->GetNormalFlowSuccessor(); - if (!successor->IsExitBlock()) { - HandleGoto(try_boundary, successor); - } -} - void LocationsBuilderARM::VisitExit(HExit* exit) { exit->SetLocations(nullptr); } diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index a96ecbd430..953e733c44 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -211,7 +211,6 @@ class InstructionCodeGeneratorARM : public HGraphVisitor { void DivRemByPowerOfTwo(HBinaryOperation* instruction); void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); void GenerateDivRemConstantIntegral(HBinaryOperation* instruction); - void HandleGoto(HInstruction* got, HBasicBlock* successor); ArmAssembler* const assembler_; CodeGeneratorARM* const codegen_; diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 9b7124d33d..7ec6b54285 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1971,7 +1971,12 @@ void InstructionCodeGeneratorARM64::VisitFloatConstant(HFloatConstant* constant) // Will be generated at use site. } -void InstructionCodeGeneratorARM64::HandleGoto(HInstruction* got, HBasicBlock* successor) { +void LocationsBuilderARM64::VisitGoto(HGoto* got) { + got->SetLocations(nullptr); +} + +void InstructionCodeGeneratorARM64::VisitGoto(HGoto* got) { + HBasicBlock* successor = got->GetSuccessor(); DCHECK(!successor->IsExitBlock()); HBasicBlock* block = got->GetBlock(); HInstruction* previous = got->GetPrevious(); @@ -1990,25 +1995,6 @@ void InstructionCodeGeneratorARM64::HandleGoto(HInstruction* got, HBasicBlock* s } } -void LocationsBuilderARM64::VisitGoto(HGoto* got) { - got->SetLocations(nullptr); -} - -void InstructionCodeGeneratorARM64::VisitGoto(HGoto* got) { - HandleGoto(got, got->GetSuccessor()); -} - -void LocationsBuilderARM64::VisitTryBoundary(HTryBoundary* try_boundary) { - try_boundary->SetLocations(nullptr); -} - -void InstructionCodeGeneratorARM64::VisitTryBoundary(HTryBoundary* try_boundary) { - HBasicBlock* successor = try_boundary->GetNormalFlowSuccessor(); - if (!successor->IsExitBlock()) { - HandleGoto(try_boundary, successor); - } -} - void InstructionCodeGeneratorARM64::GenerateTestAndBranch(HInstruction* instruction, vixl::Label* true_target, vixl::Label* false_target, diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 2c610380ed..bbe3adc76b 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -181,7 +181,7 @@ class InstructionCodeGeneratorARM64 : public HGraphVisitor { void DivRemByPowerOfTwo(HBinaryOperation* instruction); void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); void GenerateDivRemIntegral(HBinaryOperation* instruction); - void HandleGoto(HInstruction* got, HBasicBlock* successor); + Arm64Assembler* const assembler_; CodeGeneratorARM64* const codegen_; diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index aa4fd26590..ab684d41d4 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -1938,7 +1938,12 @@ void InstructionCodeGeneratorMIPS64::VisitFloatConstant(HFloatConstant* constant // Will be generated at use site. } -void InstructionCodeGeneratorMIPS64::HandleGoto(HInstruction* got, HBasicBlock* successor) { +void LocationsBuilderMIPS64::VisitGoto(HGoto* got) { + got->SetLocations(nullptr); +} + +void InstructionCodeGeneratorMIPS64::VisitGoto(HGoto* got) { + HBasicBlock* successor = got->GetSuccessor(); DCHECK(!successor->IsExitBlock()); HBasicBlock* block = got->GetBlock(); HInstruction* previous = got->GetPrevious(); @@ -1957,25 +1962,6 @@ void InstructionCodeGeneratorMIPS64::HandleGoto(HInstruction* got, HBasicBlock* } } -void LocationsBuilderMIPS64::VisitGoto(HGoto* got) { - got->SetLocations(nullptr); -} - -void InstructionCodeGeneratorMIPS64::VisitGoto(HGoto* got) { - HandleGoto(got, got->GetSuccessor()); -} - -void LocationsBuilderMIPS64::VisitTryBoundary(HTryBoundary* try_boundary) { - try_boundary->SetLocations(nullptr); -} - -void InstructionCodeGeneratorMIPS64::VisitTryBoundary(HTryBoundary* try_boundary) { - HBasicBlock* successor = try_boundary->GetNormalFlowSuccessor(); - if (!successor->IsExitBlock()) { - HandleGoto(try_boundary, successor); - } -} - void InstructionCodeGeneratorMIPS64::GenerateTestAndBranch(HInstruction* instruction, Label* true_target, Label* false_target, diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h index c724a217d8..ec36496a4f 100644 --- a/compiler/optimizing/code_generator_mips64.h +++ b/compiler/optimizing/code_generator_mips64.h @@ -196,7 +196,6 @@ class InstructionCodeGeneratorMIPS64 : public HGraphVisitor { Label* true_target, Label* false_target, Label* always_true_target); - void HandleGoto(HInstruction* got, HBasicBlock* successor); Mips64Assembler* const assembler_; CodeGeneratorMIPS64* const codegen_; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 6c82fe99c7..4d106c4fa4 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -842,7 +842,12 @@ void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstr } } -void InstructionCodeGeneratorX86::HandleGoto(HInstruction* got, HBasicBlock* successor) { +void LocationsBuilderX86::VisitGoto(HGoto* got) { + got->SetLocations(nullptr); +} + +void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) { + HBasicBlock* successor = got->GetSuccessor(); DCHECK(!successor->IsExitBlock()); HBasicBlock* block = got->GetBlock(); @@ -862,25 +867,6 @@ void InstructionCodeGeneratorX86::HandleGoto(HInstruction* got, HBasicBlock* suc } } -void LocationsBuilderX86::VisitGoto(HGoto* got) { - got->SetLocations(nullptr); -} - -void InstructionCodeGeneratorX86::VisitGoto(HGoto* got) { - HandleGoto(got, got->GetSuccessor()); -} - -void LocationsBuilderX86::VisitTryBoundary(HTryBoundary* try_boundary) { - try_boundary->SetLocations(nullptr); -} - -void InstructionCodeGeneratorX86::VisitTryBoundary(HTryBoundary* try_boundary) { - HBasicBlock* successor = try_boundary->GetNormalFlowSuccessor(); - if (!successor->IsExitBlock()) { - HandleGoto(try_boundary, successor); - } -} - void LocationsBuilderX86::VisitExit(HExit* exit) { exit->SetLocations(nullptr); } diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index 623e83222d..1ad89c9bfc 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -201,7 +201,6 @@ class InstructionCodeGeneratorX86 : public HGraphVisitor { Label* true_target, Label* false_target, Label* always_true_target); - void HandleGoto(HInstruction* got, HBasicBlock* successor); X86Assembler* const assembler_; CodeGeneratorX86* const codegen_; diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 22f5d96635..a8f57cc9ac 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -786,7 +786,12 @@ void CodeGeneratorX86_64::Move(HInstruction* instruction, } } -void InstructionCodeGeneratorX86_64::HandleGoto(HInstruction* got, HBasicBlock* successor) { +void LocationsBuilderX86_64::VisitGoto(HGoto* got) { + got->SetLocations(nullptr); +} + +void InstructionCodeGeneratorX86_64::VisitGoto(HGoto* got) { + HBasicBlock* successor = got->GetSuccessor(); DCHECK(!successor->IsExitBlock()); HBasicBlock* block = got->GetBlock(); @@ -806,25 +811,6 @@ void InstructionCodeGeneratorX86_64::HandleGoto(HInstruction* got, HBasicBlock* } } -void LocationsBuilderX86_64::VisitGoto(HGoto* got) { - got->SetLocations(nullptr); -} - -void InstructionCodeGeneratorX86_64::VisitGoto(HGoto* got) { - HandleGoto(got, got->GetSuccessor()); -} - -void LocationsBuilderX86_64::VisitTryBoundary(HTryBoundary* try_boundary) { - try_boundary->SetLocations(nullptr); -} - -void InstructionCodeGeneratorX86_64::VisitTryBoundary(HTryBoundary* try_boundary) { - HBasicBlock* successor = try_boundary->GetNormalFlowSuccessor(); - if (!successor->IsExitBlock()) { - HandleGoto(try_boundary, successor); - } -} - void LocationsBuilderX86_64::VisitExit(HExit* exit) { exit->SetLocations(nullptr); } diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index c2aa56b63f..a18e89a3e7 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -202,7 +202,6 @@ class InstructionCodeGeneratorX86_64 : public HGraphVisitor { Label* true_target, Label* false_target, Label* always_true_target); - void HandleGoto(HInstruction* got, HBasicBlock* successor); X86_64Assembler* const assembler_; CodeGeneratorX86_64* const codegen_; diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index d7e6bd8161..fd28f0b83f 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -81,10 +81,7 @@ void GraphChecker::VisitBasicBlock(HBasicBlock* block) { } // Ensure `block` ends with a branch instruction. - // This invariant is not enforced on non-SSA graphs. Graph built from DEX with - // dead code that falls out of the method will not end with a control-flow - // instruction. Such code is removed during the SSA-building DCE phase. - if (GetGraph()->IsInSsaForm() && !block->EndsWithControlFlowInstruction()) { + if (!block->EndsWithControlFlowInstruction()) { AddError(StringPrintf("Block %d does not end with a branch instruction.", block->GetBlockId())); } @@ -256,22 +253,6 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) { } } -void GraphChecker::VisitReturn(HReturn* ret) { - if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) { - AddError(StringPrintf("%s:%d does not jump to the exit block.", - ret->DebugName(), - ret->GetId())); - } -} - -void GraphChecker::VisitReturnVoid(HReturnVoid* ret) { - if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) { - AddError(StringPrintf("%s:%d does not jump to the exit block.", - ret->DebugName(), - ret->GetId())); - } -} - void SSAChecker::VisitBasicBlock(HBasicBlock* block) { super_type::VisitBasicBlock(block); diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h index bafa69d422..b4314da03b 100644 --- a/compiler/optimizing/graph_checker.h +++ b/compiler/optimizing/graph_checker.h @@ -48,10 +48,6 @@ class GraphChecker : public HGraphDelegateVisitor { // Check that the HasBoundsChecks() flag is set for bounds checks. void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE; - // Check that the Return and ReturnVoid jump to the exit block. - void VisitReturn(HReturn* ret) OVERRIDE; - void VisitReturnVoid(HReturnVoid* ret) OVERRIDE; - // Was the last visit of the graph valid? bool IsValid() const { return errors_.empty(); diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 30d61ef040..7d723ef13d 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -252,22 +252,8 @@ class HGraphVisualizerPrinter : public HGraphVisitor { AddIndent(); output_ << "successors"; for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) { - if (!block->IsExceptionalSuccessor(i)) { - HBasicBlock* successor = block->GetSuccessors().Get(i); - output_ << " \"B" << successor->GetBlockId() << "\" "; - } - } - output_<< std::endl; - } - - void PrintExceptionHandlers(HBasicBlock* block) { - AddIndent(); - output_ << "xhandlers"; - for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) { - if (block->IsExceptionalSuccessor(i)) { - HBasicBlock* handler = block->GetSuccessors().Get(i); - output_ << " \"B" << handler->GetBlockId() << "\" "; - } + HBasicBlock* successor = block->GetSuccessors().Get(i); + output_ << " \"B" << successor->GetBlockId() << "\" "; } if (block->IsExitBlock() && (disasm_info_ != nullptr) && @@ -379,15 +365,6 @@ class HGraphVisualizerPrinter : public HGraphVisitor { << std::noboolalpha; } - void VisitTryBoundary(HTryBoundary* try_boundary) OVERRIDE { - StartAttributeStream("is_entry") << std::boolalpha - << try_boundary->IsTryEntry() - << std::noboolalpha; - StartAttributeStream("is_exit") << std::boolalpha - << try_boundary->IsTryExit() - << std::noboolalpha; - } - bool IsPass(const char* name) { return strcmp(pass_name_, name) == 0; } @@ -602,14 +579,8 @@ class HGraphVisualizerPrinter : public HGraphVisitor { } PrintPredecessors(block); PrintSuccessors(block); - PrintExceptionHandlers(block); - - if (block->IsCatchBlock()) { - PrintProperty("flags", "catch_block"); - } else { - PrintEmptyProperty("flags"); - } - + PrintEmptyProperty("xhandlers"); + PrintEmptyProperty("flags"); if (block->GetDominator() != nullptr) { PrintProperty("dominator", "B", block->GetDominator()->GetBlockId()); } diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 881f9ec117..a6390af1f2 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -189,20 +189,15 @@ void HGraph::TransformToSsa() { ssa_builder.BuildSsa(); } -HBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) { +void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) { + // Insert a new node between `block` and `successor` to split the + // critical edge. HBasicBlock* new_block = new (arena_) HBasicBlock(this, successor->GetDexPc()); AddBlock(new_block); + new_block->AddInstruction(new (arena_) HGoto()); // Use `InsertBetween` to ensure the predecessor index and successor index of // `block` and `successor` are preserved. new_block->InsertBetween(block, successor); - return new_block; -} - -void HGraph::SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor) { - // Insert a new node between `block` and `successor` to split the - // critical edge. - HBasicBlock* new_block = SplitEdge(block, successor); - new_block->AddInstruction(new (arena_) HGoto()); if (successor->IsLoopHeader()) { // If we split at a back edge boundary, make the new block the back edge. HLoopInformation* info = successor->GetLoopInformation(); @@ -1024,35 +1019,6 @@ void HInstruction::MoveBefore(HInstruction* cursor) { } } -HBasicBlock* HBasicBlock::SplitBefore(HInstruction* cursor) { - DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented"; - DCHECK_EQ(cursor->GetBlock(), this); - - HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc()); - new_block->instructions_.first_instruction_ = cursor; - new_block->instructions_.last_instruction_ = instructions_.last_instruction_; - instructions_.last_instruction_ = cursor->previous_; - if (cursor->previous_ == nullptr) { - instructions_.first_instruction_ = nullptr; - } else { - cursor->previous_->next_ = nullptr; - cursor->previous_ = nullptr; - } - - new_block->instructions_.SetBlockOfInstructions(new_block); - AddInstruction(new (GetGraph()->GetArena()) HGoto()); - - for (size_t i = 0, e = GetSuccessors().Size(); i < e; ++i) { - HBasicBlock* successor = GetSuccessors().Get(i); - new_block->successors_.Add(successor); - successor->predecessors_.Put(successor->GetPredecessorIndexOf(this), new_block); - } - successors_.Reset(); - AddSuccessor(new_block); - - return new_block; -} - HBasicBlock* HBasicBlock::SplitAfter(HInstruction* cursor) { DCHECK(!cursor->IsControlFlow()); DCHECK_NE(instructions_.last_instruction_, cursor); @@ -1082,24 +1048,14 @@ HBasicBlock* HBasicBlock::SplitAfter(HInstruction* cursor) { return new_block; } -bool HBasicBlock::IsExceptionalSuccessor(size_t idx) const { - return !GetInstructions().IsEmpty() - && GetLastInstruction()->IsTryBoundary() - && GetLastInstruction()->AsTryBoundary()->IsExceptionalSuccessor(idx); -} - -static bool HasOnlyOneInstruction(const HBasicBlock& block) { - return block.GetPhis().IsEmpty() - && !block.GetInstructions().IsEmpty() - && block.GetFirstInstruction() == block.GetLastInstruction(); -} - bool HBasicBlock::IsSingleGoto() const { - return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsGoto(); -} - -bool HBasicBlock::IsSingleTryBoundary() const { - return HasOnlyOneInstruction(*this) && GetLastInstruction()->IsTryBoundary(); + HLoopInformation* loop_info = GetLoopInformation(); + DCHECK(EndsWithControlFlowInstruction()); + return GetPhis().IsEmpty() + && GetFirstInstruction() == GetLastInstruction() + && GetLastInstruction()->IsGoto() + // Back edges generate the suspend check. + && (loop_info == nullptr || !loop_info->IsBackEdge(*this)); } bool HBasicBlock::EndsWithControlFlowInstruction() const { diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index f2e9e22057..0f5b1abbbf 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -39,7 +39,6 @@ class HCurrentMethod; class HDoubleConstant; class HEnvironment; class HFloatConstant; -class HGraphBuilder; class HGraphVisitor; class HInstruction; class HIntConstant; @@ -208,12 +207,6 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { // Removes `block` from the graph. void DeleteDeadBlock(HBasicBlock* block); - // Splits the edge between `block` and `successor` while preserving the - // indices in the predecessor/successor lists. If there are multiple edges - // between the blocks, the lowest indices are used. - // Returns the new block which is empty and has the same dex pc as `successor`. - HBasicBlock* SplitEdge(HBasicBlock* block, HBasicBlock* successor); - void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor); void SimplifyLoop(HBasicBlock* header); @@ -573,15 +566,6 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { } bool IsSingleGoto() const; - bool IsSingleTryBoundary() const; - - // Returns true if this block emits nothing but a jump. - bool IsSingleJump() const { - HLoopInformation* loop_info = GetLoopInformation(); - return (IsSingleGoto() || IsSingleTryBoundary()) - // Back edges generate a suspend check. - && (loop_info == nullptr || !loop_info->IsBackEdge(*this)); - } void AddBackEdge(HBasicBlock* back_edge) { if (loop_information_ == nullptr) { @@ -690,7 +674,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { successors_.Put(1, temp); } - size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const { + size_t GetPredecessorIndexOf(HBasicBlock* predecessor) { for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) { if (predecessors_.Get(i) == predecessor) { return i; @@ -699,7 +683,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { return -1; } - size_t GetSuccessorIndexOf(HBasicBlock* successor) const { + size_t GetSuccessorIndexOf(HBasicBlock* successor) { for (size_t i = 0, e = successors_.Size(); i < e; ++i) { if (successors_.Get(i) == successor) { return i; @@ -708,32 +692,6 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { return -1; } - HBasicBlock* GetSinglePredecessor() const { - DCHECK_EQ(GetPredecessors().Size(), 1u); - return GetPredecessors().Get(0); - } - - HBasicBlock* GetSingleSuccessor() const { - DCHECK_EQ(GetSuccessors().Size(), 1u); - return GetSuccessors().Get(0); - } - - // Returns whether the first occurrence of `predecessor` in the list of - // predecessors is at index `idx`. - bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const { - DCHECK_EQ(GetPredecessors().Get(idx), predecessor); - return GetPredecessorIndexOf(predecessor) == idx; - } - - // Returns whether successor at index `idx` is an exception handler. - bool IsExceptionalSuccessor(size_t idx) const; - - // Split the block into two blocks just before `cursor`. Returns the newly - // created, latter block. Note that this method will create a Goto at the end - // of the former block and will create an edge between them. It will not, - // however, update the graph, reverse post order or loop information. - HBasicBlock* SplitBefore(HInstruction* cursor); - // Split the block into two blocks just after `cursor`. Returns the newly // created block. Note that this method just updates raw block information, // like predecessors, successors, dominators, and instruction list. It does not @@ -955,7 +913,6 @@ class HLoopInformationOutwardIterator : public ValueObject { M(SuspendCheck, Instruction) \ M(Temporary, Instruction) \ M(Throw, Instruction) \ - M(TryBoundary, Instruction) \ M(TypeConversion, Instruction) \ M(UShr, BinaryOperation) \ M(Xor, BinaryOperation) \ @@ -1901,7 +1858,7 @@ class HGoto : public HTemplateInstruction<0> { bool IsControlFlow() const OVERRIDE { return true; } HBasicBlock* GetSuccessor() const { - return GetBlock()->GetSingleSuccessor(); + return GetBlock()->GetSuccessors().Get(0); } DECLARE_INSTRUCTION(Goto); @@ -1935,65 +1892,6 @@ class HIf : public HTemplateInstruction<1> { DISALLOW_COPY_AND_ASSIGN(HIf); }; - -// Abstract instruction which marks the beginning and/or end of a try block and -// links it to the respective exception handlers. Behaves the same as a Goto in -// non-exceptional control flow. -// Normal-flow successor is stored at index zero, exception handlers under -// higher indices in no particular order. -class HTryBoundary : public HTemplateInstruction<0> { - public: - HTryBoundary(bool is_entry, bool is_exit) - : HTemplateInstruction(SideEffects::None()), is_entry_(is_entry), is_exit_(is_exit) {} - - bool IsControlFlow() const OVERRIDE { return true; } - - // Returns the block's non-exceptional successor (index zero). - HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors().Get(0); } - - // Returns whether `handler` is among its exception handlers (non-zero index - // successors). - bool HasExceptionHandler(HBasicBlock* handler) const { - DCHECK(handler->IsCatchBlock()); - return GetBlock()->GetSuccessors().Contains(handler, /* start_from */ 1); - } - - // Returns whether successor at index `idx` is an exception handler. - bool IsExceptionalSuccessor(size_t idx) const { - DCHECK_LT(idx, GetBlock()->GetSuccessors().Size()); - bool is_handler = (idx != 0); - DCHECK(!is_handler || GetBlock()->GetSuccessors().Get(idx)->IsCatchBlock()); - return is_handler; - } - - // If not present already, adds `handler` to its block's list of exception - // handlers. - void AddExceptionHandler(HBasicBlock* handler) { - if (!HasExceptionHandler(handler)) { - GetBlock()->AddSuccessor(handler); - } - } - - bool IsTryEntry() const { return is_entry_; } - bool IsTryExit() const { return is_exit_; } - - DECLARE_INSTRUCTION(TryBoundary); - - private: - // Only for debugging purposes. - bool is_entry_; - bool is_exit_; - - // Only set by HGraphBuilder. - void SetIsTryEntry() { is_entry_ = true; } - void SetIsTryExit() { is_exit_ = true; } - - friend HGraphBuilder; - - DISALLOW_COPY_AND_ASSIGN(HTryBoundary); -}; - - // Deoptimize to interpreter, upon checking a condition. class HDeoptimize : public HTemplateInstruction<1> { public: |