blob: da91cb811d0fc22c641b4616aed7d0a26ca642d3 [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"
Zheng Xuad4450e2015-04-17 18:48:56 +080022#include "gtest/gtest-typed-test.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010023
24namespace art {
25
Zheng Xuad4450e2015-04-17 18:48:56 +080026constexpr int kScratchRegisterStartIndexForTest = 100;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010027
Zheng Xuad4450e2015-04-17 18:48:56 +080028static void DumpRegisterForTest(std::ostream& os, int reg) {
29 if (reg >= kScratchRegisterStartIndexForTest) {
30 os << "T" << reg - kScratchRegisterStartIndexForTest;
31 } else {
32 os << reg;
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000033 }
Zheng Xuad4450e2015-04-17 18:48:56 +080034}
35
36static void DumpLocationForTest(std::ostream& os, Location location) {
37 if (location.IsConstant()) {
38 os << "C";
39 } else if (location.IsPair()) {
40 DumpRegisterForTest(os, location.low());
41 os << ",";
42 DumpRegisterForTest(os, location.high());
43 } else if (location.IsRegister()) {
44 DumpRegisterForTest(os, location.reg());
45 } else if (location.IsStackSlot()) {
46 os << location.GetStackIndex() << "(sp)";
47 } else {
48 DCHECK(location.IsDoubleStackSlot())<< location;
49 os << "2x" << location.GetStackIndex() << "(sp)";
50 }
51}
52
53class TestParallelMoveResolverWithSwap : public ParallelMoveResolverWithSwap {
54 public:
55 explicit TestParallelMoveResolverWithSwap(ArenaAllocator* allocator)
56 : ParallelMoveResolverWithSwap(allocator) {}
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000057
Alexandre Rames2ed20af2015-03-06 13:55:35 +000058 void EmitMove(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +010059 DCHECK_LT(index, moves_.size());
60 MoveOperands* move = moves_[index];
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010061 if (!message_.str().empty()) {
62 message_ << " ";
63 }
Nicolas Geoffray48c310c2015-01-14 10:45:05 +000064 message_ << "(";
Zheng Xuad4450e2015-04-17 18:48:56 +080065 DumpLocationForTest(message_, move->GetSource());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000066 message_ << " -> ";
Zheng Xuad4450e2015-04-17 18:48:56 +080067 DumpLocationForTest(message_, move->GetDestination());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000068 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010069 }
70
Alexandre Rames2ed20af2015-03-06 13:55:35 +000071 void EmitSwap(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +010072 DCHECK_LT(index, moves_.size());
73 MoveOperands* move = moves_[index];
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010074 if (!message_.str().empty()) {
75 message_ << " ";
76 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000077 message_ << "(";
Zheng Xuad4450e2015-04-17 18:48:56 +080078 DumpLocationForTest(message_, move->GetSource());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000079 message_ << " <-> ";
Zheng Xuad4450e2015-04-17 18:48:56 +080080 DumpLocationForTest(message_, move->GetDestination());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000081 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010082 }
83
Alexandre Rames2ed20af2015-03-06 13:55:35 +000084 void SpillScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
85 void RestoreScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010086
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010087 std::string GetMessage() const {
88 return message_.str();
89 }
90
91 private:
92 std::ostringstream message_;
93
94
Zheng Xuad4450e2015-04-17 18:48:56 +080095 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolverWithSwap);
96};
97
98class TestParallelMoveResolverNoSwap : public ParallelMoveResolverNoSwap {
99 public:
100 explicit TestParallelMoveResolverNoSwap(ArenaAllocator* allocator)
101 : ParallelMoveResolverNoSwap(allocator), scratch_index_(kScratchRegisterStartIndexForTest) {}
102
103 void PrepareForEmitNativeCode() OVERRIDE {
104 scratch_index_ = kScratchRegisterStartIndexForTest;
105 }
106
107 void FinishEmitNativeCode() OVERRIDE {}
108
109 Location AllocateScratchLocationFor(Location::Kind kind) OVERRIDE {
110 if (kind == Location::kStackSlot || kind == Location::kFpuRegister ||
111 kind == Location::kRegister) {
112 kind = Location::kRegister;
113 } else {
114 // Allocate register pair for double stack slot which simulates 32-bit backend's behavior.
115 kind = Location::kRegisterPair;
116 }
117 Location scratch = GetScratchLocation(kind);
118 if (scratch.Equals(Location::NoLocation())) {
119 AddScratchLocation(Location::RegisterLocation(scratch_index_));
120 AddScratchLocation(Location::RegisterLocation(scratch_index_ + 1));
121 AddScratchLocation(Location::RegisterPairLocation(scratch_index_, scratch_index_ + 1));
122 scratch = (kind == Location::kRegister) ? Location::RegisterLocation(scratch_index_)
123 : Location::RegisterPairLocation(scratch_index_, scratch_index_ + 1);
124 scratch_index_ += 2;
125 }
126 return scratch;
127 }
128
129 void FreeScratchLocation(Location loc ATTRIBUTE_UNUSED) OVERRIDE {}
130
131 void EmitMove(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +0100132 DCHECK_LT(index, moves_.size());
133 MoveOperands* move = moves_[index];
Zheng Xuad4450e2015-04-17 18:48:56 +0800134 if (!message_.str().empty()) {
135 message_ << " ";
136 }
137 message_ << "(";
138 DumpLocationForTest(message_, move->GetSource());
139 message_ << " -> ";
140 DumpLocationForTest(message_, move->GetDestination());
141 message_ << ")";
142 }
143
144 std::string GetMessage() const {
145 return message_.str();
146 }
147
148 private:
149 std::ostringstream message_;
150
151 int scratch_index_;
152
153 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolverNoSwap);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100154};
155
156static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
157 const size_t operands[][2],
158 size_t number_of_moves) {
159 HParallelMove* moves = new (allocator) HParallelMove(allocator);
160 for (size_t i = 0; i < number_of_moves; ++i) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000161 moves->AddMove(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100162 Location::RegisterLocation(operands[i][0]),
163 Location::RegisterLocation(operands[i][1]),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100164 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000165 nullptr);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100166 }
167 return moves;
168}
169
Zheng Xuad4450e2015-04-17 18:48:56 +0800170template <typename T>
171class ParallelMoveTest : public ::testing::Test {
172 public:
173 static const bool has_swap;
174};
175
176template<> const bool ParallelMoveTest<TestParallelMoveResolverWithSwap>::has_swap = true;
177template<> const bool ParallelMoveTest<TestParallelMoveResolverNoSwap>::has_swap = false;
178
179typedef ::testing::Types<TestParallelMoveResolverWithSwap, TestParallelMoveResolverNoSwap>
180 ParallelMoveResolverTestTypes;
181
182TYPED_TEST_CASE(ParallelMoveTest, ParallelMoveResolverTestTypes);
183
184
185TYPED_TEST(ParallelMoveTest, Dependency) {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100186 ArenaPool pool;
187 ArenaAllocator allocator(&pool);
188
189 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800190 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100191 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
192 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800193 if (TestFixture::has_swap) {
194 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
195 } else {
196 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
197 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100198 }
199
200 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800201 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100202 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
203 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800204 if (TestFixture::has_swap) {
205 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
206 } else {
207 ASSERT_STREQ("(2 -> 3) (1 -> 2) (0 -> 1) (2 -> 4)", resolver.GetMessage().c_str());
208 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100209 }
210}
211
Zheng Xuad4450e2015-04-17 18:48:56 +0800212TYPED_TEST(ParallelMoveTest, Cycle) {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100213 ArenaPool pool;
214 ArenaAllocator allocator(&pool);
215
216 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800217 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100218 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
219 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800220 if (TestFixture::has_swap) {
221 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
222 } else {
223 ASSERT_STREQ("(1 -> T0) (0 -> 1) (T0 -> 0)", resolver.GetMessage().c_str());
224 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100225 }
226
227 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800228 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100229 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
230 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800231 if (TestFixture::has_swap) {
232 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
233 } else {
234 ASSERT_STREQ("(1 -> 2) (0 -> 1) (2 -> 0)", resolver.GetMessage().c_str());
235 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100236 }
237
238 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800239 TypeParam resolver(&allocator);
240 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}, {0, 2}};
241 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
242 if (TestFixture::has_swap) {
243 ASSERT_STREQ("(0 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
244 } else {
245 ASSERT_STREQ("(0 -> 2) (1 -> 0) (2 -> 1)", resolver.GetMessage().c_str());
246 }
247 }
248
249 {
250 TypeParam resolver(&allocator);
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000251 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}};
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100252 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800253 if (TestFixture::has_swap) {
254 ASSERT_STREQ("(4 <-> 0) (3 <-> 4) (2 <-> 3) (1 <-> 2)", resolver.GetMessage().c_str());
255 } else {
256 ASSERT_STREQ("(4 -> T0) (3 -> 4) (2 -> 3) (1 -> 2) (0 -> 1) (T0 -> 0)",
257 resolver.GetMessage().c_str());
258 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100259 }
260}
261
Zheng Xuad4450e2015-04-17 18:48:56 +0800262TYPED_TEST(ParallelMoveTest, ConstantLast) {
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000263 ArenaPool pool;
264 ArenaAllocator allocator(&pool);
Zheng Xuad4450e2015-04-17 18:48:56 +0800265 TypeParam resolver(&allocator);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000266 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000267 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000268 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
269 Location::RegisterLocation(0),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100270 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000271 nullptr);
272 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000273 Location::RegisterLocation(1),
274 Location::RegisterLocation(2),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100275 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000276 nullptr);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000277 resolver.EmitNativeCode(moves);
278 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
279}
280
Zheng Xuad4450e2015-04-17 18:48:56 +0800281TYPED_TEST(ParallelMoveTest, Pairs) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000282 ArenaPool pool;
283 ArenaAllocator allocator(&pool);
284
285 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800286 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000287 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
288 moves->AddMove(
289 Location::RegisterLocation(2),
290 Location::RegisterLocation(4),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100291 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000292 nullptr);
293 moves->AddMove(
294 Location::RegisterPairLocation(0, 1),
295 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100296 Primitive::kPrimLong,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000297 nullptr);
298 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000299 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000300 }
301
302 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800303 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000304 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
305 moves->AddMove(
306 Location::RegisterPairLocation(0, 1),
307 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100308 Primitive::kPrimLong,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000309 nullptr);
310 moves->AddMove(
311 Location::RegisterLocation(2),
312 Location::RegisterLocation(4),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100313 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000314 nullptr);
315 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000316 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000317 }
318
319 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800320 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000321 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
322 moves->AddMove(
323 Location::RegisterPairLocation(0, 1),
324 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100325 Primitive::kPrimLong,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000326 nullptr);
327 moves->AddMove(
328 Location::RegisterLocation(2),
329 Location::RegisterLocation(0),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100330 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000331 nullptr);
332 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800333 if (TestFixture::has_swap) {
334 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
335 } else {
336 ASSERT_STREQ("(2 -> T0) (0,1 -> 2,3) (T0 -> 0)", resolver.GetMessage().c_str());
337 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000338 }
339 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800340 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000341 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
342 moves->AddMove(
343 Location::RegisterLocation(2),
344 Location::RegisterLocation(7),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100345 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000346 nullptr);
347 moves->AddMove(
348 Location::RegisterLocation(7),
349 Location::RegisterLocation(1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100350 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000351 nullptr);
352 moves->AddMove(
353 Location::RegisterPairLocation(0, 1),
354 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100355 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000356 nullptr);
357 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800358 if (TestFixture::has_swap) {
359 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
360 } else {
361 ASSERT_STREQ("(0,1 -> T0,T1) (7 -> 1) (2 -> 7) (T0,T1 -> 2,3)",
362 resolver.GetMessage().c_str());
363 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000364 }
365 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800366 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000367 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
368 moves->AddMove(
369 Location::RegisterLocation(2),
370 Location::RegisterLocation(7),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100371 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000372 nullptr);
373 moves->AddMove(
374 Location::RegisterPairLocation(0, 1),
375 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100376 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000377 nullptr);
378 moves->AddMove(
379 Location::RegisterLocation(7),
380 Location::RegisterLocation(1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100381 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000382 nullptr);
383 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800384 if (TestFixture::has_swap) {
385 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
386 } else {
387 ASSERT_STREQ("(0,1 -> T0,T1) (7 -> 1) (2 -> 7) (T0,T1 -> 2,3)",
388 resolver.GetMessage().c_str());
389 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000390 }
391 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800392 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000393 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
394 moves->AddMove(
395 Location::RegisterPairLocation(0, 1),
396 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100397 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000398 nullptr);
399 moves->AddMove(
400 Location::RegisterLocation(2),
401 Location::RegisterLocation(7),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100402 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000403 nullptr);
404 moves->AddMove(
405 Location::RegisterLocation(7),
406 Location::RegisterLocation(1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100407 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000408 nullptr);
409 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800410 if (TestFixture::has_swap) {
411 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
412 } else {
413 ASSERT_STREQ("(7 -> T0) (2 -> 7) (0,1 -> 2,3) (T0 -> 1)", resolver.GetMessage().c_str());
414 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000415 }
416 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800417 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000418 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
419 moves->AddMove(
420 Location::RegisterPairLocation(0, 1),
421 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100422 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000423 nullptr);
424 moves->AddMove(
425 Location::RegisterPairLocation(2, 3),
426 Location::RegisterPairLocation(0, 1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100427 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000428 nullptr);
429 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800430 if (TestFixture::has_swap) {
431 ASSERT_STREQ("(2,3 <-> 0,1)", resolver.GetMessage().c_str());
432 } else {
433 ASSERT_STREQ("(2,3 -> T0,T1) (0,1 -> 2,3) (T0,T1 -> 0,1)", resolver.GetMessage().c_str());
434 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000435 }
436 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800437 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000438 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
439 moves->AddMove(
440 Location::RegisterPairLocation(2, 3),
441 Location::RegisterPairLocation(0, 1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100442 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000443 nullptr);
444 moves->AddMove(
445 Location::RegisterPairLocation(0, 1),
446 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100447 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000448 nullptr);
449 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800450 if (TestFixture::has_swap) {
451 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
452 } else {
453 ASSERT_STREQ("(0,1 -> T0,T1) (2,3 -> 0,1) (T0,T1 -> 2,3)", resolver.GetMessage().c_str());
454 }
455 }
456}
457
458TYPED_TEST(ParallelMoveTest, MultiCycles) {
459 ArenaPool pool;
460 ArenaAllocator allocator(&pool);
461
462 {
463 TypeParam resolver(&allocator);
464 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}, {2, 3}, {3, 2}};
465 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
466 if (TestFixture::has_swap) {
467 ASSERT_STREQ("(1 <-> 0) (3 <-> 2)", resolver.GetMessage().c_str());
468 } else {
469 ASSERT_STREQ("(1 -> T0) (0 -> 1) (T0 -> 0) (3 -> T0) (2 -> 3) (T0 -> 2)",
470 resolver.GetMessage().c_str());
471 }
472 }
473 {
474 TypeParam resolver(&allocator);
475 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
476 moves->AddMove(
477 Location::RegisterPairLocation(0, 1),
478 Location::RegisterPairLocation(2, 3),
479 Primitive::kPrimLong,
480 nullptr);
481 moves->AddMove(
482 Location::RegisterLocation(2),
483 Location::RegisterLocation(0),
484 Primitive::kPrimInt,
485 nullptr);
486 moves->AddMove(
487 Location::RegisterLocation(3),
488 Location::RegisterLocation(1),
489 Primitive::kPrimInt,
490 nullptr);
491 resolver.EmitNativeCode(moves);
492 if (TestFixture::has_swap) {
493 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
494 } else {
495 ASSERT_STREQ("(2 -> T0) (3 -> T1) (0,1 -> 2,3) (T0 -> 0) (T1 -> 1)",
496 resolver.GetMessage().c_str());
497 }
498 }
499 {
500 TypeParam resolver(&allocator);
501 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
502 moves->AddMove(
503 Location::RegisterLocation(2),
504 Location::RegisterLocation(0),
505 Primitive::kPrimInt,
506 nullptr);
507 moves->AddMove(
508 Location::RegisterLocation(3),
509 Location::RegisterLocation(1),
510 Primitive::kPrimInt,
511 nullptr);
512 moves->AddMove(
513 Location::RegisterPairLocation(0, 1),
514 Location::RegisterPairLocation(2, 3),
515 Primitive::kPrimLong,
516 nullptr);
517 resolver.EmitNativeCode(moves);
518 if (TestFixture::has_swap) {
519 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
520 } else {
521 ASSERT_STREQ("(3 -> T0) (0,1 -> T2,T3) (T0 -> 1) (2 -> 0) (T2,T3 -> 2,3)",
522 resolver.GetMessage().c_str());
523 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000524 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100525
526 {
527 // Test involving registers used in single context and pair context.
Zheng Xuad4450e2015-04-17 18:48:56 +0800528 TypeParam resolver(&allocator);
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100529 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
530 moves->AddMove(
531 Location::RegisterLocation(10),
532 Location::RegisterLocation(5),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100533 Primitive::kPrimInt,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100534 nullptr);
535 moves->AddMove(
536 Location::RegisterPairLocation(4, 5),
537 Location::DoubleStackSlot(32),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100538 Primitive::kPrimLong,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100539 nullptr);
540 moves->AddMove(
541 Location::DoubleStackSlot(32),
542 Location::RegisterPairLocation(10, 11),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100543 Primitive::kPrimLong,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100544 nullptr);
545 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800546 if (TestFixture::has_swap) {
547 ASSERT_STREQ("(2x32(sp) <-> 10,11) (4,5 <-> 2x32(sp)) (4 -> 5)", resolver.GetMessage().c_str());
548 } else {
549 ASSERT_STREQ("(2x32(sp) -> T0,T1) (4,5 -> 2x32(sp)) (10 -> 5) (T0,T1 -> 10,11)",
550 resolver.GetMessage().c_str());
551 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100552 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000553}
554
Nicolas Geoffray90218252015-04-15 11:56:51 +0100555// Test that we do 64bits moves before 32bits moves.
Zheng Xuad4450e2015-04-17 18:48:56 +0800556TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) {
Nicolas Geoffray90218252015-04-15 11:56:51 +0100557 ArenaPool pool;
558 ArenaAllocator allocator(&pool);
559
560 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800561 TypeParam resolver(&allocator);
Nicolas Geoffray90218252015-04-15 11:56:51 +0100562 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
563 moves->AddMove(
564 Location::RegisterLocation(0),
565 Location::RegisterLocation(1),
566 Primitive::kPrimLong,
567 nullptr);
568 moves->AddMove(
569 Location::RegisterLocation(1),
570 Location::StackSlot(48),
571 Primitive::kPrimInt,
572 nullptr);
573 moves->AddMove(
574 Location::StackSlot(48),
575 Location::RegisterLocation(0),
576 Primitive::kPrimInt,
577 nullptr);
578 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800579 if (TestFixture::has_swap) {
580 ASSERT_STREQ("(0 <-> 1) (48(sp) <-> 0)", resolver.GetMessage().c_str());
581 } else {
582 ASSERT_STREQ("(48(sp) -> T0) (1 -> 48(sp)) (0 -> 1) (T0 -> 0)",
583 resolver.GetMessage().c_str());
584 }
Nicolas Geoffray90218252015-04-15 11:56:51 +0100585 }
586
587 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800588 TypeParam resolver(&allocator);
Nicolas Geoffray90218252015-04-15 11:56:51 +0100589 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
590 moves->AddMove(
591 Location::RegisterPairLocation(0, 1),
592 Location::RegisterPairLocation(2, 3),
593 Primitive::kPrimLong,
594 nullptr);
595 moves->AddMove(
596 Location::RegisterPairLocation(2, 3),
597 Location::DoubleStackSlot(32),
598 Primitive::kPrimLong,
599 nullptr);
600 moves->AddMove(
601 Location::DoubleStackSlot(32),
602 Location::RegisterPairLocation(0, 1),
603 Primitive::kPrimLong,
604 nullptr);
605 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800606 if (TestFixture::has_swap) {
607 ASSERT_STREQ("(2x32(sp) <-> 0,1) (2,3 <-> 2x32(sp))", resolver.GetMessage().c_str());
608 } else {
609 ASSERT_STREQ("(2x32(sp) -> T0,T1) (2,3 -> 2x32(sp)) (0,1 -> 2,3) (T0,T1 -> 0,1)",
610 resolver.GetMessage().c_str());
611 }
Nicolas Geoffray90218252015-04-15 11:56:51 +0100612 }
613}
614
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100615} // namespace art