blob: 817a44b1848bbeb6db9165c970b44df96db19361 [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
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#include "base/arena_allocator.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010018#include "nodes.h"
19#include "parallel_move_resolver.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010020
21#include "gtest/gtest.h"
22
23namespace art {
24
25class TestParallelMoveResolver : public ParallelMoveResolver {
26 public:
27 explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
28
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000029 void Dump(Location location) {
30 if (location.IsConstant()) {
31 message_ << "C";
32 } else if (location.IsPair()) {
33 message_ << location.low() << "," << location.high();
34 } else {
35 message_ << location.reg();
36 }
37 }
38
Alexandre Rames2ed20af2015-03-06 13:55:35 +000039 void EmitMove(size_t index) OVERRIDE {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010040 MoveOperands* move = moves_.Get(index);
41 if (!message_.str().empty()) {
42 message_ << " ";
43 }
Nicolas Geoffray48c310c2015-01-14 10:45:05 +000044 message_ << "(";
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000045 Dump(move->GetSource());
46 message_ << " -> ";
47 Dump(move->GetDestination());
48 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010049 }
50
Alexandre Rames2ed20af2015-03-06 13:55:35 +000051 void EmitSwap(size_t index) OVERRIDE {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010052 MoveOperands* move = moves_.Get(index);
53 if (!message_.str().empty()) {
54 message_ << " ";
55 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000056 message_ << "(";
57 Dump(move->GetSource());
58 message_ << " <-> ";
59 Dump(move->GetDestination());
60 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010061 }
62
Alexandre Rames2ed20af2015-03-06 13:55:35 +000063 void SpillScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
64 void RestoreScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010065
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010066 std::string GetMessage() const {
67 return message_.str();
68 }
69
70 private:
71 std::ostringstream message_;
72
73
74 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver);
75};
76
77static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
78 const size_t operands[][2],
79 size_t number_of_moves) {
80 HParallelMove* moves = new (allocator) HParallelMove(allocator);
81 for (size_t i = 0; i < number_of_moves; ++i) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000082 moves->AddMove(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010083 Location::RegisterLocation(operands[i][0]),
84 Location::RegisterLocation(operands[i][1]),
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000085 nullptr);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010086 }
87 return moves;
88}
89
90TEST(ParallelMoveTest, Dependency) {
91 ArenaPool pool;
92 ArenaAllocator allocator(&pool);
93
94 {
95 TestParallelMoveResolver resolver(&allocator);
96 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
97 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
98 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
99 }
100
101 {
102 TestParallelMoveResolver resolver(&allocator);
103 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
104 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
105 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
106 }
107}
108
109TEST(ParallelMoveTest, Swap) {
110 ArenaPool pool;
111 ArenaAllocator allocator(&pool);
112
113 {
114 TestParallelMoveResolver resolver(&allocator);
115 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
116 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
117 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
118 }
119
120 {
121 TestParallelMoveResolver resolver(&allocator);
122 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
123 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
124 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
125 }
126
127 {
128 TestParallelMoveResolver resolver(&allocator);
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000129 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}};
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100130 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000131 ASSERT_STREQ("(4 <-> 0) (3 <-> 4) (2 <-> 3) (1 <-> 2)", resolver.GetMessage().c_str());
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100132 }
133}
134
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000135TEST(ParallelMoveTest, ConstantLast) {
136 ArenaPool pool;
137 ArenaAllocator allocator(&pool);
138 TestParallelMoveResolver resolver(&allocator);
139 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000140 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000141 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
142 Location::RegisterLocation(0),
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000143 nullptr);
144 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000145 Location::RegisterLocation(1),
146 Location::RegisterLocation(2),
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000147 nullptr);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000148 resolver.EmitNativeCode(moves);
149 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
150}
151
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000152TEST(ParallelMoveTest, Pairs) {
153 ArenaPool pool;
154 ArenaAllocator allocator(&pool);
155
156 {
157 TestParallelMoveResolver resolver(&allocator);
158 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
159 moves->AddMove(
160 Location::RegisterLocation(2),
161 Location::RegisterLocation(4),
162 nullptr);
163 moves->AddMove(
164 Location::RegisterPairLocation(0, 1),
165 Location::RegisterPairLocation(2, 3),
166 nullptr);
167 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000168 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000169 }
170
171 {
172 TestParallelMoveResolver resolver(&allocator);
173 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
174 moves->AddMove(
175 Location::RegisterPairLocation(0, 1),
176 Location::RegisterPairLocation(2, 3),
177 nullptr);
178 moves->AddMove(
179 Location::RegisterLocation(2),
180 Location::RegisterLocation(4),
181 nullptr);
182 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000183 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000184 }
185
186 {
187 TestParallelMoveResolver resolver(&allocator);
188 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
189 moves->AddMove(
190 Location::RegisterPairLocation(0, 1),
191 Location::RegisterPairLocation(2, 3),
192 nullptr);
193 moves->AddMove(
194 Location::RegisterLocation(2),
195 Location::RegisterLocation(0),
196 nullptr);
197 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000198 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
199 }
200 {
201 TestParallelMoveResolver resolver(&allocator);
202 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
203 moves->AddMove(
204 Location::RegisterLocation(2),
205 Location::RegisterLocation(7),
206 nullptr);
207 moves->AddMove(
208 Location::RegisterLocation(7),
209 Location::RegisterLocation(1),
210 nullptr);
211 moves->AddMove(
212 Location::RegisterPairLocation(0, 1),
213 Location::RegisterPairLocation(2, 3),
214 nullptr);
215 resolver.EmitNativeCode(moves);
216 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
217 }
218 {
219 TestParallelMoveResolver resolver(&allocator);
220 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
221 moves->AddMove(
222 Location::RegisterLocation(2),
223 Location::RegisterLocation(7),
224 nullptr);
225 moves->AddMove(
226 Location::RegisterPairLocation(0, 1),
227 Location::RegisterPairLocation(2, 3),
228 nullptr);
229 moves->AddMove(
230 Location::RegisterLocation(7),
231 Location::RegisterLocation(1),
232 nullptr);
233 resolver.EmitNativeCode(moves);
234 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
235 }
236 {
237 TestParallelMoveResolver resolver(&allocator);
238 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
239 moves->AddMove(
240 Location::RegisterPairLocation(0, 1),
241 Location::RegisterPairLocation(2, 3),
242 nullptr);
243 moves->AddMove(
244 Location::RegisterLocation(2),
245 Location::RegisterLocation(7),
246 nullptr);
247 moves->AddMove(
248 Location::RegisterLocation(7),
249 Location::RegisterLocation(1),
250 nullptr);
251 resolver.EmitNativeCode(moves);
252 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
253 }
254 {
255 TestParallelMoveResolver resolver(&allocator);
256 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
257 moves->AddMove(
258 Location::RegisterPairLocation(0, 1),
259 Location::RegisterPairLocation(2, 3),
260 nullptr);
261 moves->AddMove(
262 Location::RegisterPairLocation(2, 3),
263 Location::RegisterPairLocation(0, 1),
264 nullptr);
265 resolver.EmitNativeCode(moves);
266 ASSERT_STREQ("(2,3 <-> 0,1)", resolver.GetMessage().c_str());
267 }
268 {
269 TestParallelMoveResolver resolver(&allocator);
270 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
271 moves->AddMove(
272 Location::RegisterPairLocation(2, 3),
273 Location::RegisterPairLocation(0, 1),
274 nullptr);
275 moves->AddMove(
276 Location::RegisterPairLocation(0, 1),
277 Location::RegisterPairLocation(2, 3),
278 nullptr);
279 resolver.EmitNativeCode(moves);
280 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000281 }
282}
283
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100284} // namespace art