Remove constant moves after emitting them in parallel resolver.
This fixes the case where a constant move requires a scratch
register. Note that there is no backend that needs this for now,
but X86 might with the move to hard float.
Change-Id: I37f6b8961b48f2cf6fbc0cd281e70d58466d018e
diff --git a/compiler/optimizing/parallel_move_resolver.cc b/compiler/optimizing/parallel_move_resolver.cc
index 1e93ece..b8f5070 100644
--- a/compiler/optimizing/parallel_move_resolver.cc
+++ b/compiler/optimizing/parallel_move_resolver.cc
@@ -37,10 +37,12 @@
// Perform the moves with constant sources.
for (size_t i = 0; i < moves_.Size(); ++i) {
- const MoveOperands& move = *moves_.Get(i);
- if (!move.IsEliminated()) {
- DCHECK(move.GetSource().IsConstant());
+ MoveOperands* move = moves_.Get(i);
+ if (!move->IsEliminated()) {
+ DCHECK(move->GetSource().IsConstant());
EmitMove(i);
+ // Eliminate the move, in case following moves need a scratch register.
+ move->Eliminate();
}
}
diff --git a/compiler/optimizing/parallel_move_resolver.h b/compiler/optimizing/parallel_move_resolver.h
index 309425e..7ec1dd2 100644
--- a/compiler/optimizing/parallel_move_resolver.h
+++ b/compiler/optimizing/parallel_move_resolver.h
@@ -58,6 +58,9 @@
};
bool IsScratchLocation(Location loc);
+
+ // Allocate a scratch register for performing a move. The method will try to use
+ // a register that is the destination of a move, but that move has not been emitted yet.
int AllocateScratchRegister(int blocked, int if_scratch, int register_count, bool* spilled);
// Emit a move.
diff --git a/compiler/optimizing/parallel_move_test.cc b/compiler/optimizing/parallel_move_test.cc
index 62629bc..210f7d7 100644
--- a/compiler/optimizing/parallel_move_test.cc
+++ b/compiler/optimizing/parallel_move_test.cc
@@ -31,9 +31,13 @@
if (!message_.str().empty()) {
message_ << " ";
}
- message_ << "("
- << move->GetSource().reg()
- << " -> "
+ message_ << "(";
+ if (move->GetSource().IsConstant()) {
+ message_ << "C";
+ } else {
+ message_ << move->GetSource().reg();
+ }
+ message_ << " -> "
<< move->GetDestination().reg()
<< ")";
}
@@ -129,4 +133,21 @@
}
}
+TEST(ParallelMoveTest, ConstantLast) {
+ ArenaPool pool;
+ ArenaAllocator allocator(&pool);
+ TestParallelMoveResolver resolver(&allocator);
+ HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
+ moves->AddMove(new (&allocator) MoveOperands(
+ Location::ConstantLocation(new (&allocator) HIntConstant(0)),
+ Location::RegisterLocation(0),
+ nullptr));
+ moves->AddMove(new (&allocator) MoveOperands(
+ Location::RegisterLocation(1),
+ Location::RegisterLocation(2),
+ nullptr));
+ resolver.EmitNativeCode(moves);
+ ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
+}
+
} // namespace art