diff options
author | Vladimir Marko <vmarko@google.com> | 2015-04-07 09:36:09 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-04-07 19:13:40 +0100 |
commit | cc23481b66fd1f2b459d82da4852073e32f033aa (patch) | |
tree | f2192d5fff8591e4e5b87d04fa6fce770f7e7f08 /compiler/dex/quick/arm | |
parent | e5c76c515a481074aaa6b869aa16490a47ba98bc (diff) | |
download | android_art-cc23481b66fd1f2b459d82da4852073e32f033aa.tar.gz android_art-cc23481b66fd1f2b459d82da4852073e32f033aa.tar.bz2 android_art-cc23481b66fd1f2b459d82da4852073e32f033aa.zip |
Promote pointer to dex cache arrays on arm.
Do the use-count analysis on temps (ArtMethod* and the new
PC-relative temp) in Mir2Lir, rather than MIRGraph. MIRGraph
isn't really supposed to know how the ArtMethod* is used by
the backend.
Change-Id: Iaf56a46ae203eca86281b02b54f39a80fe5cc2dd
Diffstat (limited to 'compiler/dex/quick/arm')
-rw-r--r-- | compiler/dex/quick/arm/call_arm.cc | 8 | ||||
-rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 9 | ||||
-rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 13 | ||||
-rw-r--r-- | compiler/dex/quick/arm/target_arm.cc | 3 | ||||
-rw-r--r-- | compiler/dex/quick/arm/utility_arm.cc | 35 |
5 files changed, 65 insertions, 3 deletions
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc index 3f4f1fef91..518e3ea3c9 100644 --- a/compiler/dex/quick/arm/call_arm.cc +++ b/compiler/dex/quick/arm/call_arm.cc @@ -491,6 +491,14 @@ void ArmMir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) { FlushIns(ArgLocs, rl_method); + // We can promote a PC-relative reference to dex cache arrays to a register + // if it's used at least twice. Without investigating where we should lazily + // load the reference, we conveniently load it after flushing inputs. + if (dex_cache_arrays_base_reg_.Valid()) { + OpPcRelDexCacheArrayAddr(cu_->dex_file, dex_cache_arrays_min_offset_, + dex_cache_arrays_base_reg_); + } + FreeTemp(rs_r0); FreeTemp(rs_r1); FreeTemp(rs_r2); diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 619c11fb94..83b27df939 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -260,6 +260,9 @@ class ArmMir2Lir FINAL : public Mir2Lir { */ LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE; + void CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs) OVERRIDE; + void DoPromotion() OVERRIDE; + /* * @brief Handle ARM specific literals. */ @@ -306,6 +309,10 @@ class ArmMir2Lir FINAL : public Mir2Lir { // Instructions needing patching with PC relative code addresses. ArenaVector<LIR*> dex_cache_access_insns_; + // Register with a reference to the dex cache arrays at dex_cache_arrays_min_offset_, + // if promoted. + RegStorage dex_cache_arrays_base_reg_; + /** * @brief Given float register pair, returns Solo64 float register. * @param reg #RegStorage containing a float register pair (e.g. @c s2 and @c s3). @@ -341,6 +348,8 @@ class ArmMir2Lir FINAL : public Mir2Lir { uint32_t unused_idx ATTRIBUTE_UNUSED, uintptr_t direct_code, uintptr_t direct_method, InvokeType type); + + void OpPcRelDexCacheArrayAddr(const DexFile* dex_file, int offset, RegStorage r_dest); }; } // namespace art diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index c788401cfb..47669db979 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -1091,7 +1091,7 @@ bool ArmMir2Lir::CanUseOpPcRelDexCacheArrayLoad() const { return dex_cache_arrays_layout_.Valid(); } -void ArmMir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) { +void ArmMir2Lir::OpPcRelDexCacheArrayAddr(const DexFile* dex_file, int offset, RegStorage r_dest) { LIR* movw = NewLIR2(kThumb2MovImm16, r_dest.GetReg(), 0); LIR* movt = NewLIR2(kThumb2MovImm16H, r_dest.GetReg(), 0); ArmOpcode add_pc_opcode = (r_dest.GetRegNum() < 8) ? kThumbAddRRLH : kThumbAddRRHH; @@ -1105,7 +1105,16 @@ void ArmMir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, R movt->operands[4] = movw->operands[4]; dex_cache_access_insns_.push_back(movw); dex_cache_access_insns_.push_back(movt); - LoadRefDisp(r_dest, 0, r_dest, kNotVolatile); +} + +void ArmMir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) { + if (dex_cache_arrays_base_reg_.Valid()) { + LoadRefDisp(dex_cache_arrays_base_reg_, offset - dex_cache_arrays_min_offset_, + r_dest, kNotVolatile); + } else { + OpPcRelDexCacheArrayAddr(dex_file, offset, r_dest); + LoadRefDisp(r_dest, 0, r_dest, kNotVolatile); + } } LIR* ArmMir2Lir::OpVldm(RegStorage r_base, int count) { diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc index 580dcb789f..5f27338e6b 100644 --- a/compiler/dex/quick/arm/target_arm.cc +++ b/compiler/dex/quick/arm/target_arm.cc @@ -576,7 +576,8 @@ RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatil ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) : Mir2Lir(cu, mir_graph, arena), call_method_insns_(arena->Adapter()), - dex_cache_access_insns_(arena->Adapter()) { + dex_cache_access_insns_(arena->Adapter()), + dex_cache_arrays_base_reg_(RegStorage::InvalidReg()) { call_method_insns_.reserve(100); // Sanity check - make sure encoding map lines up. for (int i = 0; i < kArmLast; i++) { diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc index e4bd2a33ae..c3371cf329 100644 --- a/compiler/dex/quick/arm/utility_arm.cc +++ b/compiler/dex/quick/arm/utility_arm.cc @@ -19,6 +19,7 @@ #include "arch/arm/instruction_set_features_arm.h" #include "arm_lir.h" #include "base/logging.h" +#include "dex/mir_graph.h" #include "dex/quick/mir_to_lir-inl.h" #include "dex/reg_storage_eq.h" #include "driver/compiler_driver.h" @@ -1266,4 +1267,38 @@ size_t ArmMir2Lir::GetInstructionOffset(LIR* lir) { return offset; } +void ArmMir2Lir::CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs) { + // Start with the default counts. + Mir2Lir::CountRefs(core_counts, fp_counts, num_regs); + + if (pc_rel_temp_ != nullptr) { + // Now, if the dex cache array base temp is used only once outside any loops (weight = 1), + // avoid the promotion, otherwise boost the weight by factor 4 because the full PC-relative + // load sequence is 4 instructions long. + int p_map_idx = SRegToPMap(pc_rel_temp_->s_reg_low); + if (core_counts[p_map_idx].count == 1) { + core_counts[p_map_idx].count = 0; + } else { + core_counts[p_map_idx].count *= 4; + } + } +} + +void ArmMir2Lir::DoPromotion() { + if (CanUseOpPcRelDexCacheArrayLoad()) { + pc_rel_temp_ = mir_graph_->GetNewCompilerTemp(kCompilerTempBackend, false); + } + + Mir2Lir::DoPromotion(); + + if (pc_rel_temp_ != nullptr) { + // Now, if the dex cache array base temp is promoted, remember the register but + // always remove the temp's stack location to avoid unnecessarily bloating the stack. + dex_cache_arrays_base_reg_ = mir_graph_->reg_location_[pc_rel_temp_->s_reg_low].reg; + DCHECK(!dex_cache_arrays_base_reg_.Valid() || !dex_cache_arrays_base_reg_.IsFloat()); + mir_graph_->RemoveLastCompilerTemp(kCompilerTempBackend, false, pc_rel_temp_); + pc_rel_temp_ = nullptr; + } +} + } // namespace art |