diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-02-18 09:54:39 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-02-18 09:54:40 +0000 |
commit | 35757740da77220dc51d5cff3bc3a779f2eea9ef (patch) | |
tree | 51ef8c6fda805fb3df6fee1d9ec040482660a253 /compiler | |
parent | de7402182c1b020dec43aa38d62fa369a4ef52b8 (diff) | |
parent | dc23d8318db08cb42e20f1d16dbc416798951a8b (diff) | |
download | art-35757740da77220dc51d5cff3bc3a779f2eea9ef.zip art-35757740da77220dc51d5cff3bc3a779f2eea9ef.tar.gz art-35757740da77220dc51d5cff3bc3a779f2eea9ef.tar.bz2 |
Merge "Avoid generating jmp +0."
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/code_generator.cc | 42 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 10 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.h | 2 |
6 files changed, 50 insertions, 10 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index d0739a6..bf3ed14 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -40,6 +40,16 @@ size_t CodeGenerator::GetCacheOffset(uint32_t index) { return mirror::ObjectArray<mirror::Object>::OffsetOfElement(index).SizeValue(); } +static bool IsSingleGoto(HBasicBlock* block) { + HLoopInformation* loop_info = block->GetLoopInformation(); + // TODO: Remove the null check b/19084197. + return (block->GetFirstInstruction() != nullptr) + && (block->GetFirstInstruction() == block->GetLastInstruction()) + && block->GetLastInstruction()->IsGoto() + // Back edges generate the suspend check. + && (loop_info == nullptr || !loop_info->IsBackEdge(block)); +} + void CodeGenerator::CompileBaseline(CodeAllocator* allocator, bool is_leaf) { Initialize(); if (!is_leaf) { @@ -56,12 +66,38 @@ void CodeGenerator::CompileBaseline(CodeAllocator* allocator, bool is_leaf) { CompileInternal(allocator, /* is_baseline */ true); } +bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const { + DCHECK_EQ(block_order_->Get(current_block_index_), current); + return GetNextBlockToEmit() == FirstNonEmptyBlock(next); +} + +HBasicBlock* CodeGenerator::GetNextBlockToEmit() const { + for (size_t i = current_block_index_ + 1; i < block_order_->Size(); ++i) { + HBasicBlock* block = block_order_->Get(i); + if (!IsSingleGoto(block)) { + return block; + } + } + return nullptr; +} + +HBasicBlock* CodeGenerator::FirstNonEmptyBlock(HBasicBlock* block) const { + while (IsSingleGoto(block)) { + block = block->GetSuccessors().Get(0); + } + return block; +} + void CodeGenerator::CompileInternal(CodeAllocator* allocator, bool is_baseline) { HGraphVisitor* instruction_visitor = GetInstructionVisitor(); DCHECK_EQ(current_block_index_, 0u); GenerateFrameEntry(); for (size_t e = block_order_->Size(); current_block_index_ < e; ++current_block_index_) { HBasicBlock* block = block_order_->Get(current_block_index_); + // 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 (IsSingleGoto(block)) continue; Bind(block); for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) { HInstruction* current = it.Current(); @@ -338,12 +374,6 @@ void CodeGenerator::AllocateLocations(HInstruction* instruction) { } } -bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const { - DCHECK_EQ(block_order_->Get(current_block_index_), current); - return (current_block_index_ < block_order_->Size() - 1) - && (block_order_->Get(current_block_index_ + 1) == next); -} - CodeGenerator* CodeGenerator::Create(HGraph* graph, InstructionSet instruction_set, const InstructionSetFeatures& isa_features, diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index efd0c84..6c78f10 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -91,6 +91,8 @@ class CodeGenerator { HGraph* GetGraph() const { return graph_; } + HBasicBlock* GetNextBlockToEmit() const; + HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const; bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const; size_t GetStackSlotOfParameter(HParameterValue* parameter) const { @@ -314,6 +316,14 @@ class CodeGenerator { return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0); } + // Arm64 has its own type for a label, so we need to templatize this method + // to share the logic. + template <typename T> + T* CommonGetLabelOf(T* raw_pointer_to_labels_array, HBasicBlock* block) const { + block = FirstNonEmptyBlock(block); + return raw_pointer_to_labels_array + block->GetBlockId(); + } + // Frame size required for this method. uint32_t frame_size_; uint32_t core_spill_mask_; diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index 47d81ff..f1a3729 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -252,7 +252,7 @@ class CodeGeneratorARM : public CodeGenerator { void MarkGCCard(Register temp, Register card, Register object, Register value); Label* GetLabelOf(HBasicBlock* block) const { - return block_labels_.GetRawStorage() + block->GetBlockId(); + return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block); } void Initialize() OVERRIDE { diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 2e937e2..afb7fc3 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -214,7 +214,7 @@ class CodeGeneratorARM64 : public CodeGenerator { void Bind(HBasicBlock* block) OVERRIDE; vixl::Label* GetLabelOf(HBasicBlock* block) const { - return block_labels_ + block->GetBlockId(); + return CommonGetLabelOf<vixl::Label>(block_labels_, block); } void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index 107ddaf..f5a9b7d 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -234,7 +234,7 @@ class CodeGeneratorX86 : public CodeGenerator { void LoadCurrentMethod(Register reg); Label* GetLabelOf(HBasicBlock* block) const { - return block_labels_.GetRawStorage() + block->GetBlockId(); + return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block); } void Initialize() OVERRIDE { diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index dbdbf86..707c999 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -232,7 +232,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { void LoadCurrentMethod(CpuRegister reg); Label* GetLabelOf(HBasicBlock* block) const { - return block_labels_.GetRawStorage() + block->GetBlockId(); + return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block); } void Initialize() OVERRIDE { |