diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-06-19 17:06:46 +0100 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-06-25 14:12:33 +0100 |
commit | de025a7d90603d58c62b8fd91393f13d8826a7ac (patch) | |
tree | 232d9bb31e75d76093352f2771d774991965ffdf /compiler/optimizing | |
parent | b5dc9444777bb027b070d3ff3fcf7a2a3fb7e3dc (diff) | |
download | android_art-de025a7d90603d58c62b8fd91393f13d8826a7ac.tar.gz android_art-de025a7d90603d58c62b8fd91393f13d8826a7ac.tar.bz2 android_art-de025a7d90603d58c62b8fd91393f13d8826a7ac.zip |
Fix a bug in LiveInterval::FirstRegisterUseAfter.
Since the use list is shared amongst siblings, we must stop looking
for the user once we have reached the end position of the current
interval. The next uses are for the next sibling.
Change-Id: Ibba180161e94a705e2034abd0b95a29347950257
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/register_allocator_test.cc | 38 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.h | 8 |
2 files changed, 43 insertions, 3 deletions
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc index bfabc5ad27..a7283ab329 100644 --- a/compiler/optimizing/register_allocator_test.cc +++ b/compiler/optimizing/register_allocator_test.cc @@ -318,4 +318,42 @@ TEST(RegisterAllocatorTest, Loop3) { ASSERT_EQ(phi_interval->GetRegister(), ret->InputAt(0)->GetLiveInterval()->GetRegister()); } +TEST(RegisterAllocatorTest, FirstRegisterUse) { + const uint16_t data[] = THREE_REGISTERS_CODE_ITEM( + Instruction::CONST_4 | 0 | 0, + Instruction::ADD_INT_LIT8 | 1 << 8, 1 << 8, + Instruction::ADD_INT_LIT8 | 0 << 8, 1 << 8, + Instruction::ADD_INT_LIT8 | 1 << 8, 1 << 8 | 1, + Instruction::RETURN_VOID); + + ArenaPool pool; + ArenaAllocator allocator(&pool); + HGraph* graph = BuildSSAGraph(data, &allocator); + CodeGenerator* codegen = CodeGenerator::Create(&allocator, graph, kArm); + SsaLivenessAnalysis liveness(*graph, codegen); + liveness.Analyze(); + + HAdd* first_add = graph->GetBlocks().Get(1)->GetFirstInstruction()->AsAdd(); + HAdd* last_add = graph->GetBlocks().Get(1)->GetLastInstruction()->GetPrevious()->AsAdd(); + ASSERT_EQ(last_add->InputAt(0), first_add); + LiveInterval* interval = first_add->GetLiveInterval(); + ASSERT_EQ(interval->GetEnd(), last_add->GetLifetimePosition() + 1); + ASSERT_TRUE(interval->GetNextSibling() == nullptr); + + // We need a register for the output of the instruction. + ASSERT_EQ(interval->FirstRegisterUse(), first_add->GetLifetimePosition()); + + // Split at the next instruction. + interval = interval->SplitAt(first_add->GetLifetimePosition() + 2); + // The user of the split is the last add. + ASSERT_EQ(interval->FirstRegisterUse(), last_add->GetLifetimePosition() + 1); + + // Split before the last add. + LiveInterval* new_interval = interval->SplitAt(last_add->GetLifetimePosition() - 1); + // Ensure the current interval has no register use... + ASSERT_EQ(interval->FirstRegisterUse(), kNoLifetime); + // And the new interval has it for the last add. + ASSERT_EQ(new_interval->FirstRegisterUse(), last_add->GetLifetimePosition() + 1); +} + } // namespace art diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index fc3eb660d5..83035b52f6 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -289,21 +289,23 @@ class LiveInterval : public ArenaObject { size_t FirstRegisterUseAfter(size_t position) const { if (position == GetStart() && defined_by_ != nullptr) { - Location location = defined_by_->GetLocations()->Out(); + LocationSummary* locations = defined_by_->GetLocations(); + Location location = locations->Out(); // This interval is the first interval of the instruction. If the output // of the instruction requires a register, we return the position of that instruction // as the first register use. if (location.IsUnallocated()) { if ((location.GetPolicy() == Location::kRequiresRegister) || (location.GetPolicy() == Location::kSameAsFirstInput - && defined_by_->GetLocations()->InAt(0).GetPolicy() == Location::kRequiresRegister)) { + && locations->InAt(0).GetPolicy() == Location::kRequiresRegister)) { return position; } } } UsePosition* use = first_use_; - while (use != nullptr) { + size_t end = GetEnd(); + while (use != nullptr && use->GetPosition() <= end) { size_t use_position = use->GetPosition(); if (use_position >= position && !use->GetIsEnvironment()) { Location location = use->GetUser()->GetLocations()->InAt(use->GetInputIndex()); |