Do not update Out after it has a valid location.
Slow paths use LocationSummary to know where to move
things around, and they are executed at the end of the
code generation.
This fix is needed for https://android-review.googlesource.com/#/c/113345/.
Change-Id: Id336c6409479b1de6dc839b736a7234d08a7774a
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index c75980d..0dfbad2 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -281,16 +281,22 @@
HInstruction* previous = instruction->GetPrevious();
Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
Move(previous, temp_location, instruction);
- previous->GetLocations()->SetOut(temp_location);
}
return;
}
AllocateRegistersLocally(instruction);
for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
Location location = instruction->GetLocations()->InAt(i);
+ HInstruction* input = instruction->InputAt(i);
if (location.IsValid()) {
// Move the input to the desired location.
- Move(instruction->InputAt(i), location, instruction);
+ if (input->GetNext()->IsTemporary()) {
+ // If the input was stored in a temporary, use that temporary to
+ // perform the move.
+ Move(input->GetNext(), location, instruction);
+ } else {
+ Move(input, location, instruction);
+ }
}
}
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index a031ce3..91b28c4 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -766,6 +766,9 @@
default:
LOG(FATAL) << "Unexpected type " << instruction->GetType();
}
+ } else if (instruction->IsTemporary()) {
+ Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
+ Move32(location, temp_location);
} else {
DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
switch (instruction->GetType()) {
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 1be5717..e84346b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -413,7 +413,9 @@
__ Mov(temp, value);
__ Str(temp, StackOperandFrom(location));
}
-
+ } else if (instruction->IsTemporary()) {
+ Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
+ MoveHelper(location, temp_location, type);
} else if (instruction->IsLoadLocal()) {
uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
switch (type) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 54a12fd..129c374 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -623,6 +623,9 @@
DCHECK(location.IsConstant());
DCHECK_EQ(location.GetConstant(), instruction);
}
+ } else if (instruction->IsTemporary()) {
+ Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
+ Move32(location, temp_location);
} else if (instruction->IsLoadLocal()) {
int slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
switch (instruction->GetType()) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 9237cc3..efe1ef2 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -559,6 +559,9 @@
default:
LOG(FATAL) << "Unexpected local type " << instruction->GetType();
}
+ } else if (instruction->IsTemporary()) {
+ Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
+ Move(location, temp_location);
} else {
DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
switch (instruction->GetType()) {
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index bed688b..d1555d4 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -417,6 +417,7 @@
LocationSummary(HInstruction* instruction, CallKind call_kind = kNoCall);
void SetInAt(uint32_t at, Location location) {
+ DCHECK(inputs_.Get(at).IsUnallocated() || inputs_.Get(at).IsInvalid());
inputs_.Put(at, location);
}
@@ -429,8 +430,17 @@
}
void SetOut(Location location, bool overlaps = true) {
+ DCHECK(output_.IsUnallocated() || output_.IsInvalid());
output_overlaps_ = overlaps;
- output_ = Location(location);
+ output_ = location;
+ }
+
+ void UpdateOut(Location location) {
+ // The only reason for updating an output is for parameters where
+ // we only know the exact stack slot after doing full register
+ // allocation.
+ DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot());
+ output_ = location;
}
void AddTemp(Location location) {
@@ -442,6 +452,7 @@
}
void SetTempAt(uint32_t at, Location location) {
+ DCHECK(temps_.Get(at).IsUnallocated() || temps_.Get(at).IsInvalid());
temps_.Put(at, location);
}
@@ -528,6 +539,8 @@
// Registers that are in use at this position.
RegisterSet live_registers_;
+ ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
+ ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
DISALLOW_COPY_AND_ASSIGN(LocationSummary);
};
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 37e5e6b..47ed8df 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2088,6 +2088,8 @@
size_t GetIndex() const { return index_; }
+ Primitive::Type GetType() const OVERRIDE { return GetPrevious()->GetType(); }
+
DECLARE_INSTRUCTION(Temporary);
private:
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 0745f9c..4a9deea 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -1164,11 +1164,11 @@
if (location.IsStackSlot()) {
location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
current->SetSpillSlot(location.GetStackIndex());
- locations->SetOut(location);
+ locations->UpdateOut(location);
} else if (location.IsDoubleStackSlot()) {
location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
current->SetSpillSlot(location.GetStackIndex());
- locations->SetOut(location);
+ locations->UpdateOut(location);
} else if (current->HasSpillSlot()) {
current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
}
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index 9b1a121..3d81362 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -622,7 +622,8 @@
liveness.Analyze();
// Check that the field gets put in the register expected by its use.
- ret->GetLocations()->SetInAt(0, Location::RegisterLocation(2));
+ // Don't use SetInAt because we are overriding an already allocated location.
+ ret->GetLocations()->inputs_.Put(0, Location::RegisterLocation(2));
RegisterAllocator register_allocator(&allocator, &codegen, liveness);
register_allocator.AllocateRegisters();
@@ -684,7 +685,8 @@
liveness.Analyze();
// check that both adds get the same register.
- first_add->InputAt(0)->GetLocations()->SetOut(Location::RegisterLocation(2));
+ // Don't use SetOutput because output is already allocated.
+ first_add->InputAt(0)->GetLocations()->output_ = Location::RegisterLocation(2);
ASSERT_EQ(first_add->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput);
ASSERT_EQ(second_add->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput);