summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-06-19 17:06:46 +0100
committerNicolas Geoffray <ngeoffray@google.com>2014-06-25 14:12:33 +0100
commitde025a7d90603d58c62b8fd91393f13d8826a7ac (patch)
tree232d9bb31e75d76093352f2771d774991965ffdf /compiler/optimizing
parentb5dc9444777bb027b070d3ff3fcf7a2a3fb7e3dc (diff)
downloadandroid_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.cc38
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.h8
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());