ART: Optimize iteration of safepoints
The LiveInterval::Covers method is optimized for multiple calls with
non-decreasing positions. This patch reverts the order of iteration
over safepoints in RegisterAllocator::ConnectSiblings to capitalize
on this effect.
Change-Id: Ieb70eb9d5c0a06ee79379aab6c87cb3290c15bf7
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 54e62a5..0e9c4d6 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -1381,6 +1381,7 @@
: Location::StackSlot(interval->GetParent()->GetSpillSlot()));
}
UsePosition* use = current->GetFirstUse();
+ size_t safepoint_index = safepoints_.Size();
// Walk over all siblings, updating locations of use positions, and
// connecting them when they are adjacent.
@@ -1422,19 +1423,27 @@
}
// At each safepoint, we record stack and register information.
- for (size_t i = 0, e = safepoints_.Size(); i < e; ++i) {
- HInstruction* safepoint = safepoints_.Get(i);
+ // We iterate backwards to test safepoints in ascending order of positions,
+ // which is what LiveInterval::Covers is optimized for.
+ while (safepoint_index > 0) {
+ HInstruction* safepoint = safepoints_.Get(--safepoint_index);
size_t position = safepoint->GetLifetimePosition();
- LocationSummary* locations = safepoint->GetLocations();
- if (!current->Covers(position)) {
+
+ // Test that safepoints are ordered in the optimal way.
+ DCHECK(safepoint_index == 0
+ || safepoints_.Get(safepoint_index - 1)->GetLifetimePosition() >= position);
+
+ if (current->IsDeadAt(position)) {
+ break;
+ } else if (!current->Covers(position)) {
continue;
- }
- if (interval->GetStart() == position) {
+ } else if (interval->GetStart() == position) {
// The safepoint is for this instruction, so the location of the instruction
// does not need to be saved.
continue;
}
+ LocationSummary* locations = safepoint->GetLocations();
if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) {
locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize);
}