From 48c310c431b110f6ab54907da20c4fa39a8f76b8 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Wed, 14 Jan 2015 10:45:05 +0000 Subject: [PATCH] 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 --- compiler/optimizing/parallel_move_resolver.cc | 8 +++++--- compiler/optimizing/parallel_move_resolver.h | 3 +++ compiler/optimizing/parallel_move_test.cc | 27 ++++++++++++++++++++++++--- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/compiler/optimizing/parallel_move_resolver.cc b/compiler/optimizing/parallel_move_resolver.cc index 1e93ece2e..b8f507099 100644 --- a/compiler/optimizing/parallel_move_resolver.cc +++ b/compiler/optimizing/parallel_move_resolver.cc @@ -37,10 +37,12 @@ void ParallelMoveResolver::EmitNativeCode(HParallelMove* parallel_move) { // 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 309425ef4..7ec1dd2de 100644 --- a/compiler/optimizing/parallel_move_resolver.h +++ b/compiler/optimizing/parallel_move_resolver.h @@ -58,6 +58,9 @@ class ParallelMoveResolver : public ValueObject { }; 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 62629bcd0..210f7d7f0 100644 --- a/compiler/optimizing/parallel_move_test.cc +++ b/compiler/optimizing/parallel_move_test.cc @@ -31,9 +31,13 @@ class TestParallelMoveResolver : public ParallelMoveResolver { 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, Swap) { } } +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 -- 2.11.0