diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/instruction_builder.cc | 6 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 13 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm.cc | 27 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 31 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 24 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 62 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 2 |
7 files changed, 99 insertions, 66 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index b0f0893720..06b39680b2 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -567,10 +567,10 @@ void HInstructionBuilder::Binop_22b(const Instruction& instruction, bool reverse UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); } -static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) { +static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, CompilerDriver* driver) { Thread* self = Thread::Current(); return cu->IsConstructor() - && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex()); + && driver->RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex()); } // Returns true if `block` has only one successor which starts at the next @@ -616,7 +616,7 @@ void HInstructionBuilder::BuildReturn(const Instruction& instruction, if (graph_->ShouldGenerateConstructorBarrier()) { // The compilation unit is null during testing. if (dex_compilation_unit_ != nullptr) { - DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_)) + DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, compiler_driver_)) << "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier."; } AppendInstruction(new (arena_) HMemoryBarrier(kStoreStore, dex_pc)); diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 3da82851a6..863dd1c6f6 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -124,11 +124,12 @@ public: \ void Set##name() { SetBit(k##name); } \ bool Get##name() const { return IsBitSet(k##name); } \ private: \ -static constexpr int k##name = bit +static constexpr size_t k##name = bit class IntrinsicOptimizations : public ValueObject { public: - explicit IntrinsicOptimizations(HInvoke* invoke) : value_(invoke->GetIntrinsicOptimizations()) {} + explicit IntrinsicOptimizations(HInvoke* invoke) + : value_(invoke->GetIntrinsicOptimizations()) {} explicit IntrinsicOptimizations(const HInvoke& invoke) : value_(invoke.GetIntrinsicOptimizations()) {} @@ -138,15 +139,17 @@ class IntrinsicOptimizations : public ValueObject { protected: bool IsBitSet(uint32_t bit) const { + DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); return (*value_ & (1 << bit)) != 0u; } void SetBit(uint32_t bit) { - *(const_cast<uint32_t*>(value_)) |= (1 << bit); + DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); + *(const_cast<uint32_t* const>(value_)) |= (1 << bit); } private: - const uint32_t *value_; + const uint32_t* const value_; DISALLOW_COPY_AND_ASSIGN(IntrinsicOptimizations); }; @@ -158,7 +161,7 @@ public: \ void Set##name() { SetBit(k##name); } \ bool Get##name() const { return IsBitSet(k##name); } \ private: \ -static constexpr int k##name = bit + kNumberOfGenericOptimizations +static constexpr size_t k##name = bit + kNumberOfGenericOptimizations class StringEqualsOptimizations : public IntrinsicOptimizations { public: diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 4b94c94f39..86b7bc138c 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -1394,15 +1394,13 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathARM(invoke); codegen_->AddSlowPath(slow_path); - Label ok; + Label conditions_on_positions_validated; SystemArrayCopyOptimizations optimizations(invoke); - if (!optimizations.GetDestinationIsSource()) { - if (!src_pos.IsConstant() || !dest_pos.IsConstant()) { - __ cmp(src, ShifterOperand(dest)); - } + if (!optimizations.GetDestinationIsSource() && + (!src_pos.IsConstant() || !dest_pos.IsConstant())) { + __ cmp(src, ShifterOperand(dest)); } - // If source and destination are the same, we go to slow path if we need to do // forward copying. if (src_pos.IsConstant()) { @@ -1413,14 +1411,14 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { || (src_pos_constant >= dest_pos.GetConstant()->AsIntConstant()->GetValue())); } else { if (!optimizations.GetDestinationIsSource()) { - __ b(&ok, NE); + __ b(&conditions_on_positions_validated, NE); } __ cmp(dest_pos.AsRegister<Register>(), ShifterOperand(src_pos_constant)); __ b(slow_path->GetEntryLabel(), GT); } } else { if (!optimizations.GetDestinationIsSource()) { - __ b(&ok, NE); + __ b(&conditions_on_positions_validated, NE); } if (dest_pos.IsConstant()) { int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue(); @@ -1431,7 +1429,7 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { __ b(slow_path->GetEntryLabel(), LT); } - __ Bind(&ok); + __ Bind(&conditions_on_positions_validated); if (!optimizations.GetSourceIsNotNull()) { // Bail out if the source is null. @@ -1482,7 +1480,7 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { bool did_unpoison = false; if (!optimizations.GetDestinationIsNonPrimitiveArray() || !optimizations.GetSourceIsNonPrimitiveArray()) { - // One or two of the references need to be unpoisoned. Unpoisoned them + // One or two of the references need to be unpoisoned. Unpoison them // both to make the identity check valid. __ MaybeUnpoisonHeapReference(temp1); __ MaybeUnpoisonHeapReference(temp2); @@ -1491,6 +1489,7 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { if (!optimizations.GetDestinationIsNonPrimitiveArray()) { // Bail out if the destination is not a non primitive array. + // /* HeapReference<Class> */ temp3 = temp1->component_type_ __ LoadFromOffset(kLoadWord, temp3, temp1, component_offset); __ CompareAndBranchIfZero(temp3, slow_path->GetEntryLabel()); __ MaybeUnpoisonHeapReference(temp3); @@ -1501,7 +1500,7 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { if (!optimizations.GetSourceIsNonPrimitiveArray()) { // Bail out if the source is not a non primitive array. - // Bail out if the destination is not a non primitive array. + // /* HeapReference<Class> */ temp3 = temp2->component_type_ __ LoadFromOffset(kLoadWord, temp3, temp2, component_offset); __ CompareAndBranchIfZero(temp3, slow_path->GetEntryLabel()); __ MaybeUnpoisonHeapReference(temp3); @@ -1518,8 +1517,10 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { if (!did_unpoison) { __ MaybeUnpoisonHeapReference(temp1); } + // /* HeapReference<Class> */ temp1 = temp1->component_type_ __ LoadFromOffset(kLoadWord, temp1, temp1, component_offset); __ MaybeUnpoisonHeapReference(temp1); + // /* HeapReference<Class> */ temp1 = temp1->super_class_ __ LoadFromOffset(kLoadWord, temp1, temp1, super_offset); // No need to unpoison the result, we're comparing against null. __ CompareAndBranchIfNonZero(temp1, slow_path->GetEntryLabel()); @@ -1530,8 +1531,10 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { } else if (!optimizations.GetSourceIsNonPrimitiveArray()) { DCHECK(optimizations.GetDestinationIsNonPrimitiveArray()); // Bail out if the source is not a non primitive array. + // /* HeapReference<Class> */ temp1 = src->klass_ __ LoadFromOffset(kLoadWord, temp1, src, class_offset); __ MaybeUnpoisonHeapReference(temp1); + // /* HeapReference<Class> */ temp3 = temp1->component_type_ __ LoadFromOffset(kLoadWord, temp3, temp1, component_offset); __ CompareAndBranchIfZero(temp3, slow_path->GetEntryLabel()); __ MaybeUnpoisonHeapReference(temp3); @@ -1585,7 +1588,7 @@ void IntrinsicCodeGeneratorARM::VisitSystemArrayCopy(HInvoke* invoke) { temp2, dest, Register(kNoRegister), - /* can_be_null */ false); + /* value_can_be_null */ false); __ Bind(slow_path->GetExitLabel()); } diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 927e2ecfbb..04ae3a6732 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1819,39 +1819,32 @@ static void GenSystemArrayCopyAddresses(vixl::MacroAssembler* masm, const Register& dst_base, const Register& src_end) { DCHECK(type == Primitive::kPrimNot || type == Primitive::kPrimChar) - << "Unexpected element type: " - << type; - const int32_t char_size = Primitive::ComponentSize(type); - const int32_t char_size_shift = Primitive::ComponentSizeShift(type); + << "Unexpected element type: " << type; + const int32_t element_size = Primitive::ComponentSize(type); + const int32_t element_size_shift = Primitive::ComponentSizeShift(type); - uint32_t offset = mirror::Array::DataOffset(char_size).Uint32Value(); + uint32_t data_offset = mirror::Array::DataOffset(element_size).Uint32Value(); if (src_pos.IsConstant()) { int32_t constant = src_pos.GetConstant()->AsIntConstant()->GetValue(); - __ Add(src_base, src, char_size * constant + offset); + __ Add(src_base, src, element_size * constant + data_offset); } else { - __ Add(src_base, src, offset); - __ Add(src_base, - src_base, - Operand(XRegisterFrom(src_pos), LSL, char_size_shift)); + __ Add(src_base, src, data_offset); + __ Add(src_base, src_base, Operand(XRegisterFrom(src_pos), LSL, element_size_shift)); } if (dst_pos.IsConstant()) { int32_t constant = dst_pos.GetConstant()->AsIntConstant()->GetValue(); - __ Add(dst_base, dst, char_size * constant + offset); + __ Add(dst_base, dst, element_size * constant + data_offset); } else { - __ Add(dst_base, dst, offset); - __ Add(dst_base, - dst_base, - Operand(XRegisterFrom(dst_pos), LSL, char_size_shift)); + __ Add(dst_base, dst, data_offset); + __ Add(dst_base, dst_base, Operand(XRegisterFrom(dst_pos), LSL, element_size_shift)); } if (copy_length.IsConstant()) { int32_t constant = copy_length.GetConstant()->AsIntConstant()->GetValue(); - __ Add(src_end, src_base, char_size * constant); + __ Add(src_end, src_base, element_size * constant); } else { - __ Add(src_end, - src_base, - Operand(XRegisterFrom(copy_length), LSL, char_size_shift)); + __ Add(src_end, src_base, Operand(XRegisterFrom(copy_length), LSL, element_size_shift)); } } diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 9ca4ef049a..1d32dc7bc5 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -1150,15 +1150,13 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86_64(invoke); codegen_->AddSlowPath(slow_path); - NearLabel ok; + NearLabel conditions_on_positions_validated; SystemArrayCopyOptimizations optimizations(invoke); - if (!optimizations.GetDestinationIsSource()) { - if (!src_pos.IsConstant() || !dest_pos.IsConstant()) { - __ cmpl(src, dest); - } + if (!optimizations.GetDestinationIsSource() && + (!src_pos.IsConstant() || !dest_pos.IsConstant())) { + __ cmpl(src, dest); } - // If source and destination are the same, we go to slow path if we need to do // forward copying. if (src_pos.IsConstant()) { @@ -1169,14 +1167,14 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { || (src_pos_constant >= dest_pos.GetConstant()->AsIntConstant()->GetValue())); } else { if (!optimizations.GetDestinationIsSource()) { - __ j(kNotEqual, &ok); + __ j(kNotEqual, &conditions_on_positions_validated); } __ cmpl(dest_pos.AsRegister<CpuRegister>(), Immediate(src_pos_constant)); __ j(kGreater, slow_path->GetEntryLabel()); } } else { if (!optimizations.GetDestinationIsSource()) { - __ j(kNotEqual, &ok); + __ j(kNotEqual, &conditions_on_positions_validated); } if (dest_pos.IsConstant()) { int32_t dest_pos_constant = dest_pos.GetConstant()->AsIntConstant()->GetValue(); @@ -1188,7 +1186,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { } } - __ Bind(&ok); + __ Bind(&conditions_on_positions_validated); if (!optimizations.GetSourceIsNotNull()) { // Bail out if the source is null. @@ -1241,7 +1239,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { bool did_unpoison = false; if (!optimizations.GetDestinationIsNonPrimitiveArray() || !optimizations.GetSourceIsNonPrimitiveArray()) { - // One or two of the references need to be unpoisoned. Unpoisoned them + // One or two of the references need to be unpoisoned. Unpoison them // both to make the identity check valid. __ MaybeUnpoisonHeapReference(temp1); __ MaybeUnpoisonHeapReference(temp2); @@ -1250,6 +1248,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { if (!optimizations.GetDestinationIsNonPrimitiveArray()) { // Bail out if the destination is not a non primitive array. + // /* HeapReference<Class> */ TMP = temp1->component_type_ __ movl(CpuRegister(TMP), Address(temp1, component_offset)); __ testl(CpuRegister(TMP), CpuRegister(TMP)); __ j(kEqual, slow_path->GetEntryLabel()); @@ -1260,6 +1259,7 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { if (!optimizations.GetSourceIsNonPrimitiveArray()) { // Bail out if the source is not a non primitive array. + // /* HeapReference<Class> */ TMP = temp2->component_type_ __ movl(CpuRegister(TMP), Address(temp2, component_offset)); __ testl(CpuRegister(TMP), CpuRegister(TMP)); __ j(kEqual, slow_path->GetEntryLabel()); @@ -1276,8 +1276,10 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { if (!did_unpoison) { __ MaybeUnpoisonHeapReference(temp1); } + // /* HeapReference<Class> */ temp1 = temp1->component_type_ __ movl(temp1, Address(temp1, component_offset)); __ MaybeUnpoisonHeapReference(temp1); + // /* HeapReference<Class> */ temp1 = temp1->super_class_ __ movl(temp1, Address(temp1, super_offset)); // No need to unpoison the result, we're comparing against null. __ testl(temp1, temp1); @@ -1289,8 +1291,10 @@ void IntrinsicCodeGeneratorX86_64::VisitSystemArrayCopy(HInvoke* invoke) { } else if (!optimizations.GetSourceIsNonPrimitiveArray()) { DCHECK(optimizations.GetDestinationIsNonPrimitiveArray()); // Bail out if the source is not a non primitive array. + // /* HeapReference<Class> */ temp1 = src->klass_ __ movl(temp1, Address(src, class_offset)); __ MaybeUnpoisonHeapReference(temp1); + // /* HeapReference<Class> */ TMP = temp1->component_type_ __ movl(CpuRegister(TMP), Address(temp1, component_offset)); __ testl(CpuRegister(TMP), CpuRegister(TMP)); __ j(kEqual, slow_path->GetEntryLabel()); diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 1086cbf503..1afa36a89c 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -535,11 +535,16 @@ void HLoopInformation::PopulateRecursive(HBasicBlock* block) { } } -void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block) { - if (blocks_.IsBitSet(block->GetBlockId())) { +void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized) { + size_t block_id = block->GetBlockId(); + + // If `block` is in `finalized`, we know its membership in the loop has been + // decided and it does not need to be revisited. + if (finalized->IsBitSet(block_id)) { return; } + bool is_finalized = false; if (block->IsLoopHeader()) { // If we hit a loop header in an irreducible loop, we first check if the // pre header of that loop belongs to the currently analyzed loop. If it does, @@ -547,26 +552,36 @@ void HLoopInformation::PopulateIrreducibleRecursive(HBasicBlock* block) { // Note that we cannot use GetPreHeader, as the loop may have not been populated // yet. HBasicBlock* pre_header = block->GetPredecessors()[0]; - PopulateIrreducibleRecursive(pre_header); + PopulateIrreducibleRecursive(pre_header, finalized); if (blocks_.IsBitSet(pre_header->GetBlockId())) { - blocks_.SetBit(block->GetBlockId()); block->SetInLoop(this); + blocks_.SetBit(block_id); + finalized->SetBit(block_id); + is_finalized = true; + HLoopInformation* info = block->GetLoopInformation(); for (HBasicBlock* back_edge : info->GetBackEdges()) { - PopulateIrreducibleRecursive(back_edge); + PopulateIrreducibleRecursive(back_edge, finalized); } } } else { // Visit all predecessors. If one predecessor is part of the loop, this // block is also part of this loop. for (HBasicBlock* predecessor : block->GetPredecessors()) { - PopulateIrreducibleRecursive(predecessor); - if (blocks_.IsBitSet(predecessor->GetBlockId())) { - blocks_.SetBit(block->GetBlockId()); + PopulateIrreducibleRecursive(predecessor, finalized); + if (!is_finalized && blocks_.IsBitSet(predecessor->GetBlockId())) { block->SetInLoop(this); + blocks_.SetBit(block_id); + finalized->SetBit(block_id); + is_finalized = true; } } } + + // All predecessors have been recursively visited. Mark finalized if not marked yet. + if (!is_finalized) { + finalized->SetBit(block_id); + } } void HLoopInformation::Populate() { @@ -576,22 +591,37 @@ void HLoopInformation::Populate() { // to end the recursion. // This is a recursive implementation of the algorithm described in // "Advanced Compiler Design & Implementation" (Muchnick) p192. + HGraph* graph = header_->GetGraph(); blocks_.SetBit(header_->GetBlockId()); header_->SetInLoop(this); + + bool is_irreducible_loop = false; for (HBasicBlock* back_edge : GetBackEdges()) { DCHECK(back_edge->GetDominator() != nullptr); if (!header_->Dominates(back_edge)) { - irreducible_ = true; - header_->GetGraph()->SetHasIrreducibleLoops(true); - PopulateIrreducibleRecursive(back_edge); - } else { - if (header_->GetGraph()->IsCompilingOsr()) { - irreducible_ = true; - header_->GetGraph()->SetHasIrreducibleLoops(true); - } + is_irreducible_loop = true; + break; + } + } + + if (is_irreducible_loop) { + ArenaBitVector visited(graph->GetArena(), + graph->GetBlocks().size(), + /* expandable */ false, + kArenaAllocGraphBuilder); + for (HBasicBlock* back_edge : GetBackEdges()) { + PopulateIrreducibleRecursive(back_edge, &visited); + } + } else { + for (HBasicBlock* back_edge : GetBackEdges()) { PopulateRecursive(back_edge); } } + + if (is_irreducible_loop || graph->IsCompilingOsr()) { + irreducible_ = true; + graph->SetHasIrreducibleLoops(true); + } } HBasicBlock* HLoopInformation::GetPreHeader() const { diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 0088fed62a..dc5a8fa9cb 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -727,7 +727,7 @@ class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> { private: // Internal recursive implementation of `Populate`. void PopulateRecursive(HBasicBlock* block); - void PopulateIrreducibleRecursive(HBasicBlock* block); + void PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized); HBasicBlock* header_; HSuspendCheck* suspend_check_; |