1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "nodes.h"
18 #include "parallel_move_resolver.h"
19 #include "utils/arena_allocator.h"
20
21 #include "gtest/gtest.h"
22
23 namespace art {
24
25 class TestParallelMoveResolver : public ParallelMoveResolver {
26 public:
TestParallelMoveResolver(ArenaAllocator * allocator)27 explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
28
EmitMove(size_t index)29 virtual void EmitMove(size_t index) {
30 MoveOperands* move = moves_.Get(index);
31 if (!message_.str().empty()) {
32 message_ << " ";
33 }
34 message_ << "("
35 << move->GetSource().reg().RegId()
36 << " -> "
37 << move->GetDestination().reg().RegId()
38 << ")";
39 }
40
EmitSwap(size_t index)41 virtual void EmitSwap(size_t index) {
42 MoveOperands* move = moves_.Get(index);
43 if (!message_.str().empty()) {
44 message_ << " ";
45 }
46 message_ << "("
47 << move->GetSource().reg().RegId()
48 << " <-> "
49 << move->GetDestination().reg().RegId()
50 << ")";
51 }
52
SpillScratch(int reg)53 virtual void SpillScratch(int reg) {}
RestoreScratch(int reg)54 virtual void RestoreScratch(int reg) {}
55
GetMessage() const56 std::string GetMessage() const {
57 return message_.str();
58 }
59
60 private:
61 std::ostringstream message_;
62
63
64 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver);
65 };
66
BuildParallelMove(ArenaAllocator * allocator,const size_t operands[][2],size_t number_of_moves)67 static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
68 const size_t operands[][2],
69 size_t number_of_moves) {
70 HParallelMove* moves = new (allocator) HParallelMove(allocator);
71 for (size_t i = 0; i < number_of_moves; ++i) {
72 moves->AddMove(new (allocator) MoveOperands(
73 Location::RegisterLocation(ManagedRegister(operands[i][0])),
74 Location::RegisterLocation(ManagedRegister(operands[i][1]))));
75 }
76 return moves;
77 }
78
TEST(ParallelMoveTest,Dependency)79 TEST(ParallelMoveTest, Dependency) {
80 ArenaPool pool;
81 ArenaAllocator allocator(&pool);
82
83 {
84 TestParallelMoveResolver resolver(&allocator);
85 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
86 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
87 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
88 }
89
90 {
91 TestParallelMoveResolver resolver(&allocator);
92 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
93 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
94 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
95 }
96 }
97
TEST(ParallelMoveTest,Swap)98 TEST(ParallelMoveTest, Swap) {
99 ArenaPool pool;
100 ArenaAllocator allocator(&pool);
101
102 {
103 TestParallelMoveResolver resolver(&allocator);
104 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
105 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
106 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
107 }
108
109 {
110 TestParallelMoveResolver resolver(&allocator);
111 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
112 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
113 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
114 }
115
116 {
117 TestParallelMoveResolver resolver(&allocator);
118 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}};
119 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
120 ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1)", resolver.GetMessage().c_str());
121 }
122
123 {
124 TestParallelMoveResolver resolver(&allocator);
125 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}, {5, 4}};
126 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
127 ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1) (5 -> 4)", resolver.GetMessage().c_str());
128 }
129 }
130
131 } // namespace art
132