summaryrefslogtreecommitdiffstats
path: root/compiler/dex/quick/arm
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2015-04-07 09:36:09 +0100
committerVladimir Marko <vmarko@google.com>2015-04-07 19:13:40 +0100
commitcc23481b66fd1f2b459d82da4852073e32f033aa (patch)
treef2192d5fff8591e4e5b87d04fa6fce770f7e7f08 /compiler/dex/quick/arm
parente5c76c515a481074aaa6b869aa16490a47ba98bc (diff)
downloadandroid_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.cc8
-rw-r--r--compiler/dex/quick/arm/codegen_arm.h9
-rw-r--r--compiler/dex/quick/arm/int_arm.cc13
-rw-r--r--compiler/dex/quick/arm/target_arm.cc3
-rw-r--r--compiler/dex/quick/arm/utility_arm.cc35
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