blob: 5e8fe37669f6b50e510a15e66b6471fb69c3a001 [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 MoveOperands* move = moves_[index];
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010060 if (!message_.str().empty()) {
61 message_ << " ";
62 }
Nicolas Geoffray48c310c2015-01-14 10:45:05 +000063 message_ << "(";
Zheng Xuad4450e2015-04-17 18:48:56 +080064 DumpLocationForTest(message_, move->GetSource());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000065 message_ << " -> ";
Zheng Xuad4450e2015-04-17 18:48:56 +080066 DumpLocationForTest(message_, move->GetDestination());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000067 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010068 }
69
Alexandre Rames2ed20af2015-03-06 13:55:35 +000070 void EmitSwap(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +010071 MoveOperands* move = moves_[index];
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010072 if (!message_.str().empty()) {
73 message_ << " ";
74 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000075 message_ << "(";
Zheng Xuad4450e2015-04-17 18:48:56 +080076 DumpLocationForTest(message_, move->GetSource());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000077 message_ << " <-> ";
Zheng Xuad4450e2015-04-17 18:48:56 +080078 DumpLocationForTest(message_, move->GetDestination());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000079 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010080 }
81
Alexandre Rames2ed20af2015-03-06 13:55:35 +000082 void SpillScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
83 void RestoreScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010084
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010085 std::string GetMessage() const {
86 return message_.str();
87 }
88
89 private:
90 std::ostringstream message_;
91
92
Zheng Xuad4450e2015-04-17 18:48:56 +080093 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolverWithSwap);
94};
95
96class TestParallelMoveResolverNoSwap : public ParallelMoveResolverNoSwap {
97 public:
98 explicit TestParallelMoveResolverNoSwap(ArenaAllocator* allocator)
99 : ParallelMoveResolverNoSwap(allocator), scratch_index_(kScratchRegisterStartIndexForTest) {}
100
101 void PrepareForEmitNativeCode() OVERRIDE {
102 scratch_index_ = kScratchRegisterStartIndexForTest;
103 }
104
105 void FinishEmitNativeCode() OVERRIDE {}
106
107 Location AllocateScratchLocationFor(Location::Kind kind) OVERRIDE {
108 if (kind == Location::kStackSlot || kind == Location::kFpuRegister ||
109 kind == Location::kRegister) {
110 kind = Location::kRegister;
111 } else {
112 // Allocate register pair for double stack slot which simulates 32-bit backend's behavior.
113 kind = Location::kRegisterPair;
114 }
115 Location scratch = GetScratchLocation(kind);
116 if (scratch.Equals(Location::NoLocation())) {
117 AddScratchLocation(Location::RegisterLocation(scratch_index_));
118 AddScratchLocation(Location::RegisterLocation(scratch_index_ + 1));
119 AddScratchLocation(Location::RegisterPairLocation(scratch_index_, scratch_index_ + 1));
120 scratch = (kind == Location::kRegister) ? Location::RegisterLocation(scratch_index_)
121 : Location::RegisterPairLocation(scratch_index_, scratch_index_ + 1);
122 scratch_index_ += 2;
123 }
124 return scratch;
125 }
126
127 void FreeScratchLocation(Location loc ATTRIBUTE_UNUSED) OVERRIDE {}
128
129 void EmitMove(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +0100130 MoveOperands* move = moves_[index];
Zheng Xuad4450e2015-04-17 18:48:56 +0800131 if (!message_.str().empty()) {
132 message_ << " ";
133 }
134 message_ << "(";
135 DumpLocationForTest(message_, move->GetSource());
136 message_ << " -> ";
137 DumpLocationForTest(message_, move->GetDestination());
138 message_ << ")";
139 }
140
141 std::string GetMessage() const {
142 return message_.str();
143 }
144
145 private:
146 std::ostringstream message_;
147
148 int scratch_index_;
149
150 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolverNoSwap);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100151};
152
153static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
154 const size_t operands[][2],
155 size_t number_of_moves) {
156 HParallelMove* moves = new (allocator) HParallelMove(allocator);
157 for (size_t i = 0; i < number_of_moves; ++i) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000158 moves->AddMove(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100159 Location::RegisterLocation(operands[i][0]),
160 Location::RegisterLocation(operands[i][1]),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100161 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000162 nullptr);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100163 }
164 return moves;
165}
166
Zheng Xuad4450e2015-04-17 18:48:56 +0800167template <typename T>
168class ParallelMoveTest : public ::testing::Test {
169 public:
170 static const bool has_swap;
171};
172
173template<> const bool ParallelMoveTest<TestParallelMoveResolverWithSwap>::has_swap = true;
174template<> const bool ParallelMoveTest<TestParallelMoveResolverNoSwap>::has_swap = false;
175
176typedef ::testing::Types<TestParallelMoveResolverWithSwap, TestParallelMoveResolverNoSwap>
177 ParallelMoveResolverTestTypes;
178
179TYPED_TEST_CASE(ParallelMoveTest, ParallelMoveResolverTestTypes);
180
181
182TYPED_TEST(ParallelMoveTest, Dependency) {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100183 ArenaPool pool;
184 ArenaAllocator allocator(&pool);
185
186 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800187 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100188 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
189 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800190 if (TestFixture::has_swap) {
191 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
192 } else {
193 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
194 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100195 }
196
197 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800198 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100199 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
200 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800201 if (TestFixture::has_swap) {
202 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
203 } else {
204 ASSERT_STREQ("(2 -> 3) (1 -> 2) (0 -> 1) (2 -> 4)", resolver.GetMessage().c_str());
205 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100206 }
207}
208
Zheng Xuad4450e2015-04-17 18:48:56 +0800209TYPED_TEST(ParallelMoveTest, Cycle) {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100210 ArenaPool pool;
211 ArenaAllocator allocator(&pool);
212
213 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800214 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100215 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
216 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800217 if (TestFixture::has_swap) {
218 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
219 } else {
220 ASSERT_STREQ("(1 -> T0) (0 -> 1) (T0 -> 0)", resolver.GetMessage().c_str());
221 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100222 }
223
224 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800225 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100226 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
227 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800228 if (TestFixture::has_swap) {
229 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
230 } else {
231 ASSERT_STREQ("(1 -> 2) (0 -> 1) (2 -> 0)", resolver.GetMessage().c_str());
232 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100233 }
234
235 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800236 TypeParam resolver(&allocator);
237 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}, {0, 2}};
238 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
239 if (TestFixture::has_swap) {
240 ASSERT_STREQ("(0 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
241 } else {
242 ASSERT_STREQ("(0 -> 2) (1 -> 0) (2 -> 1)", resolver.GetMessage().c_str());
243 }
244 }
245
246 {
247 TypeParam resolver(&allocator);
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000248 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}};
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100249 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800250 if (TestFixture::has_swap) {
251 ASSERT_STREQ("(4 <-> 0) (3 <-> 4) (2 <-> 3) (1 <-> 2)", resolver.GetMessage().c_str());
252 } else {
253 ASSERT_STREQ("(4 -> T0) (3 -> 4) (2 -> 3) (1 -> 2) (0 -> 1) (T0 -> 0)",
254 resolver.GetMessage().c_str());
255 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100256 }
257}
258
Zheng Xuad4450e2015-04-17 18:48:56 +0800259TYPED_TEST(ParallelMoveTest, ConstantLast) {
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000260 ArenaPool pool;
261 ArenaAllocator allocator(&pool);
Zheng Xuad4450e2015-04-17 18:48:56 +0800262 TypeParam resolver(&allocator);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000263 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000264 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000265 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
266 Location::RegisterLocation(0),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100267 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000268 nullptr);
269 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000270 Location::RegisterLocation(1),
271 Location::RegisterLocation(2),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100272 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000273 nullptr);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000274 resolver.EmitNativeCode(moves);
275 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
276}
277
Zheng Xuad4450e2015-04-17 18:48:56 +0800278TYPED_TEST(ParallelMoveTest, Pairs) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000279 ArenaPool pool;
280 ArenaAllocator allocator(&pool);
281
282 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800283 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000284 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
285 moves->AddMove(
286 Location::RegisterLocation(2),
287 Location::RegisterLocation(4),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100288 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000289 nullptr);
290 moves->AddMove(
291 Location::RegisterPairLocation(0, 1),
292 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100293 Primitive::kPrimLong,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000294 nullptr);
295 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000296 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000297 }
298
299 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800300 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000301 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
302 moves->AddMove(
303 Location::RegisterPairLocation(0, 1),
304 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100305 Primitive::kPrimLong,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000306 nullptr);
307 moves->AddMove(
308 Location::RegisterLocation(2),
309 Location::RegisterLocation(4),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100310 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000311 nullptr);
312 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000313 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000314 }
315
316 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800317 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000318 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
319 moves->AddMove(
320 Location::RegisterPairLocation(0, 1),
321 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100322 Primitive::kPrimLong,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000323 nullptr);
324 moves->AddMove(
325 Location::RegisterLocation(2),
326 Location::RegisterLocation(0),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100327 Primitive::kPrimInt,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000328 nullptr);
329 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800330 if (TestFixture::has_swap) {
331 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
332 } else {
333 ASSERT_STREQ("(2 -> T0) (0,1 -> 2,3) (T0 -> 0)", resolver.GetMessage().c_str());
334 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000335 }
336 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800337 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000338 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
339 moves->AddMove(
340 Location::RegisterLocation(2),
341 Location::RegisterLocation(7),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100342 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000343 nullptr);
344 moves->AddMove(
345 Location::RegisterLocation(7),
346 Location::RegisterLocation(1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100347 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000348 nullptr);
349 moves->AddMove(
350 Location::RegisterPairLocation(0, 1),
351 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100352 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000353 nullptr);
354 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800355 if (TestFixture::has_swap) {
356 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
357 } else {
358 ASSERT_STREQ("(0,1 -> T0,T1) (7 -> 1) (2 -> 7) (T0,T1 -> 2,3)",
359 resolver.GetMessage().c_str());
360 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000361 }
362 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800363 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000364 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
365 moves->AddMove(
366 Location::RegisterLocation(2),
367 Location::RegisterLocation(7),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100368 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000369 nullptr);
370 moves->AddMove(
371 Location::RegisterPairLocation(0, 1),
372 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100373 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000374 nullptr);
375 moves->AddMove(
376 Location::RegisterLocation(7),
377 Location::RegisterLocation(1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100378 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000379 nullptr);
380 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800381 if (TestFixture::has_swap) {
382 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
383 } else {
384 ASSERT_STREQ("(0,1 -> T0,T1) (7 -> 1) (2 -> 7) (T0,T1 -> 2,3)",
385 resolver.GetMessage().c_str());
386 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000387 }
388 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800389 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000390 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
391 moves->AddMove(
392 Location::RegisterPairLocation(0, 1),
393 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100394 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000395 nullptr);
396 moves->AddMove(
397 Location::RegisterLocation(2),
398 Location::RegisterLocation(7),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100399 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000400 nullptr);
401 moves->AddMove(
402 Location::RegisterLocation(7),
403 Location::RegisterLocation(1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100404 Primitive::kPrimInt,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000405 nullptr);
406 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800407 if (TestFixture::has_swap) {
408 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
409 } else {
410 ASSERT_STREQ("(7 -> T0) (2 -> 7) (0,1 -> 2,3) (T0 -> 1)", resolver.GetMessage().c_str());
411 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000412 }
413 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800414 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000415 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
416 moves->AddMove(
417 Location::RegisterPairLocation(0, 1),
418 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100419 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000420 nullptr);
421 moves->AddMove(
422 Location::RegisterPairLocation(2, 3),
423 Location::RegisterPairLocation(0, 1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100424 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000425 nullptr);
426 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800427 if (TestFixture::has_swap) {
428 ASSERT_STREQ("(2,3 <-> 0,1)", resolver.GetMessage().c_str());
429 } else {
430 ASSERT_STREQ("(2,3 -> T0,T1) (0,1 -> 2,3) (T0,T1 -> 0,1)", resolver.GetMessage().c_str());
431 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000432 }
433 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800434 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000435 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
436 moves->AddMove(
437 Location::RegisterPairLocation(2, 3),
438 Location::RegisterPairLocation(0, 1),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100439 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000440 nullptr);
441 moves->AddMove(
442 Location::RegisterPairLocation(0, 1),
443 Location::RegisterPairLocation(2, 3),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100444 Primitive::kPrimLong,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000445 nullptr);
446 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800447 if (TestFixture::has_swap) {
448 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
449 } else {
450 ASSERT_STREQ("(0,1 -> T0,T1) (2,3 -> 0,1) (T0,T1 -> 2,3)", resolver.GetMessage().c_str());
451 }
452 }
453}
454
455TYPED_TEST(ParallelMoveTest, MultiCycles) {
456 ArenaPool pool;
457 ArenaAllocator allocator(&pool);
458
459 {
460 TypeParam resolver(&allocator);
461 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}, {2, 3}, {3, 2}};
462 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
463 if (TestFixture::has_swap) {
464 ASSERT_STREQ("(1 <-> 0) (3 <-> 2)", resolver.GetMessage().c_str());
465 } else {
466 ASSERT_STREQ("(1 -> T0) (0 -> 1) (T0 -> 0) (3 -> T0) (2 -> 3) (T0 -> 2)",
467 resolver.GetMessage().c_str());
468 }
469 }
470 {
471 TypeParam resolver(&allocator);
472 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
473 moves->AddMove(
474 Location::RegisterPairLocation(0, 1),
475 Location::RegisterPairLocation(2, 3),
476 Primitive::kPrimLong,
477 nullptr);
478 moves->AddMove(
479 Location::RegisterLocation(2),
480 Location::RegisterLocation(0),
481 Primitive::kPrimInt,
482 nullptr);
483 moves->AddMove(
484 Location::RegisterLocation(3),
485 Location::RegisterLocation(1),
486 Primitive::kPrimInt,
487 nullptr);
488 resolver.EmitNativeCode(moves);
489 if (TestFixture::has_swap) {
490 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
491 } else {
492 ASSERT_STREQ("(2 -> T0) (3 -> T1) (0,1 -> 2,3) (T0 -> 0) (T1 -> 1)",
493 resolver.GetMessage().c_str());
494 }
495 }
496 {
497 TypeParam resolver(&allocator);
498 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
499 moves->AddMove(
500 Location::RegisterLocation(2),
501 Location::RegisterLocation(0),
502 Primitive::kPrimInt,
503 nullptr);
504 moves->AddMove(
505 Location::RegisterLocation(3),
506 Location::RegisterLocation(1),
507 Primitive::kPrimInt,
508 nullptr);
509 moves->AddMove(
510 Location::RegisterPairLocation(0, 1),
511 Location::RegisterPairLocation(2, 3),
512 Primitive::kPrimLong,
513 nullptr);
514 resolver.EmitNativeCode(moves);
515 if (TestFixture::has_swap) {
516 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
517 } else {
518 ASSERT_STREQ("(3 -> T0) (0,1 -> T2,T3) (T0 -> 1) (2 -> 0) (T2,T3 -> 2,3)",
519 resolver.GetMessage().c_str());
520 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000521 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100522
523 {
524 // Test involving registers used in single context and pair context.
Zheng Xuad4450e2015-04-17 18:48:56 +0800525 TypeParam resolver(&allocator);
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100526 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
527 moves->AddMove(
528 Location::RegisterLocation(10),
529 Location::RegisterLocation(5),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100530 Primitive::kPrimInt,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100531 nullptr);
532 moves->AddMove(
533 Location::RegisterPairLocation(4, 5),
534 Location::DoubleStackSlot(32),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100535 Primitive::kPrimLong,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100536 nullptr);
537 moves->AddMove(
538 Location::DoubleStackSlot(32),
539 Location::RegisterPairLocation(10, 11),
Nicolas Geoffray90218252015-04-15 11:56:51 +0100540 Primitive::kPrimLong,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100541 nullptr);
542 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800543 if (TestFixture::has_swap) {
544 ASSERT_STREQ("(2x32(sp) <-> 10,11) (4,5 <-> 2x32(sp)) (4 -> 5)", resolver.GetMessage().c_str());
545 } else {
546 ASSERT_STREQ("(2x32(sp) -> T0,T1) (4,5 -> 2x32(sp)) (10 -> 5) (T0,T1 -> 10,11)",
547 resolver.GetMessage().c_str());
548 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100549 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000550}
551
Nicolas Geoffray90218252015-04-15 11:56:51 +0100552// Test that we do 64bits moves before 32bits moves.
Zheng Xuad4450e2015-04-17 18:48:56 +0800553TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) {
Nicolas Geoffray90218252015-04-15 11:56:51 +0100554 ArenaPool pool;
555 ArenaAllocator allocator(&pool);
556
557 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800558 TypeParam resolver(&allocator);
Nicolas Geoffray90218252015-04-15 11:56:51 +0100559 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
560 moves->AddMove(
561 Location::RegisterLocation(0),
562 Location::RegisterLocation(1),
563 Primitive::kPrimLong,
564 nullptr);
565 moves->AddMove(
566 Location::RegisterLocation(1),
567 Location::StackSlot(48),
568 Primitive::kPrimInt,
569 nullptr);
570 moves->AddMove(
571 Location::StackSlot(48),
572 Location::RegisterLocation(0),
573 Primitive::kPrimInt,
574 nullptr);
575 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800576 if (TestFixture::has_swap) {
577 ASSERT_STREQ("(0 <-> 1) (48(sp) <-> 0)", resolver.GetMessage().c_str());
578 } else {
579 ASSERT_STREQ("(48(sp) -> T0) (1 -> 48(sp)) (0 -> 1) (T0 -> 0)",
580 resolver.GetMessage().c_str());
581 }
Nicolas Geoffray90218252015-04-15 11:56:51 +0100582 }
583
584 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800585 TypeParam resolver(&allocator);
Nicolas Geoffray90218252015-04-15 11:56:51 +0100586 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
587 moves->AddMove(
588 Location::RegisterPairLocation(0, 1),
589 Location::RegisterPairLocation(2, 3),
590 Primitive::kPrimLong,
591 nullptr);
592 moves->AddMove(
593 Location::RegisterPairLocation(2, 3),
594 Location::DoubleStackSlot(32),
595 Primitive::kPrimLong,
596 nullptr);
597 moves->AddMove(
598 Location::DoubleStackSlot(32),
599 Location::RegisterPairLocation(0, 1),
600 Primitive::kPrimLong,
601 nullptr);
602 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800603 if (TestFixture::has_swap) {
604 ASSERT_STREQ("(2x32(sp) <-> 0,1) (2,3 <-> 2x32(sp))", resolver.GetMessage().c_str());
605 } else {
606 ASSERT_STREQ("(2x32(sp) -> T0,T1) (2,3 -> 2x32(sp)) (0,1 -> 2,3) (T0,T1 -> 0,1)",
607 resolver.GetMessage().c_str());
608 }
Nicolas Geoffray90218252015-04-15 11:56:51 +0100609 }
610}
611
Nicolas Geoffray3e3e4a72015-12-17 14:28:35 +0000612TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves2) {
613 ArenaPool pool;
614 ArenaAllocator allocator(&pool);
615
616 {
617 TypeParam resolver(&allocator);
618 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
619 moves->AddMove(
620 Location::RegisterLocation(0),
621 Location::RegisterLocation(3),
622 Primitive::kPrimInt,
623 nullptr);
624 moves->AddMove(
625 Location::RegisterPairLocation(2, 3),
626 Location::RegisterPairLocation(0, 1),
627 Primitive::kPrimLong,
628 nullptr);
629 moves->AddMove(
630 Location::RegisterLocation(7),
631 Location::RegisterLocation(2),
632 Primitive::kPrimInt,
633 nullptr);
634 resolver.EmitNativeCode(moves);
635 if (TestFixture::has_swap) {
636 ASSERT_STREQ("(2,3 <-> 0,1) (2 -> 3) (7 -> 2)", resolver.GetMessage().c_str());
637 } else {
638 ASSERT_STREQ("(2,3 -> T0,T1) (0 -> 3) (T0,T1 -> 0,1) (7 -> 2)",
639 resolver.GetMessage().c_str());
640 }
641 }
642}
643
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100644} // namespace art