blob: 210f7d7f09e617480323159f025f93679cc41e6e [file] [log] [blame]
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001/*
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
23namespace art {
24
25class TestParallelMoveResolver : public ParallelMoveResolver {
26 public:
27 explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
28
29 virtual void EmitMove(size_t index) {
30 MoveOperands* move = moves_.Get(index);
31 if (!message_.str().empty()) {
32 message_ << " ";
33 }
Nicolas Geoffray48c310c2015-01-14 10:45:05 +000034 message_ << "(";
35 if (move->GetSource().IsConstant()) {
36 message_ << "C";
37 } else {
38 message_ << move->GetSource().reg();
39 }
40 message_ << " -> "
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010041 << move->GetDestination().reg()
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010042 << ")";
43 }
44
45 virtual void EmitSwap(size_t index) {
46 MoveOperands* move = moves_.Get(index);
47 if (!message_.str().empty()) {
48 message_ << " ";
49 }
50 message_ << "("
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010051 << move->GetSource().reg()
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010052 << " <-> "
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010053 << move->GetDestination().reg()
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010054 << ")";
55 }
56
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070057 virtual void SpillScratch(int reg ATTRIBUTE_UNUSED) {}
58 virtual void RestoreScratch(int reg ATTRIBUTE_UNUSED) {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010059
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010060 std::string GetMessage() const {
61 return message_.str();
62 }
63
64 private:
65 std::ostringstream message_;
66
67
68 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver);
69};
70
71static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
72 const size_t operands[][2],
73 size_t number_of_moves) {
74 HParallelMove* moves = new (allocator) HParallelMove(allocator);
75 for (size_t i = 0; i < number_of_moves; ++i) {
76 moves->AddMove(new (allocator) MoveOperands(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010077 Location::RegisterLocation(operands[i][0]),
78 Location::RegisterLocation(operands[i][1]),
Nicolas Geoffray740475d2014-09-29 10:33:25 +010079 nullptr));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010080 }
81 return moves;
82}
83
84TEST(ParallelMoveTest, Dependency) {
85 ArenaPool pool;
86 ArenaAllocator allocator(&pool);
87
88 {
89 TestParallelMoveResolver resolver(&allocator);
90 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
91 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
92 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
93 }
94
95 {
96 TestParallelMoveResolver resolver(&allocator);
97 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
98 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
99 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
100 }
101}
102
103TEST(ParallelMoveTest, Swap) {
104 ArenaPool pool;
105 ArenaAllocator allocator(&pool);
106
107 {
108 TestParallelMoveResolver resolver(&allocator);
109 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
110 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
111 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
112 }
113
114 {
115 TestParallelMoveResolver resolver(&allocator);
116 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
117 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
118 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
119 }
120
121 {
122 TestParallelMoveResolver resolver(&allocator);
123 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}};
124 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
125 ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1)", resolver.GetMessage().c_str());
126 }
127
128 {
129 TestParallelMoveResolver resolver(&allocator);
130 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}, {5, 4}};
131 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
132 ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1) (5 -> 4)", resolver.GetMessage().c_str());
133 }
134}
135
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000136TEST(ParallelMoveTest, ConstantLast) {
137 ArenaPool pool;
138 ArenaAllocator allocator(&pool);
139 TestParallelMoveResolver resolver(&allocator);
140 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
141 moves->AddMove(new (&allocator) MoveOperands(
142 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
143 Location::RegisterLocation(0),
144 nullptr));
145 moves->AddMove(new (&allocator) MoveOperands(
146 Location::RegisterLocation(1),
147 Location::RegisterLocation(2),
148 nullptr));
149 resolver.EmitNativeCode(moves);
150 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
151}
152
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100153} // namespace art