blob: 5c502f7ef43da9dbc0f80c01a1e1db0f98cf9e9a [file] [log] [blame]
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#include "base/arena_allocator.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010018#include "nodes.h"
19#include "parallel_move_resolver.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010020
21#include "gtest/gtest.h"
22
23namespace art {
24
25class TestParallelMoveResolver : public ParallelMoveResolver {
26 public:
27 explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
28
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000029 void Dump(Location location) {
30 if (location.IsConstant()) {
31 message_ << "C";
32 } else if (location.IsPair()) {
33 message_ << location.low() << "," << location.high();
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +010034 } else if (location.IsRegister()) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000035 message_ << location.reg();
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +010036 } else if (location.IsStackSlot()) {
37 message_ << location.GetStackIndex() << "(sp)";
38 } else {
39 message_ << "2x" << location.GetStackIndex() << "(sp)";
40 DCHECK(location.IsDoubleStackSlot()) << location;
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000041 }
42 }
43
Alexandre Rames2ed20af2015-03-06 13:55:35 +000044 void EmitMove(size_t index) OVERRIDE {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010045 MoveOperands* move = moves_.Get(index);
46 if (!message_.str().empty()) {
47 message_ << " ";
48 }
Nicolas Geoffray48c310c2015-01-14 10:45:05 +000049 message_ << "(";
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000050 Dump(move->GetSource());
51 message_ << " -> ";
52 Dump(move->GetDestination());
53 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010054 }
55
Alexandre Rames2ed20af2015-03-06 13:55:35 +000056 void EmitSwap(size_t index) OVERRIDE {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010057 MoveOperands* move = moves_.Get(index);
58 if (!message_.str().empty()) {
59 message_ << " ";
60 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000061 message_ << "(";
62 Dump(move->GetSource());
63 message_ << " <-> ";
64 Dump(move->GetDestination());
65 message_ << ")";
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010066 }
67
Alexandre Rames2ed20af2015-03-06 13:55:35 +000068 void SpillScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
69 void RestoreScratch(int reg ATTRIBUTE_UNUSED) OVERRIDE {}
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010070
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010071 std::string GetMessage() const {
72 return message_.str();
73 }
74
75 private:
76 std::ostringstream message_;
77
78
79 DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver);
80};
81
82static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
83 const size_t operands[][2],
84 size_t number_of_moves) {
85 HParallelMove* moves = new (allocator) HParallelMove(allocator);
86 for (size_t i = 0; i < number_of_moves; ++i) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000087 moves->AddMove(
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010088 Location::RegisterLocation(operands[i][0]),
89 Location::RegisterLocation(operands[i][1]),
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +000090 nullptr);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010091 }
92 return moves;
93}
94
95TEST(ParallelMoveTest, Dependency) {
96 ArenaPool pool;
97 ArenaAllocator allocator(&pool);
98
99 {
100 TestParallelMoveResolver resolver(&allocator);
101 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
102 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
103 ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
104 }
105
106 {
107 TestParallelMoveResolver resolver(&allocator);
108 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
109 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
110 ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
111 }
112}
113
114TEST(ParallelMoveTest, Swap) {
115 ArenaPool pool;
116 ArenaAllocator allocator(&pool);
117
118 {
119 TestParallelMoveResolver resolver(&allocator);
120 static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
121 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
122 ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
123 }
124
125 {
126 TestParallelMoveResolver resolver(&allocator);
127 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
128 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
129 ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
130 }
131
132 {
133 TestParallelMoveResolver resolver(&allocator);
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000134 static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}};
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100135 resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
Nicolas Geoffray6450d142015-01-16 09:04:49 +0000136 ASSERT_STREQ("(4 <-> 0) (3 <-> 4) (2 <-> 3) (1 <-> 2)", resolver.GetMessage().c_str());
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100137 }
138}
139
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000140TEST(ParallelMoveTest, ConstantLast) {
141 ArenaPool pool;
142 ArenaAllocator allocator(&pool);
143 TestParallelMoveResolver resolver(&allocator);
144 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000145 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000146 Location::ConstantLocation(new (&allocator) HIntConstant(0)),
147 Location::RegisterLocation(0),
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000148 nullptr);
149 moves->AddMove(
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000150 Location::RegisterLocation(1),
151 Location::RegisterLocation(2),
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000152 nullptr);
Nicolas Geoffray48c310c2015-01-14 10:45:05 +0000153 resolver.EmitNativeCode(moves);
154 ASSERT_STREQ("(1 -> 2) (C -> 0)", resolver.GetMessage().c_str());
155}
156
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000157TEST(ParallelMoveTest, Pairs) {
158 ArenaPool pool;
159 ArenaAllocator allocator(&pool);
160
161 {
162 TestParallelMoveResolver resolver(&allocator);
163 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
164 moves->AddMove(
165 Location::RegisterLocation(2),
166 Location::RegisterLocation(4),
167 nullptr);
168 moves->AddMove(
169 Location::RegisterPairLocation(0, 1),
170 Location::RegisterPairLocation(2, 3),
171 nullptr);
172 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000173 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000174 }
175
176 {
177 TestParallelMoveResolver resolver(&allocator);
178 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
179 moves->AddMove(
180 Location::RegisterPairLocation(0, 1),
181 Location::RegisterPairLocation(2, 3),
182 nullptr);
183 moves->AddMove(
184 Location::RegisterLocation(2),
185 Location::RegisterLocation(4),
186 nullptr);
187 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000188 ASSERT_STREQ("(2 -> 4) (0,1 -> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000189 }
190
191 {
192 TestParallelMoveResolver resolver(&allocator);
193 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
194 moves->AddMove(
195 Location::RegisterPairLocation(0, 1),
196 Location::RegisterPairLocation(2, 3),
197 nullptr);
198 moves->AddMove(
199 Location::RegisterLocation(2),
200 Location::RegisterLocation(0),
201 nullptr);
202 resolver.EmitNativeCode(moves);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000203 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
204 }
205 {
206 TestParallelMoveResolver resolver(&allocator);
207 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
208 moves->AddMove(
209 Location::RegisterLocation(2),
210 Location::RegisterLocation(7),
211 nullptr);
212 moves->AddMove(
213 Location::RegisterLocation(7),
214 Location::RegisterLocation(1),
215 nullptr);
216 moves->AddMove(
217 Location::RegisterPairLocation(0, 1),
218 Location::RegisterPairLocation(2, 3),
219 nullptr);
220 resolver.EmitNativeCode(moves);
221 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
222 }
223 {
224 TestParallelMoveResolver resolver(&allocator);
225 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
226 moves->AddMove(
227 Location::RegisterLocation(2),
228 Location::RegisterLocation(7),
229 nullptr);
230 moves->AddMove(
231 Location::RegisterPairLocation(0, 1),
232 Location::RegisterPairLocation(2, 3),
233 nullptr);
234 moves->AddMove(
235 Location::RegisterLocation(7),
236 Location::RegisterLocation(1),
237 nullptr);
238 resolver.EmitNativeCode(moves);
239 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
240 }
241 {
242 TestParallelMoveResolver resolver(&allocator);
243 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
244 moves->AddMove(
245 Location::RegisterPairLocation(0, 1),
246 Location::RegisterPairLocation(2, 3),
247 nullptr);
248 moves->AddMove(
249 Location::RegisterLocation(2),
250 Location::RegisterLocation(7),
251 nullptr);
252 moves->AddMove(
253 Location::RegisterLocation(7),
254 Location::RegisterLocation(1),
255 nullptr);
256 resolver.EmitNativeCode(moves);
257 ASSERT_STREQ("(0,1 <-> 2,3) (7 -> 1) (0 -> 7)", resolver.GetMessage().c_str());
258 }
259 {
260 TestParallelMoveResolver resolver(&allocator);
261 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
262 moves->AddMove(
263 Location::RegisterPairLocation(0, 1),
264 Location::RegisterPairLocation(2, 3),
265 nullptr);
266 moves->AddMove(
267 Location::RegisterPairLocation(2, 3),
268 Location::RegisterPairLocation(0, 1),
269 nullptr);
270 resolver.EmitNativeCode(moves);
271 ASSERT_STREQ("(2,3 <-> 0,1)", resolver.GetMessage().c_str());
272 }
273 {
274 TestParallelMoveResolver resolver(&allocator);
275 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
276 moves->AddMove(
277 Location::RegisterPairLocation(2, 3),
278 Location::RegisterPairLocation(0, 1),
279 nullptr);
280 moves->AddMove(
281 Location::RegisterPairLocation(0, 1),
282 Location::RegisterPairLocation(2, 3),
283 nullptr);
284 resolver.EmitNativeCode(moves);
285 ASSERT_STREQ("(0,1 <-> 2,3)", resolver.GetMessage().c_str());
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000286 }
Nicolas Geoffraya2d15b52015-03-31 18:13:51 +0100287
288 {
289 // Test involving registers used in single context and pair context.
290 TestParallelMoveResolver resolver(&allocator);
291 HParallelMove* moves = new (&allocator) HParallelMove(&allocator);
292 moves->AddMove(
293 Location::RegisterLocation(10),
294 Location::RegisterLocation(5),
295 nullptr);
296 moves->AddMove(
297 Location::RegisterPairLocation(4, 5),
298 Location::DoubleStackSlot(32),
299 nullptr);
300 moves->AddMove(
301 Location::DoubleStackSlot(32),
302 Location::RegisterPairLocation(10, 11),
303 nullptr);
304 resolver.EmitNativeCode(moves);
305 ASSERT_STREQ("(2x32(sp) <-> 10,11) (4,5 <-> 2x32(sp)) (4 -> 5)", resolver.GetMessage().c_str());
306 }
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +0000307}
308
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100309} // namespace art