blob: be3520116686534210ace2e64c30d4e77bf52454 [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"
David Sehr3215fff2018-04-03 17:10:12 -070018#include "base/malloc_arena_pool.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010019#include "nodes.h"
20#include "parallel_move_resolver.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010021
Zheng Xuad4450e2015-04-17 18:48:56 +080022#include "gtest/gtest-typed-test.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070023#include "gtest/gtest.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010024
25namespace art {
26
Zheng Xuad4450e2015-04-17 18:48:56 +080027constexpr int kScratchRegisterStartIndexForTest = 100;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010028
Zheng Xuad4450e2015-04-17 18:48:56 +080029static void DumpRegisterForTest(std::ostream& os, int reg) {
30 if (reg >= kScratchRegisterStartIndexForTest) {
31 os << "T" << reg - kScratchRegisterStartIndexForTest;
32 } else {
33 os << reg;
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000034 }
Zheng Xuad4450e2015-04-17 18:48:56 +080035}
36
37static void DumpLocationForTest(std::ostream& os, Location location) {
38 if (location.IsConstant()) {
39 os << "C";
40 } else if (location.IsPair()) {
41 DumpRegisterForTest(os, location.low());
42 os << ",";
43 DumpRegisterForTest(os, location.high());
44 } else if (location.IsRegister()) {
45 DumpRegisterForTest(os, location.reg());
46 } else if (location.IsStackSlot()) {
47 os << location.GetStackIndex() << "(sp)";
48 } else {
49 DCHECK(location.IsDoubleStackSlot())<< location;
50 os << "2x" << location.GetStackIndex() << "(sp)";
51 }
52}
53
54class TestParallelMoveResolverWithSwap : public ParallelMoveResolverWithSwap {
55 public:
56 explicit TestParallelMoveResolverWithSwap(ArenaAllocator* allocator)
57 : ParallelMoveResolverWithSwap(allocator) {}
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000058
Alexandre Rames2ed20af2015-03-06 13:55:35 +000059 void EmitMove(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +010060 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 MoveOperands* move = moves_[index];
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010073 if (!message_.str().empty()) {
74 message_ << " ";
75 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000076 message_ << "(";
Zheng Xuad4450e2015-04-17 18:48:56 +080077 DumpLocationForTest(message_, move->GetSource());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000078 message_ << " <-> ";
Zheng Xuad4450e2015-04-17 18:48:56 +080079 DumpLocationForTest(message_, move->GetDestination());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000080 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010081 }
82
Alexandre Rames2ed20af2015-03-06 13:55:35 +000083 void SpillScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
84 void RestoreScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010085
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010086 std::string GetMessage() const {
87 return message_.str();
88 }
89
90 private:
91 std::ostringstream message_;
92
93
Zheng Xuad4450e2015-04-17 18:48:56 +080094 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolverWithSwap);
95};
96
97class TestParallelMoveResolverNoSwap : public ParallelMoveResolverNoSwap {
98 public:
99 explicit TestParallelMoveResolverNoSwap(ArenaAllocator* allocator)
100 : ParallelMoveResolverNoSwap(allocator), scratch_index_(kScratchRegisterStartIndexForTest) {}
101
102 void PrepareForEmitNativeCode() OVERRIDE {
103 scratch_index_ = kScratchRegisterStartIndexForTest;
104 }
105
106 void FinishEmitNativeCode() OVERRIDE {}
107
108 Location AllocateScratchLocationFor(Location::Kind kind) OVERRIDE {
109 if (kind == Location::kStackSlot || kind == Location::kFpuRegister ||
110 kind == Location::kRegister) {
111 kind = Location::kRegister;
112 } else {
113 // Allocate register pair for double stack slot which simulates 32-bit backend's behavior.
114 kind = Location::kRegisterPair;
115 }
116 Location scratch = GetScratchLocation(kind);
117 if (scratch.Equals(Location::NoLocation())) {
118 AddScratchLocation(Location::RegisterLocation(scratch_index_));
119 AddScratchLocation(Location::RegisterLocation(scratch_index_ + 1));
120 AddScratchLocation(Location::RegisterPairLocation(scratch_index_, scratch_index_ + 1));
121 scratch = (kind == Location::kRegister) ? Location::RegisterLocation(scratch_index_)
122 : Location::RegisterPairLocation(scratch_index_, scratch_index_ + 1);
123 scratch_index_ += 2;
124 }
125 return scratch;
126 }
127
128 void FreeScratchLocation(Location loc ATTRIBUTE_UNUSED) OVERRIDE {}
129
130 void EmitMove(size_t index) OVERRIDE {
Vladimir Marko225b6462015-09-28 12:17:40 +0100131 MoveOperands* move = moves_[index];
Zheng Xuad4450e2015-04-17 18:48:56 +0800132 if (!message_.str().empty()) {
133 message_ << " ";
134 }
135 message_ << "(";
136 DumpLocationForTest(message_, move->GetSource());
137 message_ << " -> ";
138 DumpLocationForTest(message_, move->GetDestination());
139 message_ << ")";
140 }
141
142 std::string GetMessage() const {
143 return message_.str();
144 }
145
146 private:
147 std::ostringstream message_;
148
149 int scratch_index_;
150
151 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolverNoSwap);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100152};
153
154static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
155 const size_t operands[][2],
156 size_t number_of_moves) {
157 HParallelMove* moves = new (allocator) HParallelMove(allocator);
158 for (size_t i = 0; i < number_of_moves; ++i) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000159 moves->AddMove(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100160 Location::RegisterLocation(operands[i][0]),
161 Location::RegisterLocation(operands[i][1]),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100162 DataType::Type::kInt32,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000163 nullptr);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100164 }
165 return moves;
166}
167
Zheng Xuad4450e2015-04-17 18:48:56 +0800168template <typename T>
169class ParallelMoveTest : public ::testing::Test {
170 public:
171 static const bool has_swap;
172};
173
174template<> const bool ParallelMoveTest<TestParallelMoveResolverWithSwap>::has_swap = true;
175template<> const bool ParallelMoveTest<TestParallelMoveResolverNoSwap>::has_swap = false;
176
177typedef ::testing::Types<TestParallelMoveResolverWithSwap, TestParallelMoveResolverNoSwap>
178 ParallelMoveResolverTestTypes;
179
180TYPED_TEST_CASE(ParallelMoveTest, ParallelMoveResolverTestTypes);
181
182
183TYPED_TEST(ParallelMoveTest, Dependency) {
David Sehr3215fff2018-04-03 17:10:12 -0700184 MallocArenaPool pool;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100185 ArenaAllocator allocator(&pool);
186
187 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800188 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100189 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
190 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800191 if (TestFixture::has_swap) {
192 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
193 } else {
194 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
195 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100196 }
197
198 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800199 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100200 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
201 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800202 if (TestFixture::has_swap) {
203 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
204 } else {
205 ASSERT_STREQ("(2 -> 3) (1 -> 2) (0 -> 1) (2 -> 4)", resolver.GetMessage().c_str());
206 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100207 }
208}
209
Zheng Xuad4450e2015-04-17 18:48:56 +0800210TYPED_TEST(ParallelMoveTest, Cycle) {
David Sehr3215fff2018-04-03 17:10:12 -0700211 MallocArenaPool pool;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100212 ArenaAllocator allocator(&pool);
213
214 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800215 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100216 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
217 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800218 if (TestFixture::has_swap) {
219 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
220 } else {
221 ASSERT_STREQ("(1 -> T0) (0 -> 1) (T0 -> 0)", resolver.GetMessage().c_str());
222 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100223 }
224
225 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800226 TypeParam resolver(&allocator);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100227 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
228 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800229 if (TestFixture::has_swap) {
230 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
231 } else {
232 ASSERT_STREQ("(1 -> 2) (0 -> 1) (2 -> 0)", resolver.GetMessage().c_str());
233 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100234 }
235
236 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800237 TypeParam resolver(&allocator);
238 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}, {0, 2}};
239 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
240 if (TestFixture::has_swap) {
241 ASSERT_STREQ("(0 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
242 } else {
243 ASSERT_STREQ("(0 -> 2) (1 -> 0) (2 -> 1)", resolver.GetMessage().c_str());
244 }
245 }
246
247 {
248 TypeParam resolver(&allocator);
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000249 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}};
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100250 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Zheng Xuad4450e2015-04-17 18:48:56 +0800251 if (TestFixture::has_swap) {
252 ASSERT_STREQ("(4 <-> 0) (3 <-> 4) (2 <-> 3) (1 <-> 2)", resolver.GetMessage().c_str());
253 } else {
254 ASSERT_STREQ("(4 -> T0) (3 -> 4) (2 -> 3) (1 -> 2) (0 -> 1) (T0 -> 0)",
255 resolver.GetMessage().c_str());
256 }
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100257 }
258}
259
Zheng Xuad4450e2015-04-17 18:48:56 +0800260TYPED_TEST(ParallelMoveTest, ConstantLast) {
David Sehr3215fff2018-04-03 17:10:12 -0700261 MallocArenaPool pool;
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000262 ArenaAllocator allocator(&pool);
Zheng Xuad4450e2015-04-17 18:48:56 +0800263 TypeParam resolver(&allocator);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000264 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000265 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000266 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
267 Location::RegisterLocation(0),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100268 DataType::Type::kInt32,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000269 nullptr);
270 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000271 Location::RegisterLocation(1),
272 Location::RegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100273 DataType::Type::kInt32,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000274 nullptr);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000275 resolver.EmitNativeCode(moves);
276 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
277}
278
Zheng Xuad4450e2015-04-17 18:48:56 +0800279TYPED_TEST(ParallelMoveTest, Pairs) {
David Sehr3215fff2018-04-03 17:10:12 -0700280 MallocArenaPool pool;
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000281 ArenaAllocator allocator(&pool);
282
283 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800284 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000285 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
286 moves->AddMove(
287 Location::RegisterLocation(2),
288 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100289 DataType::Type::kInt32,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000290 nullptr);
291 moves->AddMove(
292 Location::RegisterPairLocation(0, 1),
293 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100294 DataType::Type::kInt64,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000295 nullptr);
296 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000297 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000298 }
299
300 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800301 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000302 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
303 moves->AddMove(
304 Location::RegisterPairLocation(0, 1),
305 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100306 DataType::Type::kInt64,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000307 nullptr);
308 moves->AddMove(
309 Location::RegisterLocation(2),
310 Location::RegisterLocation(4),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100311 DataType::Type::kInt32,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000312 nullptr);
313 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000314 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000315 }
316
317 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800318 TypeParam resolver(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000319 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
320 moves->AddMove(
321 Location::RegisterPairLocation(0, 1),
322 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100323 DataType::Type::kInt64,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000324 nullptr);
325 moves->AddMove(
326 Location::RegisterLocation(2),
327 Location::RegisterLocation(0),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100328 DataType::Type::kInt32,
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000329 nullptr);
330 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800331 if (TestFixture::has_swap) {
332 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
333 } else {
334 ASSERT_STREQ("(2 -> T0) (0,1 -> 2,3) (T0 -> 0)", resolver.GetMessage().c_str());
335 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000336 }
337 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800338 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000339 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
340 moves->AddMove(
341 Location::RegisterLocation(2),
342 Location::RegisterLocation(7),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100343 DataType::Type::kInt32,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000344 nullptr);
345 moves->AddMove(
346 Location::RegisterLocation(7),
347 Location::RegisterLocation(1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100348 DataType::Type::kInt32,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000349 nullptr);
350 moves->AddMove(
351 Location::RegisterPairLocation(0, 1),
352 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100353 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000354 nullptr);
355 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800356 if (TestFixture::has_swap) {
357 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
358 } else {
359 ASSERT_STREQ("(0,1 -> T0,T1) (7 -> 1) (2 -> 7) (T0,T1 -> 2,3)",
360 resolver.GetMessage().c_str());
361 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000362 }
363 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800364 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000365 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
366 moves->AddMove(
367 Location::RegisterLocation(2),
368 Location::RegisterLocation(7),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100369 DataType::Type::kInt32,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000370 nullptr);
371 moves->AddMove(
372 Location::RegisterPairLocation(0, 1),
373 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100374 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000375 nullptr);
376 moves->AddMove(
377 Location::RegisterLocation(7),
378 Location::RegisterLocation(1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100379 DataType::Type::kInt32,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000380 nullptr);
381 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800382 if (TestFixture::has_swap) {
383 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
384 } else {
385 ASSERT_STREQ("(0,1 -> T0,T1) (7 -> 1) (2 -> 7) (T0,T1 -> 2,3)",
386 resolver.GetMessage().c_str());
387 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000388 }
389 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800390 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000391 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
392 moves->AddMove(
393 Location::RegisterPairLocation(0, 1),
394 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100395 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000396 nullptr);
397 moves->AddMove(
398 Location::RegisterLocation(2),
399 Location::RegisterLocation(7),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100400 DataType::Type::kInt32,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000401 nullptr);
402 moves->AddMove(
403 Location::RegisterLocation(7),
404 Location::RegisterLocation(1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100405 DataType::Type::kInt32,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000406 nullptr);
407 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800408 if (TestFixture::has_swap) {
409 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
410 } else {
411 ASSERT_STREQ("(7 -> T0) (2 -> 7) (0,1 -> 2,3) (T0 -> 1)", resolver.GetMessage().c_str());
412 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000413 }
414 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800415 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000416 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
417 moves->AddMove(
418 Location::RegisterPairLocation(0, 1),
419 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100420 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000421 nullptr);
422 moves->AddMove(
423 Location::RegisterPairLocation(2, 3),
424 Location::RegisterPairLocation(0, 1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100425 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000426 nullptr);
427 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800428 if (TestFixture::has_swap) {
429 ASSERT_STREQ("(2,3 <-> 0,1)", resolver.GetMessage().c_str());
430 } else {
431 ASSERT_STREQ("(2,3 -> T0,T1) (0,1 -> 2,3) (T0,T1 -> 0,1)", resolver.GetMessage().c_str());
432 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000433 }
434 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800435 TypeParam resolver(&allocator);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000436 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
437 moves->AddMove(
438 Location::RegisterPairLocation(2, 3),
439 Location::RegisterPairLocation(0, 1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100440 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000441 nullptr);
442 moves->AddMove(
443 Location::RegisterPairLocation(0, 1),
444 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100445 DataType::Type::kInt64,
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000446 nullptr);
447 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800448 if (TestFixture::has_swap) {
449 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
450 } else {
451 ASSERT_STREQ("(0,1 -> T0,T1) (2,3 -> 0,1) (T0,T1 -> 2,3)", resolver.GetMessage().c_str());
452 }
453 }
454}
455
456TYPED_TEST(ParallelMoveTest, MultiCycles) {
David Sehr3215fff2018-04-03 17:10:12 -0700457 MallocArenaPool pool;
Zheng Xuad4450e2015-04-17 18:48:56 +0800458 ArenaAllocator allocator(&pool);
459
460 {
461 TypeParam resolver(&allocator);
462 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}, {2, 3}, {3, 2}};
463 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
464 if (TestFixture::has_swap) {
465 ASSERT_STREQ("(1 <-> 0) (3 <-> 2)", resolver.GetMessage().c_str());
466 } else {
467 ASSERT_STREQ("(1 -> T0) (0 -> 1) (T0 -> 0) (3 -> T0) (2 -> 3) (T0 -> 2)",
468 resolver.GetMessage().c_str());
469 }
470 }
471 {
472 TypeParam resolver(&allocator);
473 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
474 moves->AddMove(
475 Location::RegisterPairLocation(0, 1),
476 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100477 DataType::Type::kInt64,
Zheng Xuad4450e2015-04-17 18:48:56 +0800478 nullptr);
479 moves->AddMove(
480 Location::RegisterLocation(2),
481 Location::RegisterLocation(0),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100482 DataType::Type::kInt32,
Zheng Xuad4450e2015-04-17 18:48:56 +0800483 nullptr);
484 moves->AddMove(
485 Location::RegisterLocation(3),
486 Location::RegisterLocation(1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100487 DataType::Type::kInt32,
Zheng Xuad4450e2015-04-17 18:48:56 +0800488 nullptr);
489 resolver.EmitNativeCode(moves);
490 if (TestFixture::has_swap) {
491 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
492 } else {
493 ASSERT_STREQ("(2 -> T0) (3 -> T1) (0,1 -> 2,3) (T0 -> 0) (T1 -> 1)",
494 resolver.GetMessage().c_str());
495 }
496 }
497 {
498 TypeParam resolver(&allocator);
499 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
500 moves->AddMove(
501 Location::RegisterLocation(2),
502 Location::RegisterLocation(0),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100503 DataType::Type::kInt32,
Zheng Xuad4450e2015-04-17 18:48:56 +0800504 nullptr);
505 moves->AddMove(
506 Location::RegisterLocation(3),
507 Location::RegisterLocation(1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100508 DataType::Type::kInt32,
Zheng Xuad4450e2015-04-17 18:48:56 +0800509 nullptr);
510 moves->AddMove(
511 Location::RegisterPairLocation(0, 1),
512 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100513 DataType::Type::kInt64,
Zheng Xuad4450e2015-04-17 18:48:56 +0800514 nullptr);
515 resolver.EmitNativeCode(moves);
516 if (TestFixture::has_swap) {
517 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
518 } else {
519 ASSERT_STREQ("(3 -> T0) (0,1 -> T2,T3) (T0 -> 1) (2 -> 0) (T2,T3 -> 2,3)",
520 resolver.GetMessage().c_str());
521 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000522 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100523
524 {
525 // Test involving registers used in single context and pair context.
Zheng Xuad4450e2015-04-17 18:48:56 +0800526 TypeParam resolver(&allocator);
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100527 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
528 moves->AddMove(
529 Location::RegisterLocation(10),
530 Location::RegisterLocation(5),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100531 DataType::Type::kInt32,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100532 nullptr);
533 moves->AddMove(
534 Location::RegisterPairLocation(4, 5),
535 Location::DoubleStackSlot(32),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100536 DataType::Type::kInt64,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100537 nullptr);
538 moves->AddMove(
539 Location::DoubleStackSlot(32),
540 Location::RegisterPairLocation(10, 11),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100541 DataType::Type::kInt64,
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100542 nullptr);
543 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800544 if (TestFixture::has_swap) {
545 ASSERT_STREQ("(2x32(sp) <-> 10,11) (4,5 <-> 2x32(sp)) (4 -> 5)", resolver.GetMessage().c_str());
546 } else {
547 ASSERT_STREQ("(2x32(sp) -> T0,T1) (4,5 -> 2x32(sp)) (10 -> 5) (T0,T1 -> 10,11)",
548 resolver.GetMessage().c_str());
549 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100550 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000551}
552
Nicolas Geoffray90218252015-04-15 11:56:51 +0100553// Test that we do 64bits moves before 32bits moves.
Zheng Xuad4450e2015-04-17 18:48:56 +0800554TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves) {
David Sehr3215fff2018-04-03 17:10:12 -0700555 MallocArenaPool pool;
Nicolas Geoffray90218252015-04-15 11:56:51 +0100556 ArenaAllocator allocator(&pool);
557
558 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800559 TypeParam resolver(&allocator);
Nicolas Geoffray90218252015-04-15 11:56:51 +0100560 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
561 moves->AddMove(
562 Location::RegisterLocation(0),
563 Location::RegisterLocation(1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100564 DataType::Type::kInt64,
Nicolas Geoffray90218252015-04-15 11:56:51 +0100565 nullptr);
566 moves->AddMove(
567 Location::RegisterLocation(1),
568 Location::StackSlot(48),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100569 DataType::Type::kInt32,
Nicolas Geoffray90218252015-04-15 11:56:51 +0100570 nullptr);
571 moves->AddMove(
572 Location::StackSlot(48),
573 Location::RegisterLocation(0),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100574 DataType::Type::kInt32,
Nicolas Geoffray90218252015-04-15 11:56:51 +0100575 nullptr);
576 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800577 if (TestFixture::has_swap) {
578 ASSERT_STREQ("(0 <-> 1) (48(sp) <-> 0)", resolver.GetMessage().c_str());
579 } else {
580 ASSERT_STREQ("(48(sp) -> T0) (1 -> 48(sp)) (0 -> 1) (T0 -> 0)",
581 resolver.GetMessage().c_str());
582 }
Nicolas Geoffray90218252015-04-15 11:56:51 +0100583 }
584
585 {
Zheng Xuad4450e2015-04-17 18:48:56 +0800586 TypeParam resolver(&allocator);
Nicolas Geoffray90218252015-04-15 11:56:51 +0100587 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
588 moves->AddMove(
589 Location::RegisterPairLocation(0, 1),
590 Location::RegisterPairLocation(2, 3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100591 DataType::Type::kInt64,
Nicolas Geoffray90218252015-04-15 11:56:51 +0100592 nullptr);
593 moves->AddMove(
594 Location::RegisterPairLocation(2, 3),
595 Location::DoubleStackSlot(32),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100596 DataType::Type::kInt64,
Nicolas Geoffray90218252015-04-15 11:56:51 +0100597 nullptr);
598 moves->AddMove(
599 Location::DoubleStackSlot(32),
600 Location::RegisterPairLocation(0, 1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100601 DataType::Type::kInt64,
Nicolas Geoffray90218252015-04-15 11:56:51 +0100602 nullptr);
603 resolver.EmitNativeCode(moves);
Zheng Xuad4450e2015-04-17 18:48:56 +0800604 if (TestFixture::has_swap) {
605 ASSERT_STREQ("(2x32(sp) <-> 0,1) (2,3 <-> 2x32(sp))", resolver.GetMessage().c_str());
606 } else {
607 ASSERT_STREQ("(2x32(sp) -> T0,T1) (2,3 -> 2x32(sp)) (0,1 -> 2,3) (T0,T1 -> 0,1)",
608 resolver.GetMessage().c_str());
609 }
Nicolas Geoffray90218252015-04-15 11:56:51 +0100610 }
611}
612
Nicolas Geoffray3e3e4a72015-12-17 14:28:35 +0000613TYPED_TEST(ParallelMoveTest, CyclesWith64BitsMoves2) {
David Sehr3215fff2018-04-03 17:10:12 -0700614 MallocArenaPool pool;
Nicolas Geoffray3e3e4a72015-12-17 14:28:35 +0000615 ArenaAllocator allocator(&pool);
616
617 {
618 TypeParam resolver(&allocator);
619 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
620 moves->AddMove(
621 Location::RegisterLocation(0),
622 Location::RegisterLocation(3),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100623 DataType::Type::kInt32,
Nicolas Geoffray3e3e4a72015-12-17 14:28:35 +0000624 nullptr);
625 moves->AddMove(
626 Location::RegisterPairLocation(2, 3),
627 Location::RegisterPairLocation(0, 1),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100628 DataType::Type::kInt64,
Nicolas Geoffray3e3e4a72015-12-17 14:28:35 +0000629 nullptr);
630 moves->AddMove(
631 Location::RegisterLocation(7),
632 Location::RegisterLocation(2),
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100633 DataType::Type::kInt32,
Nicolas Geoffray3e3e4a72015-12-17 14:28:35 +0000634 nullptr);
635 resolver.EmitNativeCode(moves);
636 if (TestFixture::has_swap) {
637 ASSERT_STREQ("(2,3 <-> 0,1) (2 -> 3) (7 -> 2)", resolver.GetMessage().c_str());
638 } else {
639 ASSERT_STREQ("(2,3 -> T0,T1) (0 -> 3) (T0,T1 -> 0,1) (7 -> 2)",
640 resolver.GetMessage().c_str());
641 }
642 }
643}
644
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100645} // namespace art