diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/register_allocator.cc | 54 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.cc | 32 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.h | 25 |
3 files changed, 74 insertions, 37 deletions
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index cf38bd3f8c..aa1584a4cc 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -1408,26 +1408,36 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) { // Walk over all uses covered by this interval, and update the location // information. - while (use != nullptr && use->GetPosition() <= current->GetEnd()) { - LocationSummary* locations = use->GetUser()->GetLocations(); - if (use->GetIsEnvironment()) { - locations->SetEnvironmentAt(use->GetInputIndex(), source); - } else { - Location expected_location = locations->InAt(use->GetInputIndex()); - // The expected (actual) location may be invalid in case the input is unused. Currently - // this only happens for intrinsics. - if (expected_location.IsValid()) { - if (expected_location.IsUnallocated()) { - locations->SetInAt(use->GetInputIndex(), source); - } else if (!expected_location.IsConstant()) { - AddInputMoveFor(interval->GetDefinedBy(), use->GetUser(), source, expected_location); - } + + LiveRange* range = current->GetFirstRange(); + while (range != nullptr) { + while (use != nullptr && use->GetPosition() < range->GetStart()) { + DCHECK(use->GetIsEnvironment()); + use = use->GetNext(); + } + while (use != nullptr && use->GetPosition() <= range->GetEnd()) { + DCHECK(current->Covers(use->GetPosition()) || (use->GetPosition() == range->GetEnd())); + LocationSummary* locations = use->GetUser()->GetLocations(); + if (use->GetIsEnvironment()) { + locations->SetEnvironmentAt(use->GetInputIndex(), source); } else { - DCHECK(use->GetUser()->IsInvoke()); - DCHECK(use->GetUser()->AsInvoke()->GetIntrinsic() != Intrinsics::kNone); + Location expected_location = locations->InAt(use->GetInputIndex()); + // The expected (actual) location may be invalid in case the input is unused. Currently + // this only happens for intrinsics. + if (expected_location.IsValid()) { + if (expected_location.IsUnallocated()) { + locations->SetInAt(use->GetInputIndex(), source); + } else if (!expected_location.IsConstant()) { + AddInputMoveFor(interval->GetDefinedBy(), use->GetUser(), source, expected_location); + } + } else { + DCHECK(use->GetUser()->IsInvoke()); + DCHECK(use->GetUser()->AsInvoke()->GetIntrinsic() != Intrinsics::kNone); + } } + use = use->GetNext(); } - use = use->GetNext(); + range = range->GetNext(); } // If the next interval starts just after this one, and has a register, @@ -1503,7 +1513,15 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) { } current = next_sibling; } while (current != nullptr); - DCHECK(use == nullptr); + + if (kIsDebugBuild) { + // Following uses can only be environment uses. The location for + // these environments will be none. + while (use != nullptr) { + DCHECK(use->GetIsEnvironment()); + use = use->GetNext(); + } + } } void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval, diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc index 0f3973e5fb..95da6ef551 100644 --- a/compiler/optimizing/ssa_liveness_analysis.cc +++ b/compiler/optimizing/ssa_liveness_analysis.cc @@ -218,28 +218,34 @@ void SsaLivenessAnalysis::ComputeLiveRanges() { current->GetLiveInterval()->SetFrom(current->GetLifetimePosition()); } - // All inputs of an instruction must be live. - for (size_t i = 0, e = current->InputCount(); i < e; ++i) { - HInstruction* input = current->InputAt(i); - // Some instructions 'inline' their inputs, that is they do not need - // to be materialized. - if (input->HasSsaIndex()) { - live_in->SetBit(input->GetSsaIndex()); - input->GetLiveInterval()->AddUse(current, i, false); - } - } - + // Process the environment first, because we know their uses come after + // or at the same liveness position of inputs. if (current->HasEnvironment()) { // Handle environment uses. See statements (b) and (c) of the // SsaLivenessAnalysis. HEnvironment* environment = current->GetEnvironment(); for (size_t i = 0, e = environment->Size(); i < e; ++i) { HInstruction* instruction = environment->GetInstructionAt(i); - if (ShouldBeLiveForEnvironment(instruction)) { + bool should_be_live = ShouldBeLiveForEnvironment(instruction); + if (should_be_live) { DCHECK(instruction->HasSsaIndex()); live_in->SetBit(instruction->GetSsaIndex()); - instruction->GetLiveInterval()->AddUse(current, i, true); } + if (instruction != nullptr) { + instruction->GetLiveInterval()->AddUse( + current, i, /* is_environment */ true, should_be_live); + } + } + } + + // All inputs of an instruction must be live. + for (size_t i = 0, e = current->InputCount(); i < e; ++i) { + HInstruction* input = current->InputAt(i); + // Some instructions 'inline' their inputs, that is they do not need + // to be materialized. + if (input->HasSsaIndex()) { + live_in->SetBit(input->GetSsaIndex()); + input->GetLiveInterval()->AddUse(current, i, /* is_environment */ false); } } } diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index bc78dc2e76..d2da84c0c0 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -189,7 +189,10 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { AddRange(position, position + 1); } - void AddUse(HInstruction* instruction, size_t input_index, bool is_environment) { + void AddUse(HInstruction* instruction, + size_t input_index, + bool is_environment, + bool keep_alive = false) { // Set the use within the instruction. size_t position = instruction->GetLifetimePosition() + 1; LocationSummary* locations = instruction->GetLocations(); @@ -211,6 +214,7 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { && (first_use_->GetPosition() < position)) { // The user uses the instruction multiple times, and one use dies before the other. // We update the use list so that the latter is first. + DCHECK(!is_environment); UsePosition* cursor = first_use_; while ((cursor->GetNext() != nullptr) && (cursor->GetNext()->GetPosition() < position)) { cursor = cursor->GetNext(); @@ -225,6 +229,15 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { return; } + first_use_ = new (allocator_) UsePosition( + instruction, input_index, is_environment, position, first_use_); + + if (is_environment && !keep_alive) { + // If this environment use does not keep the instruction live, it does not + // affect the live range of that instruction. + return; + } + size_t start_block_position = instruction->GetBlock()->GetLifetimeStart(); if (first_range_ == nullptr) { // First time we see a use of that interval. @@ -246,8 +259,6 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { // and the check line 205 would succeed. first_range_ = new (allocator_) LiveRange(start_block_position, position, first_range_); } - first_use_ = new (allocator_) UsePosition( - instruction, input_index, is_environment, position, first_use_); } void AddPhiUse(HInstruction* instruction, size_t input_index, HBasicBlock* block) { @@ -425,9 +436,11 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { UsePosition* use = first_use_; size_t end = GetEnd(); while (use != nullptr && use->GetPosition() <= end) { - size_t use_position = use->GetPosition(); - if (use_position > position) { - return use_position; + if (!use->GetIsEnvironment()) { + size_t use_position = use->GetPosition(); + if (use_position > position) { + return use_position; + } } use = use->GetNext(); } |