Home | History | Annotate | Download | only in optimizing
      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:
     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     }
     34     message_ << "("
     35              << move->GetSource().reg().RegId()
     36              << " -> "
     37              << move->GetDestination().reg().RegId()
     38              << ")";
     39   }
     40 
     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 
     53   virtual void SpillScratch(int reg) {}
     54   virtual void RestoreScratch(int reg) {}
     55 
     56   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 
     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 
     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 
     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