From 79e9f43951c3cfa9ab3b0fea93e5bfdfa7aa5950 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Sat, 23 Jan 2016 23:00:45 +0000 Subject: Lift the spill at each irreducible loop block restriction. It was not intended to have it this way anyway. This also required to fix GetSiblingAt, to take into account interval holes, and ConnectSplitSibling to re-materialize a constant or a method. Change-Id: Ia5534a93a5413cd0458a251c022d0b655369502b --- compiler/optimizing/graph_visualizer.cc | 1 + compiler/optimizing/register_allocator.cc | 37 ++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) (limited to 'compiler/optimizing') diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 32c3a925e0..2218d0b82a 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -505,6 +505,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { if (IsPass(LICM::kLoopInvariantCodeMotionPassName) || IsPass(HDeadCodeElimination::kFinalDeadCodeEliminationPassName) || IsPass(HDeadCodeElimination::kInitialDeadCodeEliminationPassName) + || IsPass(RegisterAllocator::kRegisterAllocatorPassName) || IsPass(SsaBuilder::kSsaBuilderPassName)) { HLoopInformation* info = instruction->GetBlock()->GetLoopInformation(); if (info == nullptr) { diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index d77639d608..44fb8de97e 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -179,7 +179,7 @@ void RegisterAllocator::AllocateRegistersInternal() { } if (block->IsCatchBlock() || - (block->GetLoopInformation() != nullptr && block->GetLoopInformation()->IsIrreducible())) { + (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible())) { // By blocking all registers at the top of each catch block or irreducible loop, we force // intervals belonging to the live-in set of the catch/header block to be spilled. // TODO(ngeoffray): Phis in this block could be allocated in register. @@ -1749,8 +1749,10 @@ void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval, } // Find the intervals that cover `from` and `to`. - LiveInterval* destination = interval->GetSiblingAt(to->GetLifetimeStart()); - LiveInterval* source = interval->GetSiblingAt(from->GetLifetimeEnd() - 1); + size_t destination_position = to->GetLifetimeStart(); + size_t source_position = from->GetLifetimeEnd() - 1; + LiveInterval* destination = interval->GetSiblingAt(destination_position); + LiveInterval* source = interval->GetSiblingAt(source_position); if (destination == source) { // Interval was not split. @@ -1775,18 +1777,41 @@ void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval, return; } + Location location_source; + // `GetSiblingAt` returns the interval whose start and end cover `position`, + // but does not check whether the interval is inactive at that position. + // The only situation where the interval is inactive at that position is in the + // presence of irreducible loops for constants and ArtMethod. + if (codegen_->GetGraph()->HasIrreducibleLoops() && + (source == nullptr || !source->CoversSlow(source_position))) { + DCHECK(IsMaterializableEntryBlockInstructionOfGraphWithIrreducibleLoop(defined_by)); + if (defined_by->IsConstant()) { + location_source = defined_by->GetLocations()->Out(); + } else { + DCHECK(defined_by->IsCurrentMethod()); + location_source = parent->NeedsTwoSpillSlots() + ? Location::DoubleStackSlot(parent->GetSpillSlot()) + : Location::StackSlot(parent->GetSpillSlot()); + } + } else { + DCHECK(source != nullptr); + DCHECK(source->CoversSlow(source_position)); + DCHECK(destination->CoversSlow(destination_position)); + location_source = source->ToLocation(); + } + // If `from` has only one successor, we can put the moves at the exit of it. Otherwise // we need to put the moves at the entry of `to`. if (from->GetNormalSuccessors().size() == 1) { InsertParallelMoveAtExitOf(from, defined_by, - source->ToLocation(), + location_source, destination->ToLocation()); } else { DCHECK_EQ(to->GetPredecessors().size(), 1u); InsertParallelMoveAtEntryOf(to, defined_by, - source->ToLocation(), + location_source, destination->ToLocation()); } } @@ -1890,7 +1915,7 @@ void RegisterAllocator::Resolve() { for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) { HBasicBlock* block = it.Current(); if (block->IsCatchBlock() || - (block->GetLoopInformation() != nullptr && block->GetLoopInformation()->IsIrreducible())) { + (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible())) { // Instructions live at the top of catch blocks or irreducible loop header // were forced to spill. if (kIsDebugBuild) { -- cgit v1.2.3-59-g8ed1b