blob: 7ab41b6ddc7e95c6b814653914d1998e89afc969 [file] [log] [blame]
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "nodes.h"
18#include "parallel_move_resolver.h"
19#include "utils/arena_allocator.h"
20
21#include "gtest/gtest.h"
22
23namespace art {
24
25class TestParallelMoveResolver : public ParallelMoveResolver {
26 public:
27 explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
28
29 virtual void EmitMove(size_t index) {
30 MoveOperands* move = moves_.Get(index);
31 if (!message_.str().empty()) {
32 message_ << " ";
33 }
Nicolas Geoffray48c310c2015-01-14 10:45:05 +000034 message_ << "(";
35 if (move->GetSource().IsConstant()) {
36 message_ << "C";
37 } else {
38 message_ << move->GetSource().reg();
39 }
40 message_ << " -> "
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010041 << move->GetDestination().reg()
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010042 << ")";
43 }
44
45 virtual void EmitSwap(size_t index) {
46 MoveOperands* move = moves_.Get(index);
47 if (!message_.str().empty()) {
48 message_ << " ";
49 }
50 message_ << "("
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010051 << move->GetSource().reg()
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010052 << " <-> "
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010053 << move->GetDestination().reg()
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010054 << ")";
55 }
56
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070057 virtual void SpillScratch(int reg ATTRIBUTE_UNUSED) {}
58 virtual void RestoreScratch(int reg ATTRIBUTE_UNUSED) {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010059
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010060 std::string GetMessage() const {
61 return message_.str();
62 }
63
64 private:
65 std::ostringstream message_;
66
67
68 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver);
69};
70
71static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
72 const size_t operands[][2],
73 size_t number_of_moves) {
74 HParallelMove* moves = new (allocator) HParallelMove(allocator);
75 for (size_t i = 0; i < number_of_moves; ++i) {
76 moves->AddMove(new (allocator) MoveOperands(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010077 Location::RegisterLocation(operands[i][0]),
78 Location::RegisterLocation(operands[i][1]),
Nicolas Geoffray740475d2014-09-29 10:33:25 +010079 nullptr));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010080 }
81 return moves;
82}
83
84TEST(ParallelMoveTest, Dependency) {
85 ArenaPool pool;
86 ArenaAllocator allocator(&pool);
87
88 {
89 TestParallelMoveResolver resolver(&allocator);
90 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
91 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
92 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
93 }
94
95 {
96 TestParallelMoveResolver resolver(&allocator);
97 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
98 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
99 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
100 }
101}
102
103TEST(ParallelMoveTest, Swap) {
104 ArenaPool pool;
105 ArenaAllocator allocator(&pool);
106
107 {
108 TestParallelMoveResolver resolver(&allocator);
109 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
110 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
111 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
112 }
113
114 {
115 TestParallelMoveResolver resolver(&allocator);
116 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
117 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
118 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
119 }
120
121 {
122 TestParallelMoveResolver resolver(&allocator);
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000123 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}};
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100124 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000125 ASSERT_STREQ("(4 <-> 0) (3 <-> 4) (2 <-> 3) (1 <-> 2)", resolver.GetMessage().c_str());
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100126 }
127}
128
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000129TEST(ParallelMoveTest, ConstantLast) {
130 ArenaPool pool;
131 ArenaAllocator allocator(&pool);
132 TestParallelMoveResolver resolver(&allocator);
133 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
134 moves->AddMove(new (&allocator) MoveOperands(
135 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
136 Location::RegisterLocation(0),
137 nullptr));
138 moves->AddMove(new (&allocator) MoveOperands(
139 Location::RegisterLocation(1),
140 Location::RegisterLocation(2),
141 nullptr));
142 resolver.EmitNativeCode(moves);
143 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
144}
145
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100146} // namespace art