1 /*
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 
23 namespace art {
24 
25 class TestParallelMoveResolver : public ParallelMoveResolver {
26  public:
TestParallelMoveResolver(ArenaAllocator * allocator)27   explicit TestParallelMoveResolver(ArenaAllocator* allocator) : ParallelMoveResolver(allocator) {}
28 
EmitMove(size_t index)29   virtual void EmitMove(size_t index) {
30     MoveOperands* move = moves_.Get(index);
31     if (!message_.str().empty()) {
32       message_ << " ";
33     }
34     message_ << "("
35              << move->GetSource().reg().RegId()
36              << " -> "
37              << move->GetDestination().reg().RegId()
38              << ")";
39   }
40 
EmitSwap(size_t index)41   virtual void EmitSwap(size_t index) {
42     MoveOperands* move = moves_.Get(index);
43     if (!message_.str().empty()) {
44       message_ << " ";
45     }
46     message_ << "("
47              << move->GetSource().reg().RegId()
48              << " <-> "
49              << move->GetDestination().reg().RegId()
50              << ")";
51   }
52 
SpillScratch(int reg)53   virtual void SpillScratch(int reg) {}
RestoreScratch(int reg)54   virtual void RestoreScratch(int reg) {}
55 
GetMessage() const56   std::string GetMessage() const {
57     return  message_.str();
58   }
59 
60  private:
61   std::ostringstream message_;
62 
63 
64   DISALLOW_COPY_AND_ASSIGN(TestParallelMoveResolver);
65 };
66 
BuildParallelMove(ArenaAllocator * allocator,const size_t operands[][2],size_t number_of_moves)67 static HParallelMove* BuildParallelMove(ArenaAllocator* allocator,
68                                         const size_t operands[][2],
69                                         size_t number_of_moves) {
70   HParallelMove* moves = new (allocator) HParallelMove(allocator);
71   for (size_t i = 0; i < number_of_moves; ++i) {
72     moves->AddMove(new (allocator) MoveOperands(
73         Location::RegisterLocation(ManagedRegister(operands[i][0])),
74         Location::RegisterLocation(ManagedRegister(operands[i][1]))));
75   }
76   return moves;
77 }
78 
TEST(ParallelMoveTest,Dependency)79 TEST(ParallelMoveTest, Dependency) {
80   ArenaPool pool;
81   ArenaAllocator allocator(&pool);
82 
83   {
84     TestParallelMoveResolver resolver(&allocator);
85     static constexpr size_t moves[][2] = {{0, 1}, {1, 2}};
86     resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
87     ASSERT_STREQ("(1 -> 2) (0 -> 1)", resolver.GetMessage().c_str());
88   }
89 
90   {
91     TestParallelMoveResolver resolver(&allocator);
92     static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {1, 4}};
93     resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
94     ASSERT_STREQ("(2 -> 3) (1 -> 2) (1 -> 4) (0 -> 1)", resolver.GetMessage().c_str());
95   }
96 }
97 
TEST(ParallelMoveTest,Swap)98 TEST(ParallelMoveTest, Swap) {
99   ArenaPool pool;
100   ArenaAllocator allocator(&pool);
101 
102   {
103     TestParallelMoveResolver resolver(&allocator);
104     static constexpr size_t moves[][2] = {{0, 1}, {1, 0}};
105     resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
106     ASSERT_STREQ("(1 <-> 0)", resolver.GetMessage().c_str());
107   }
108 
109   {
110     TestParallelMoveResolver resolver(&allocator);
111     static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {1, 0}};
112     resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
113     ASSERT_STREQ("(1 -> 2) (1 <-> 0)", resolver.GetMessage().c_str());
114   }
115 
116   {
117     TestParallelMoveResolver resolver(&allocator);
118     static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}};
119     resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
120     ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1)", resolver.GetMessage().c_str());
121   }
122 
123   {
124     TestParallelMoveResolver resolver(&allocator);
125     static constexpr size_t moves[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 1}, {5, 4}};
126     resolver.EmitNativeCode(BuildParallelMove(&allocator, moves, arraysize(moves)));
127     ASSERT_STREQ("(4 <-> 1) (3 <-> 4) (2 <-> 3) (0 -> 1) (5 -> 4)", resolver.GetMessage().c_str());
128   }
129 }
130 
131 }  // namespace art
132