Move PC-relative addressing bases to a better position.
Move the platform-specific HX86ComputeBaseMethodAddress and
HArmDexCacheArraysBase to the latest dominator of their uses
outside any loop. This brings the base closer to the first
use (previously, it was in the entry block) and relieves
some pressure on the register allocator while avoiding
recalculation of the base in a loop.
Change-Id: I231aa81eb5b4de9af2d0167054d06b65eb18a636
diff --git a/compiler/optimizing/dex_cache_array_fixups_arm.cc b/compiler/optimizing/dex_cache_array_fixups_arm.cc
index 7f5f0e5..6582063 100644
--- a/compiler/optimizing/dex_cache_array_fixups_arm.cc
+++ b/compiler/optimizing/dex_cache_array_fixups_arm.cc
@@ -33,6 +33,16 @@
// Attribute memory use to code generator.
graph->GetArena()->Adapter(kArenaAllocCodeGenerator)) {}
+ void MoveBasesIfNeeded() {
+ for (const auto& entry : dex_cache_array_bases_) {
+ // Bring the base closer to the first use (previously, it was in the
+ // entry block) and relieve some pressure on the register allocator
+ // while avoiding recalculation of the base in a loop.
+ HArmDexCacheArraysBase* base = entry.second;
+ base->MoveBeforeFirstUserAndOutOfLoops();
+ }
+ }
+
private:
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
// If this is an invoke with PC-relative access to the dex cache methods array,
@@ -40,7 +50,7 @@
if (invoke->HasPcRelativeDexCache()) {
// Initialize base for target method dex file if needed.
MethodReference target_method = invoke->GetTargetMethod();
- HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(invoke, *target_method.dex_file);
+ HArmDexCacheArraysBase* base = GetOrCreateDexCacheArrayBase(*target_method.dex_file);
// Update the element offset in base.
DexCacheArraysLayout layout(kArmPointerSize, target_method.dex_file);
base->UpdateElementOffset(layout.MethodOffset(target_method.dex_method_index));
@@ -50,8 +60,7 @@
}
}
- HArmDexCacheArraysBase* GetOrCreateDexCacheArrayBase(HInstruction* user,
- const DexFile& dex_file) {
+ HArmDexCacheArraysBase* GetOrCreateDexCacheArrayBase(const DexFile& dex_file) {
// Ensure we only initialize the pointer once for each dex file.
auto lb = dex_cache_array_bases_.lower_bound(&dex_file);
if (lb != dex_cache_array_bases_.end() &&
@@ -59,11 +68,11 @@
return lb->second;
}
- HGraph* graph = GetGraph();
- HBasicBlock* entry = graph->GetEntryBlock();
- HArmDexCacheArraysBase* base = new (graph->GetArena()) HArmDexCacheArraysBase(dex_file);
- HInstruction* insert_pos = (user->GetBlock() == entry) ? user : entry->GetLastInstruction();
- entry->InsertInstructionBefore(base, insert_pos);
+ // Insert the base at the start of the entry block, move it to a better
+ // position later in MoveBaseIfNeeded().
+ HArmDexCacheArraysBase* base = new (GetGraph()->GetArena()) HArmDexCacheArraysBase(dex_file);
+ HBasicBlock* entry_block = GetGraph()->GetEntryBlock();
+ entry_block->InsertInstructionBefore(base, entry_block->GetFirstInstruction());
dex_cache_array_bases_.PutBefore(lb, &dex_file, base);
return base;
}
@@ -76,6 +85,7 @@
void DexCacheArrayFixups::Run() {
DexCacheArrayFixupsVisitor visitor(graph_);
visitor.VisitInsertionOrder();
+ visitor.MoveBasesIfNeeded();
}
} // namespace arm