diff options
Diffstat (limited to 'compiler')
24 files changed, 49 insertions, 580 deletions
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index 4c03e5ddfe..478588561f 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -249,9 +249,9 @@ class CompilerDriverProfileTest : public CompilerDriverTest { ProfileCompilationInfo info; for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { - std::cout << std::string(dex_file->GetLocation()); - profile_info_.AddData(dex_file->GetLocation(), dex_file->GetLocationChecksum(), 1); - profile_info_.AddData(dex_file->GetLocation(), dex_file->GetLocationChecksum(), 2); + std::string key = ProfileCompilationInfo::GetProfileDexFileKey(dex_file->GetLocation()); + profile_info_.AddData(key, dex_file->GetLocationChecksum(), 1); + profile_info_.AddData(key, dex_file->GetLocationChecksum(), 2); } return &profile_info_; } diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index d2bf6c07c8..3fe786141e 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -203,6 +203,7 @@ JitCompiler::~JitCompiler() { } bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) { + DCHECK(!method->IsProxyMethod()); TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit)); const uint64_t start_time = NanoTime(); StackHandleScope<2> hs(self); @@ -220,20 +221,17 @@ bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) { bool success = false; { TimingLogger::ScopedTiming t2("Compiling", &logger); - // If we get a request to compile a proxy method, we pass the actual Java method - // of that proxy method, as the compiler does not expect a proxy method. - ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(sizeof(void*)); JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache(); - success = compiler_driver_->GetCompiler()->JitCompile(self, code_cache, method_to_compile, osr); + success = compiler_driver_->GetCompiler()->JitCompile(self, code_cache, method, osr); if (success && (perf_file_ != nullptr)) { - const void* ptr = method_to_compile->GetEntryPointFromQuickCompiledCode(); + const void* ptr = method->GetEntryPointFromQuickCompiledCode(); std::ostringstream stream; stream << std::hex << reinterpret_cast<uintptr_t>(ptr) << " " << code_cache->GetMemorySizeOfCodePointer(ptr) << " " - << PrettyMethod(method_to_compile) + << PrettyMethod(method) << std::endl; std::string str = stream.str(); bool res = perf_file_->WriteFully(str.c_str(), str.size()); diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 8d77daf183..a1d62760a1 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -37,41 +37,6 @@ namespace art { -/** - * Helper class to add HTemporary instructions. This class is used when - * converting a DEX instruction to multiple HInstruction, and where those - * instructions do not die at the following instruction, but instead spans - * multiple instructions. - */ -class Temporaries : public ValueObject { - public: - explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {} - - void Add(HInstruction* instruction) { - HInstruction* temp = new (graph_->GetArena()) HTemporary(index_, instruction->GetDexPc()); - instruction->GetBlock()->AddInstruction(temp); - - DCHECK(temp->GetPrevious() == instruction); - - size_t offset; - if (instruction->GetType() == Primitive::kPrimLong - || instruction->GetType() == Primitive::kPrimDouble) { - offset = 2; - } else { - offset = 1; - } - index_ += offset; - - graph_->UpdateTemporariesVRegSlots(index_); - } - - private: - HGraph* const graph_; - - // Current index in the temporary stack, updated by `Add`. - size_t index_; -}; - void HGraphBuilder::InitializeLocals(uint16_t count) { graph_->SetNumberOfVRegs(count); locals_.resize(count); @@ -1166,12 +1131,10 @@ bool HGraphBuilder::HandleInvoke(HInvoke* invoke, size_t start_index = 0; size_t argument_index = 0; if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) { // Instance call. - Temporaries temps(graph_); HInstruction* arg = LoadLocal( is_range ? register_index : args[0], Primitive::kPrimNot, invoke->GetDexPc()); HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc()); current_block_->AddInstruction(null_check); - temps.Add(null_check); invoke->SetArgumentAt(0, null_check); start_index = 1; argument_index = 1; @@ -1269,9 +1232,6 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, ? GetFieldAccessType(*dex_file_, field_index) : resolved_field->GetTypeAsPrimitiveType(); if (is_put) { - Temporaries temps(graph_); - // We need one temporary for the null check. - temps.Add(null_check); HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); HInstruction* field_set = nullptr; if (resolved_field == nullptr) { @@ -1456,8 +1416,6 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, uint16_t class_def_index = klass->GetDexClassDefIndex(); if (is_put) { // We need to keep the class alive before loading the value. - Temporaries temps(graph_); - temps.Add(cls); HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc); DCHECK_EQ(value->GetType(), field_type); current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls, @@ -1510,9 +1468,7 @@ void HGraphBuilder::BuildCheckedDivRem(uint16_t out_vreg, || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0) || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) { second = new (arena_) HDivZeroCheck(second, dex_pc); - Temporaries temps(graph_); current_block_->AddInstruction(second); - temps.Add(current_block_->GetLastInstruction()); } if (isDiv) { @@ -1531,21 +1487,15 @@ void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, uint8_t array_reg = instruction.VRegB_23x(); uint8_t index_reg = instruction.VRegC_23x(); - // We need one temporary for the null check, one for the index, and one for the length. - Temporaries temps(graph_); - HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot, dex_pc); object = new (arena_) HNullCheck(object, dex_pc); current_block_->AddInstruction(object); - temps.Add(object); HInstruction* length = new (arena_) HArrayLength(object, dex_pc); current_block_->AddInstruction(length); - temps.Add(length); HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt, dex_pc); index = new (arena_) HBoundsCheck(index, length, dex_pc); current_block_->AddInstruction(index); - temps.Add(index); if (is_put) { HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type, dex_pc); // TODO: Insert a type check node if the type is Object. @@ -1586,8 +1536,6 @@ void HGraphBuilder::BuildFilledNewArray(uint32_t dex_pc, bool is_reference_array = (primitive == 'L') || (primitive == '['); Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt; - Temporaries temps(graph_); - temps.Add(object); for (size_t i = 0; i < number_of_vreg_arguments; ++i) { HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc); HInstruction* index = graph_->GetIntConstant(i, dex_pc); @@ -1612,11 +1560,9 @@ void HGraphBuilder::BuildFillArrayData(HInstruction* object, } void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) { - Temporaries temps(graph_); HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot, dex_pc); HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc); current_block_->AddInstruction(null_check); - temps.Add(null_check); HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc); current_block_->AddInstruction(length); @@ -1733,10 +1679,6 @@ void HGraphBuilder::BuildTypeCheck(const Instruction& instruction, compiler_driver_->CanAssumeTypeIsPresentInDexCache(dex_file, type_index)); current_block_->AddInstruction(cls); - // The class needs a temporary before being used by the type check. - Temporaries temps(graph_); - temps.Add(cls); - TypeCheckKind check_kind = ComputeTypeCheckKind(resolved_class); if (instruction.Opcode() == Instruction::INSTANCE_OF) { current_block_->AddInstruction(new (arena_) HInstanceOf(object, cls, check_kind, dex_pc)); @@ -2815,8 +2757,6 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 case Instruction::ARRAY_LENGTH: { HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot, dex_pc); - // No need for a temporary for the null check, it is the only input of the following - // instruction. object = new (arena_) HNullCheck(object, dex_pc); current_block_->AddInstruction(object); current_block_->AddInstruction(new (arena_) HArrayLength(object, dex_pc)); diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index e1b83f05d6..c2c8ccfc56 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -287,19 +287,6 @@ void CodeGenerator::InitializeCodeGeneration(size_t number_of_spill_slots, } } -Location CodeGenerator::GetTemporaryLocation(HTemporary* temp) const { - uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs(); - // The type of the previous instruction tells us if we need a single or double stack slot. - Primitive::Type type = temp->GetType(); - int32_t temp_size = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble) ? 2 : 1; - // Use the temporary region (right below the dex registers). - int32_t slot = GetFrameSize() - FrameEntrySpillSize() - - kVRegSize // filler - - (number_of_locals * kVRegSize) - - ((temp_size + temp->GetIndex()) * kVRegSize); - return temp_size == 2 ? Location::DoubleStackSlot(slot) : Location::StackSlot(slot); -} - int32_t CodeGenerator::GetStackSlot(HLocal* local) const { uint16_t reg_number = local->GetRegNumber(); uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs(); diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 0a688cf649..49c193e7bf 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -187,7 +187,6 @@ class CodeGenerator { virtual void GenerateFrameEntry() = 0; virtual void GenerateFrameExit() = 0; virtual void Bind(HBasicBlock* block) = 0; - virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0; virtual void MoveConstant(Location destination, int32_t value) = 0; virtual void MoveLocation(Location dst, Location src, Primitive::Type dst_type) = 0; virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0; @@ -203,7 +202,6 @@ class CodeGenerator { size_t number_of_out_slots, const ArenaVector<HBasicBlock*>& block_order); int32_t GetStackSlot(HLocal* local) const; - Location GetTemporaryLocation(HTemporary* temp) const; uint32_t GetFrameSize() const { return frame_size_; } void SetFrameSize(uint32_t size) { frame_size_ = size; } diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index e43493280a..005b6c189e 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1195,90 +1195,6 @@ void CodeGeneratorARM::Move64(Location destination, Location source) { } } -void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) { - LocationSummary* locations = instruction->GetLocations(); - if (instruction->IsCurrentMethod()) { - Move32(location, Location::StackSlot(kCurrentMethodStackOffset)); - } else if (locations != nullptr && locations->Out().Equals(location)) { - return; - } else if (locations != nullptr && locations->Out().IsConstant()) { - HConstant* const_to_move = locations->Out().GetConstant(); - if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) { - int32_t value = GetInt32ValueOf(const_to_move); - if (location.IsRegister()) { - __ LoadImmediate(location.AsRegister<Register>(), value); - } else { - DCHECK(location.IsStackSlot()); - __ LoadImmediate(IP, value); - __ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex()); - } - } else { - DCHECK(const_to_move->IsLongConstant()) << const_to_move->DebugName(); - int64_t value = const_to_move->AsLongConstant()->GetValue(); - if (location.IsRegisterPair()) { - __ LoadImmediate(location.AsRegisterPairLow<Register>(), Low32Bits(value)); - __ LoadImmediate(location.AsRegisterPairHigh<Register>(), High32Bits(value)); - } else { - DCHECK(location.IsDoubleStackSlot()); - __ LoadImmediate(IP, Low32Bits(value)); - __ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex()); - __ LoadImmediate(IP, High32Bits(value)); - __ StoreToOffset(kStoreWord, IP, SP, location.GetHighStackIndex(kArmWordSize)); - } - } - } else if (instruction->IsLoadLocal()) { - uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimFloat: - Move32(location, Location::StackSlot(stack_slot)); - break; - - case Primitive::kPrimLong: - case Primitive::kPrimDouble: - Move64(location, Location::DoubleStackSlot(stack_slot)); - break; - - default: - LOG(FATAL) << "Unexpected type " << instruction->GetType(); - } - } else if (instruction->IsTemporary()) { - Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - if (temp_location.IsStackSlot()) { - Move32(location, temp_location); - } else { - DCHECK(temp_location.IsDoubleStackSlot()); - Move64(location, temp_location); - } - } else { - DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimNot: - case Primitive::kPrimInt: - case Primitive::kPrimFloat: - Move32(location, locations->Out()); - break; - - case Primitive::kPrimLong: - case Primitive::kPrimDouble: - Move64(location, locations->Out()); - break; - - default: - LOG(FATAL) << "Unexpected type " << instruction->GetType(); - } - } -} - void CodeGeneratorARM::MoveConstant(Location location, int32_t value) { DCHECK(location.IsRegister()); __ LoadImmediate(location.AsRegister<Register>(), value); @@ -4933,14 +4849,6 @@ void CodeGeneratorARM::MarkGCCard(Register temp, } } -void LocationsBuilderARM::VisitTemporary(HTemporary* temp) { - temp->SetLocations(nullptr); -} - -void InstructionCodeGeneratorARM::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) { - // Nothing to do, this is driven by the code generator. -} - void LocationsBuilderARM::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) { LOG(FATAL) << "Unreachable"; } diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index 558c9cf0e4..cfd7a3bc14 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -307,7 +307,6 @@ class CodeGeneratorARM : public CodeGenerator { void GenerateFrameEntry() OVERRIDE; void GenerateFrameExit() OVERRIDE; void Bind(HBasicBlock* block) OVERRIDE; - void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index cfdf6b18cd..de23fe8eef 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1066,54 +1066,6 @@ void CodeGeneratorARM64::Bind(HBasicBlock* block) { __ Bind(GetLabelOf(block)); } -void CodeGeneratorARM64::Move(HInstruction* instruction, - Location location, - HInstruction* move_for) { - LocationSummary* locations = instruction->GetLocations(); - Primitive::Type type = instruction->GetType(); - DCHECK_NE(type, Primitive::kPrimVoid); - - if (instruction->IsCurrentMethod()) { - MoveLocation(location, - Location::DoubleStackSlot(kCurrentMethodStackOffset), - Primitive::kPrimVoid); - } else if (locations != nullptr && locations->Out().Equals(location)) { - return; - } else if (instruction->IsIntConstant() - || instruction->IsLongConstant() - || instruction->IsNullConstant()) { - int64_t value = GetInt64ValueOf(instruction->AsConstant()); - if (location.IsRegister()) { - Register dst = RegisterFrom(location, type); - DCHECK(((instruction->IsIntConstant() || instruction->IsNullConstant()) && dst.Is32Bits()) || - (instruction->IsLongConstant() && dst.Is64Bits())); - __ Mov(dst, value); - } else { - DCHECK(location.IsStackSlot() || location.IsDoubleStackSlot()); - UseScratchRegisterScope temps(GetVIXLAssembler()); - Register temp = (instruction->IsIntConstant() || instruction->IsNullConstant()) - ? temps.AcquireW() - : temps.AcquireX(); - __ Mov(temp, value); - __ Str(temp, StackOperandFrom(location)); - } - } else if (instruction->IsTemporary()) { - Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - MoveLocation(location, temp_location, type); - } else if (instruction->IsLoadLocal()) { - uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); - if (Primitive::Is64BitType(type)) { - MoveLocation(location, Location::DoubleStackSlot(stack_slot), type); - } else { - MoveLocation(location, Location::StackSlot(stack_slot), type); - } - - } else { - DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); - MoveLocation(location, locations->Out(), type); - } -} - void CodeGeneratorARM64::MoveConstant(Location location, int32_t value) { DCHECK(location.IsRegister()); __ Mov(RegisterFrom(location, Primitive::kPrimInt), value); @@ -4445,14 +4397,6 @@ void InstructionCodeGeneratorARM64::VisitSuspendCheck(HSuspendCheck* instruction GenerateSuspendCheck(instruction, nullptr); } -void LocationsBuilderARM64::VisitTemporary(HTemporary* temp) { - temp->SetLocations(nullptr); -} - -void InstructionCodeGeneratorARM64::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) { - // Nothing to do, this is driven by the code generator. -} - void LocationsBuilderARM64::VisitThrow(HThrow* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index a9d1bbde98..360488eb4a 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -350,8 +350,6 @@ class CodeGeneratorARM64 : public CodeGenerator { return CommonGetLabelOf<vixl::Label>(block_labels_, block); } - void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; - size_t GetWordSize() const OVERRIDE { return kArm64WordSize; } diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index e9c0b6ae79..3eda8639c1 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -976,46 +976,6 @@ void CodeGeneratorMIPS::MoveConstant(Location destination, int32_t value) { __ LoadConst32(dst, value); } -void CodeGeneratorMIPS::Move(HInstruction* instruction, - Location location, - HInstruction* move_for) { - LocationSummary* locations = instruction->GetLocations(); - Primitive::Type type = instruction->GetType(); - DCHECK_NE(type, Primitive::kPrimVoid); - - if (instruction->IsCurrentMethod()) { - Move32(location, Location::StackSlot(kCurrentMethodStackOffset)); - } else if (locations != nullptr && locations->Out().Equals(location)) { - return; - } else if (instruction->IsIntConstant() - || instruction->IsLongConstant() - || instruction->IsNullConstant()) { - MoveConstant(location, instruction->AsConstant()); - } else if (instruction->IsTemporary()) { - Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - if (temp_location.IsStackSlot()) { - Move32(location, temp_location); - } else { - DCHECK(temp_location.IsDoubleStackSlot()); - Move64(location, temp_location); - } - } else if (instruction->IsLoadLocal()) { - uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); - if (Primitive::Is64BitType(type)) { - Move64(location, Location::DoubleStackSlot(stack_slot)); - } else { - Move32(location, Location::StackSlot(stack_slot)); - } - } else { - DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); - if (Primitive::Is64BitType(type)) { - Move64(location, locations->Out()); - } else { - Move32(location, locations->Out()); - } - } -} - void CodeGeneratorMIPS::AddLocationAsTemp(Location location, LocationSummary* locations) { if (location.IsRegister()) { locations->AddTemp(location); @@ -4795,14 +4755,6 @@ void InstructionCodeGeneratorMIPS::VisitSuspendCheck(HSuspendCheck* instruction) GenerateSuspendCheck(instruction, nullptr); } -void LocationsBuilderMIPS::VisitTemporary(HTemporary* temp) { - temp->SetLocations(nullptr); -} - -void InstructionCodeGeneratorMIPS::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) { - // Nothing to do, this is driven by the code generator. -} - void LocationsBuilderMIPS::VisitThrow(HThrow* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h index 2cde0ed90b..12964b0b6a 100644 --- a/compiler/optimizing/code_generator_mips.h +++ b/compiler/optimizing/code_generator_mips.h @@ -268,7 +268,6 @@ class CodeGeneratorMIPS : public CodeGenerator { void Bind(HBasicBlock* block) OVERRIDE; - void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; void Move32(Location destination, Location source); void Move64(Location destination, Location source); void MoveConstant(Location location, HConstant* c); diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index da98a89f65..71d65e84a6 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -869,65 +869,6 @@ void CodeGeneratorMIPS64::SwapLocations(Location loc1, Location loc2, Primitive: } } -void CodeGeneratorMIPS64::Move(HInstruction* instruction, - Location location, - HInstruction* move_for) { - LocationSummary* locations = instruction->GetLocations(); - Primitive::Type type = instruction->GetType(); - DCHECK_NE(type, Primitive::kPrimVoid); - - if (instruction->IsCurrentMethod()) { - MoveLocation(location, Location::DoubleStackSlot(kCurrentMethodStackOffset), type); - } else if (locations != nullptr && locations->Out().Equals(location)) { - return; - } else if (instruction->IsIntConstant() - || instruction->IsLongConstant() - || instruction->IsNullConstant()) { - if (location.IsRegister()) { - // Move to GPR from constant - GpuRegister dst = location.AsRegister<GpuRegister>(); - if (instruction->IsNullConstant() || instruction->IsIntConstant()) { - __ LoadConst32(dst, GetInt32ValueOf(instruction->AsConstant())); - } else { - __ LoadConst64(dst, instruction->AsLongConstant()->GetValue()); - } - } else { - DCHECK(location.IsStackSlot() || location.IsDoubleStackSlot()); - // Move to stack from constant - GpuRegister gpr = ZERO; - if (location.IsStackSlot()) { - int32_t value = GetInt32ValueOf(instruction->AsConstant()); - if (value != 0) { - gpr = TMP; - __ LoadConst32(gpr, value); - } - __ StoreToOffset(kStoreWord, gpr, SP, location.GetStackIndex()); - } else { - DCHECK(location.IsDoubleStackSlot()); - int64_t value = instruction->AsLongConstant()->GetValue(); - if (value != 0) { - gpr = TMP; - __ LoadConst64(gpr, value); - } - __ StoreToOffset(kStoreDoubleword, gpr, SP, location.GetStackIndex()); - } - } - } else if (instruction->IsTemporary()) { - Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - MoveLocation(location, temp_location, type); - } else if (instruction->IsLoadLocal()) { - uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); - if (Primitive::Is64BitType(type)) { - MoveLocation(location, Location::DoubleStackSlot(stack_slot), type); - } else { - MoveLocation(location, Location::StackSlot(stack_slot), type); - } - } else { - DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); - MoveLocation(location, locations->Out(), type); - } -} - void CodeGeneratorMIPS64::MoveConstant(Location location, int32_t value) { DCHECK(location.IsRegister()); __ LoadConst32(location.AsRegister<GpuRegister>(), value); @@ -3946,14 +3887,6 @@ void InstructionCodeGeneratorMIPS64::VisitSuspendCheck(HSuspendCheck* instructio GenerateSuspendCheck(instruction, nullptr); } -void LocationsBuilderMIPS64::VisitTemporary(HTemporary* temp) { - temp->SetLocations(nullptr); -} - -void InstructionCodeGeneratorMIPS64::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) { - // Nothing to do, this is driven by the code generator. -} - void LocationsBuilderMIPS64::VisitThrow(HThrow* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h index c836f837de..1161253792 100644 --- a/compiler/optimizing/code_generator_mips64.h +++ b/compiler/optimizing/code_generator_mips64.h @@ -268,8 +268,6 @@ class CodeGeneratorMIPS64 : public CodeGenerator { void Bind(HBasicBlock* block) OVERRIDE; - void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; - size_t GetWordSize() const OVERRIDE { return kMips64DoublewordSize; } size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64DoublewordSize; } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index de62010102..3713690335 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1127,91 +1127,6 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { } } -void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) { - LocationSummary* locations = instruction->GetLocations(); - if (instruction->IsCurrentMethod()) { - Move32(location, Location::StackSlot(kCurrentMethodStackOffset)); - } else if (locations != nullptr && locations->Out().Equals(location)) { - return; - } else if (locations != nullptr && locations->Out().IsConstant()) { - HConstant* const_to_move = locations->Out().GetConstant(); - if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) { - Immediate imm(GetInt32ValueOf(const_to_move)); - if (location.IsRegister()) { - __ movl(location.AsRegister<Register>(), imm); - } else if (location.IsStackSlot()) { - __ movl(Address(ESP, location.GetStackIndex()), imm); - } else { - DCHECK(location.IsConstant()); - DCHECK_EQ(location.GetConstant(), const_to_move); - } - } else if (const_to_move->IsLongConstant()) { - int64_t value = const_to_move->AsLongConstant()->GetValue(); - if (location.IsRegisterPair()) { - __ movl(location.AsRegisterPairLow<Register>(), Immediate(Low32Bits(value))); - __ movl(location.AsRegisterPairHigh<Register>(), Immediate(High32Bits(value))); - } else if (location.IsDoubleStackSlot()) { - __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value))); - __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)), - Immediate(High32Bits(value))); - } else { - DCHECK(location.IsConstant()); - DCHECK_EQ(location.GetConstant(), instruction); - } - } - } else if (instruction->IsTemporary()) { - Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - if (temp_location.IsStackSlot()) { - Move32(location, temp_location); - } else { - DCHECK(temp_location.IsDoubleStackSlot()); - Move64(location, temp_location); - } - } else if (instruction->IsLoadLocal()) { - int slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimFloat: - Move32(location, Location::StackSlot(slot)); - break; - - case Primitive::kPrimLong: - case Primitive::kPrimDouble: - Move64(location, Location::DoubleStackSlot(slot)); - break; - - default: - LOG(FATAL) << "Unimplemented local type " << instruction->GetType(); - } - } else { - DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimFloat: - Move32(location, locations->Out()); - break; - - case Primitive::kPrimLong: - case Primitive::kPrimDouble: - Move64(location, locations->Out()); - break; - - default: - LOG(FATAL) << "Unexpected type " << instruction->GetType(); - } - } -} - void CodeGeneratorX86::MoveConstant(Location location, int32_t value) { DCHECK(location.IsRegister()); __ movl(location.AsRegister<Register>(), Immediate(value)); @@ -5513,14 +5428,6 @@ void InstructionCodeGeneratorX86::VisitBoundsCheck(HBoundsCheck* instruction) { } } -void LocationsBuilderX86::VisitTemporary(HTemporary* temp) { - temp->SetLocations(nullptr); -} - -void InstructionCodeGeneratorX86::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) { - // Nothing to do, this is driven by the code generator. -} - void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) { LOG(FATAL) << "Unreachable"; } diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index 45e8ffa84f..2fb6d60ad5 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -317,7 +317,6 @@ class CodeGeneratorX86 : public CodeGenerator { void GenerateFrameEntry() OVERRIDE; void GenerateFrameExit() OVERRIDE; void Bind(HBasicBlock* block) OVERRIDE; - void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 4f0f5f0ff8..35603aa030 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1206,82 +1206,6 @@ void CodeGeneratorX86_64::Move(Location destination, Location source) { } } -void CodeGeneratorX86_64::Move(HInstruction* instruction, - Location location, - HInstruction* move_for) { - LocationSummary* locations = instruction->GetLocations(); - if (instruction->IsCurrentMethod()) { - Move(location, Location::DoubleStackSlot(kCurrentMethodStackOffset)); - } else if (locations != nullptr && locations->Out().Equals(location)) { - return; - } else if (locations != nullptr && locations->Out().IsConstant()) { - HConstant* const_to_move = locations->Out().GetConstant(); - if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) { - Immediate imm(GetInt32ValueOf(const_to_move)); - if (location.IsRegister()) { - __ movl(location.AsRegister<CpuRegister>(), imm); - } else if (location.IsStackSlot()) { - __ movl(Address(CpuRegister(RSP), location.GetStackIndex()), imm); - } else { - DCHECK(location.IsConstant()); - DCHECK_EQ(location.GetConstant(), const_to_move); - } - } else if (const_to_move->IsLongConstant()) { - int64_t value = const_to_move->AsLongConstant()->GetValue(); - if (location.IsRegister()) { - Load64BitValue(location.AsRegister<CpuRegister>(), value); - } else if (location.IsDoubleStackSlot()) { - Store64BitValueToStack(location, value); - } else { - DCHECK(location.IsConstant()); - DCHECK_EQ(location.GetConstant(), const_to_move); - } - } - } else if (instruction->IsLoadLocal()) { - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimFloat: - Move(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal()))); - break; - - case Primitive::kPrimLong: - case Primitive::kPrimDouble: - Move(location, - Location::DoubleStackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal()))); - break; - - default: - LOG(FATAL) << "Unexpected local type " << instruction->GetType(); - } - } else if (instruction->IsTemporary()) { - Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - Move(location, temp_location); - } else { - DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); - switch (instruction->GetType()) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: - case Primitive::kPrimChar: - case Primitive::kPrimShort: - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - Move(location, locations->Out()); - break; - - default: - LOG(FATAL) << "Unexpected type " << instruction->GetType(); - } - } -} - void CodeGeneratorX86_64::MoveConstant(Location location, int32_t value) { DCHECK(location.IsRegister()); Load64BitValue(location.AsRegister<CpuRegister>(), static_cast<int64_t>(value)); @@ -5142,14 +5066,6 @@ void CodeGeneratorX86_64::MarkGCCard(CpuRegister temp, } } -void LocationsBuilderX86_64::VisitTemporary(HTemporary* temp) { - temp->SetLocations(nullptr); -} - -void InstructionCodeGeneratorX86_64::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) { - // Nothing to do, this is driven by the code generator. -} - void LocationsBuilderX86_64::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) { LOG(FATAL) << "Unimplemented"; } diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index 72dddfddfa..97f6f84236 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -299,7 +299,6 @@ class CodeGeneratorX86_64 : public CodeGenerator { void GenerateFrameEntry() OVERRIDE; void GenerateFrameExit() OVERRIDE; void Bind(HBasicBlock* block) OVERRIDE; - void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; void MoveConstant(Location destination, int32_t value) OVERRIDE; void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index 322a577bbf..4f37c37e39 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -777,9 +777,9 @@ TEST_F(CodegenTest, MaterializedCondition2) { HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]); HLessThan cmp_lt(cst_lhs, cst_rhs); if_block->AddInstruction(&cmp_lt); - // We insert a temporary to separate the HIf from the HLessThan and force - // the materialization of the condition. - HTemporary force_materialization(0); + // We insert a dummy instruction to separate the HIf from the HLessThan + // and force the materialization of the condition. + HMemoryBarrier force_materialization(MemBarrierKind::kAnyAny, 0); if_block->AddInstruction(&force_materialization); HIf if_lt(&cmp_lt); if_block->AddInstruction(&if_lt); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index fa6aae81f8..3740c405c1 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -378,7 +378,7 @@ bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction, // Run type propagation to get the guard typed, and eventually propagate the // type of the receiver. - ReferenceTypePropagation rtp_fixup(graph_, handles_); + ReferenceTypePropagation rtp_fixup(graph_, handles_, /* is_first_run */ false); rtp_fixup.Run(); MaybeRecordStat(kInlinedMonomorphicCall); @@ -420,6 +420,9 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, actual_method = new_method; } else if (actual_method != new_method) { // Different methods, bailout. + VLOG(compiler) << "Call to " << PrettyMethod(resolved_method) + << " from inline cache is not inlined because it resolves" + << " to different methods"; return false; } } @@ -474,7 +477,7 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, deoptimize->CopyEnvironmentFrom(invoke_instruction->GetEnvironment()); // Run type propagation to get the guard typed. - ReferenceTypePropagation rtp_fixup(graph_, handles_); + ReferenceTypePropagation rtp_fixup(graph_, handles_, /* is_first_run */ false); rtp_fixup.Run(); MaybeRecordStat(kInlinedPolymorphicCall); @@ -727,7 +730,7 @@ HInstanceFieldGet* HInliner::CreateInstanceFieldGet(Handle<mirror::DexCache> dex // dex pc for the associated stack map. 0 is bogus but valid. Bug: 26854537. /* dex_pc */ 0); if (iget->GetType() == Primitive::kPrimNot) { - ReferenceTypePropagation rtp(graph_, handles_); + ReferenceTypePropagation rtp(graph_, handles_, /* is_first_run */ false); rtp.Visit(iget); } return iget; @@ -756,6 +759,7 @@ HInstanceFieldSet* HInliner::CreateInstanceFieldSet(Handle<mirror::DexCache> dex /* dex_pc */ 0); return iput; } + bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, HInvoke* invoke_instruction, bool same_dex_file, @@ -988,12 +992,18 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, if (current->IsNewInstance() && (current->AsNewInstance()->GetEntrypoint() == kQuickAllocObjectWithAccessCheck)) { + VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file) + << " could not be inlined because it is using an entrypoint" + << " with access checks"; // Allocation entrypoint does not handle inlined frames. return false; } if (current->IsNewArray() && (current->AsNewArray()->GetEntrypoint() == kQuickAllocArrayWithAccessCheck)) { + VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file) + << " could not be inlined because it is using an entrypoint" + << " with access checks"; // Allocation entrypoint does not handle inlined frames. return false; } @@ -1003,6 +1013,9 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, current->IsUnresolvedStaticFieldSet() || current->IsUnresolvedInstanceFieldSet()) { // Entrypoint for unresolved fields does not handle inlined frames. + VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file) + << " could not be inlined because it is using an unresolved" + << " entrypoint"; return false; } } @@ -1044,13 +1057,13 @@ void HInliner::FixUpReturnReferenceType(ArtMethod* resolved_method, if (invoke_rti.IsStrictSupertypeOf(return_rti) || (return_rti.IsExact() && !invoke_rti.IsExact()) || !return_replacement->CanBeNull()) { - ReferenceTypePropagation(graph_, handles_).Run(); + ReferenceTypePropagation(graph_, handles_, /* is_first_run */ false).Run(); } } } else if (return_replacement->IsInstanceOf()) { if (do_rtp) { // Inlining InstanceOf into an If may put a tighter bound on reference types. - ReferenceTypePropagation(graph_, handles_).Run(); + ReferenceTypePropagation(graph_, handles_, /* is_first_run */ false).Run(); } } } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 7f463a36e9..2697af33eb 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1235,7 +1235,6 @@ class HLoopInformationOutwardIterator : public ValueObject { M(StoreLocal, Instruction) \ M(Sub, BinaryOperation) \ M(SuspendCheck, Instruction) \ - M(Temporary, Instruction) \ M(Throw, Instruction) \ M(TryBoundary, Instruction) \ M(TypeConversion, Instruction) \ @@ -4941,33 +4940,6 @@ class HBoundsCheck : public HExpression<2> { DISALLOW_COPY_AND_ASSIGN(HBoundsCheck); }; -/** - * Some DEX instructions are folded into multiple HInstructions that need - * to stay live until the last HInstruction. This class - * is used as a marker for the baseline compiler to ensure its preceding - * HInstruction stays live. `index` represents the stack location index of the - * instruction (the actual offset is computed as index * vreg_size). - */ -class HTemporary : public HTemplateInstruction<0> { - public: - explicit HTemporary(size_t index, uint32_t dex_pc = kNoDexPc) - : HTemplateInstruction(SideEffects::None(), dex_pc), index_(index) {} - - size_t GetIndex() const { return index_; } - - Primitive::Type GetType() const OVERRIDE { - // The previous instruction is the one that will be stored in the temporary location. - DCHECK(GetPrevious() != nullptr); - return GetPrevious()->GetType(); - } - - DECLARE_INSTRUCTION(Temporary); - - private: - const size_t index_; - DISALLOW_COPY_AND_ASSIGN(HTemporary); -}; - class HSuspendCheck : public HTemplateInstruction<0> { public: explicit HSuspendCheck(uint32_t dex_pc) diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 1224a48fa0..deaa415ed4 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -55,10 +55,12 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { public: RTPVisitor(HGraph* graph, HandleCache* handle_cache, - ArenaVector<HInstruction*>* worklist) + ArenaVector<HInstruction*>* worklist, + bool is_first_run) : HGraphDelegateVisitor(graph), handle_cache_(handle_cache), - worklist_(worklist) {} + worklist_(worklist), + is_first_run_(is_first_run) {} void VisitNewInstance(HNewInstance* new_instance) OVERRIDE; void VisitLoadClass(HLoadClass* load_class) OVERRIDE; @@ -86,14 +88,17 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { private: HandleCache* handle_cache_; ArenaVector<HInstruction*>* worklist_; + const bool is_first_run_; }; ReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph, StackHandleScopeCollection* handles, + bool is_first_run, const char* name) : HOptimization(graph, name), handle_cache_(handles), - worklist_(graph->GetArena()->Adapter(kArenaAllocReferenceTypePropagation)) { + worklist_(graph->GetArena()->Adapter(kArenaAllocReferenceTypePropagation)), + is_first_run_(is_first_run) { } void ReferenceTypePropagation::ValidateTypes() { @@ -125,7 +130,7 @@ void ReferenceTypePropagation::ValidateTypes() { } void ReferenceTypePropagation::Visit(HInstruction* instruction) { - RTPVisitor visitor(graph_, &handle_cache_, &worklist_); + RTPVisitor visitor(graph_, &handle_cache_, &worklist_, is_first_run_); instruction->Accept(&visitor); } @@ -144,7 +149,7 @@ void ReferenceTypePropagation::Run() { } void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) { - RTPVisitor visitor(graph_, &handle_cache_, &worklist_); + RTPVisitor visitor(graph_, &handle_cache_, &worklist_, is_first_run_); // Handle Phis first as there might be instructions in the same block who depend on them. for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { VisitPhi(it.Current()->AsPhi()); @@ -620,6 +625,7 @@ void ReferenceTypePropagation::RTPVisitor::VisitCheckCast(HCheckCast* check_cast DCHECK_EQ(bound_type->InputAt(0), check_cast->InputAt(0)); if (class_rti.IsValid()) { + DCHECK(is_first_run_); // This is the first run of RTP and class is resolved. bound_type->SetUpperBound(class_rti, /* CheckCast succeeds for nulls. */ true); } else { @@ -636,6 +642,12 @@ void ReferenceTypePropagation::VisitPhi(HPhi* phi) { } if (phi->GetBlock()->IsLoopHeader()) { + if (!is_first_run_ && graph_->IsCompilingOsr()) { + // Don't update the type of a loop phi when compiling OSR: we may have done + // speculative optimizations dominating that phi, that do not hold at the + // point the interpreter jumps to that loop header. + return; + } ScopedObjectAccess soa(Thread::Current()); // Set the initial type for the phi. Use the non back edge input for reaching // a fixed point faster. diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index a7f10a65ab..028a6fc514 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -33,6 +33,7 @@ class ReferenceTypePropagation : public HOptimization { public: ReferenceTypePropagation(HGraph* graph, StackHandleScopeCollection* handles, + bool is_first_run, const char* name = kReferenceTypePropagationPassName); // Visit a single instruction. @@ -93,6 +94,8 @@ class ReferenceTypePropagation : public HOptimization { ArenaVector<HInstruction*> worklist_; + // Whether this reference type propagation is the first run we are doing. + const bool is_first_run_; static constexpr size_t kDefaultWorklistSize = 8; diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index 165d09d1a5..2d0a399290 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -483,7 +483,7 @@ GraphAnalysisResult SsaBuilder::BuildSsa() { // 6) Compute type of reference type instructions. The pass assumes that // NullConstant has been fixed up. - ReferenceTypePropagation(GetGraph(), handles_).Run(); + ReferenceTypePropagation(GetGraph(), handles_, /* is_first_run */ true).Run(); // 7) Step 1) duplicated ArrayGet instructions with ambiguous type (int/float // or long/double) and marked ArraySets with ambiguous input type. Now that RTP @@ -899,11 +899,6 @@ void SsaBuilder::VisitInstruction(HInstruction* instruction) { } } -void SsaBuilder::VisitTemporary(HTemporary* temp) { - // Temporaries are only used by the baseline register allocator. - temp->GetBlock()->RemoveInstruction(temp); -} - void SsaBuilder::VisitArrayGet(HArrayGet* aget) { Primitive::Type type = aget->GetType(); DCHECK(!Primitive::IsFloatingPointType(type)); diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h index ccef8ea380..4cba41f389 100644 --- a/compiler/optimizing/ssa_builder.h +++ b/compiler/optimizing/ssa_builder.h @@ -75,7 +75,6 @@ class SsaBuilder : public HGraphVisitor { void VisitLoadLocal(HLoadLocal* load) OVERRIDE; void VisitStoreLocal(HStoreLocal* store) OVERRIDE; void VisitInstruction(HInstruction* instruction) OVERRIDE; - void VisitTemporary(HTemporary* instruction) OVERRIDE; void VisitArrayGet(HArrayGet* aget) OVERRIDE; void VisitArraySet(HArraySet* aset) OVERRIDE; void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE; |