/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "nodes.h" #include "parallel_move_resolver.h" #include "utils/arena_allocator.h" #include "gtest/gtest.h" namespace art { class TestParallelMoveResolver : public ParallelMoveResolver { public: explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {} virtual void EmitMove(size_t index) { MoveOperands* move = moves_.Get(index); if (!message_.str().empty()) { message_ << " "; } message_ << "("; if (move->GetSource().IsConstant()) { message_ << "C"; } else { message_ << move->GetSource().reg(); } message_ << " -> " << move->GetDestination().reg() << ")"; } virtual void EmitSwap(size_t index) { MoveOperands* move = moves_.Get(index); if (!message_.str().empty()) { message_ << " "; } message_ << "(" << move->GetSource().reg() << " <-> " << move->GetDestination().reg() << ")"; } virtual void SpillScratch(int reg ATTRIBUTE_UNUSED) {} virtual void RestoreScratch(int reg ATTRIBUTE_UNUSED) {} std::string GetMessage() const { return message_.str(); } private: std::ostringstream message_; DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver); }; static HParallelMove* BuildParallelMove(ArenaAllocator* allocator, const size_t operands[][2], size_t number_of_moves) { HParallelMove* moves = new (allocator) HParallelMove(allocator); for (size_t i = 0; i < number_of_moves; ++i) { moves->AddMove(new (allocator) MoveOperands( Location::RegisterLocation(operands[i][0]), Location::RegisterLocation(operands[i][1]), nullptr)); } return moves; } TEST(ParallelMoveTest, Dependency) { ArenaPool pool; ArenaAllocator allocator(&pool); { TestParallelMoveResolver resolver(&allocator); static constexpr size_t moves[][2] = {{0, 1}, {1, 2}}; resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves))); ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str()); } { TestParallelMoveResolver resolver(&allocator); static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}}; resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves))); ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str()); } } TEST(ParallelMoveTest, Swap) { ArenaPool pool; ArenaAllocator allocator(&pool); { TestParallelMoveResolver resolver(&allocator); static constexpr size_t moves[][2] = {{0, 1}, {1, 0}}; resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves))); ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str()); } { TestParallelMoveResolver resolver(&allocator); static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}}; resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves))); ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str()); } { TestParallelMoveResolver resolver(&allocator); static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}}; resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves))); ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1)", resolver.GetMessage().c_str()); } { TestParallelMoveResolver resolver(&allocator); static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}, {5, 4}}; resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves))); ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1) (5 -> 4)", resolver.GetMessage().c_str()); } } 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