| OLD | NEW | 
|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/compiler/move-optimizer.h" | 5 #include "src/compiler/move-optimizer.h" | 
| 6 #include "test/unittests/compiler/instruction-sequence-unittest.h" | 6 #include "test/unittests/compiler/instruction-sequence-unittest.h" | 
| 7 | 7 | 
| 8 namespace v8 { | 8 namespace v8 { | 
| 9 namespace internal { | 9 namespace internal { | 
| 10 namespace compiler { | 10 namespace compiler { | 
| 11 | 11 | 
| 12 class MoveOptimizerTest : public InstructionSequenceTest { | 12 class MoveOptimizerTest : public InstructionSequenceTest { | 
| 13  public: | 13  public: | 
| 14   Instruction* LastInstruction() { return sequence()->instructions().back(); } | 14   Instruction* LastInstruction() { return sequence()->instructions().back(); } | 
| 15 | 15 | 
| 16   void AddMove(Instruction* instr, TestOperand from, TestOperand to, | 16   void AddMove(Instruction* instr, TestOperand from, TestOperand to, | 
| 17                Instruction::GapPosition pos = Instruction::START) { | 17                Instruction::GapPosition pos = Instruction::START) { | 
| 18     auto parallel_move = instr->GetOrCreateParallelMove(pos, zone()); | 18     auto parallel_move = instr->GetOrCreateParallelMove(pos, zone()); | 
| 19     parallel_move->AddMove(ConvertMoveArg(from), ConvertMoveArg(to), zone()); | 19     parallel_move->AddMove(ConvertMoveArg(from), ConvertMoveArg(to)); | 
| 20   } | 20   } | 
| 21 | 21 | 
| 22   int NonRedundantSize(ParallelMove* move) { | 22   int NonRedundantSize(ParallelMove* moves) { | 
| 23     int i = 0; | 23     int i = 0; | 
| 24     auto ops = move->move_operands(); | 24     for (auto move : *moves) { | 
| 25     for (auto op = ops->begin(); op != ops->end(); ++op) { | 25       if (move->IsRedundant()) continue; | 
| 26       if (op->IsRedundant()) continue; |  | 
| 27       i++; | 26       i++; | 
| 28     } | 27     } | 
| 29     return i; | 28     return i; | 
| 30   } | 29   } | 
| 31 | 30 | 
| 32   bool Contains(ParallelMove* move, TestOperand from_op, TestOperand to_op) { | 31   bool Contains(ParallelMove* moves, TestOperand from_op, TestOperand to_op) { | 
| 33     auto from = ConvertMoveArg(from_op); | 32     auto from = ConvertMoveArg(from_op); | 
| 34     auto to = ConvertMoveArg(to_op); | 33     auto to = ConvertMoveArg(to_op); | 
| 35     auto ops = move->move_operands(); | 34     for (auto move : *moves) { | 
| 36     for (auto op = ops->begin(); op != ops->end(); ++op) { | 35       if (move->IsRedundant()) continue; | 
| 37       if (op->IsRedundant()) continue; | 36       if (move->source() == from && move->destination() == to) { | 
| 38       if (op->source()->Equals(from) && op->destination()->Equals(to)) { |  | 
| 39         return true; | 37         return true; | 
| 40       } | 38       } | 
| 41     } | 39     } | 
| 42     return false; | 40     return false; | 
| 43   } | 41   } | 
| 44 | 42 | 
| 45   // TODO(dcarney): add a verifier. | 43   // TODO(dcarney): add a verifier. | 
| 46   void Optimize() { | 44   void Optimize() { | 
| 47     WireBlocks(); | 45     WireBlocks(); | 
| 48     if (FLAG_trace_turbo) { | 46     if (FLAG_trace_turbo) { | 
| 49       OFStream os(stdout); | 47       OFStream os(stdout); | 
| 50       PrintableInstructionSequence printable = {config(), sequence()}; | 48       PrintableInstructionSequence printable = {config(), sequence()}; | 
| 51       os << "----- Instruction sequence before move optimization -----\n" | 49       os << "----- Instruction sequence before move optimization -----\n" | 
| 52          << printable; | 50          << printable; | 
| 53     } | 51     } | 
| 54     MoveOptimizer move_optimizer(zone(), sequence()); | 52     MoveOptimizer move_optimizer(zone(), sequence()); | 
| 55     move_optimizer.Run(); | 53     move_optimizer.Run(); | 
| 56     if (FLAG_trace_turbo) { | 54     if (FLAG_trace_turbo) { | 
| 57       OFStream os(stdout); | 55       OFStream os(stdout); | 
| 58       PrintableInstructionSequence printable = {config(), sequence()}; | 56       PrintableInstructionSequence printable = {config(), sequence()}; | 
| 59       os << "----- Instruction sequence after move optimization -----\n" | 57       os << "----- Instruction sequence after move optimization -----\n" | 
| 60          << printable; | 58          << printable; | 
| 61     } | 59     } | 
| 62   } | 60   } | 
| 63 | 61 | 
| 64  private: | 62  private: | 
| 65   InstructionOperand* ConvertMoveArg(TestOperand op) { | 63   InstructionOperand ConvertMoveArg(TestOperand op) { | 
| 66     CHECK_EQ(kNoValue, op.vreg_.value_); | 64     CHECK_EQ(kNoValue, op.vreg_.value_); | 
| 67     CHECK_NE(kNoValue, op.value_); | 65     CHECK_NE(kNoValue, op.value_); | 
| 68     switch (op.type_) { | 66     switch (op.type_) { | 
| 69       case kConstant: | 67       case kConstant: | 
| 70         return ConstantOperand::New(zone(), op.value_); | 68         return ConstantOperand(op.value_); | 
| 71       case kFixedSlot: | 69       case kFixedSlot: | 
| 72         return StackSlotOperand::New(zone(), op.value_); | 70         return StackSlotOperand(op.value_); | 
| 73       case kFixedRegister: | 71       case kFixedRegister: | 
| 74         CHECK(0 <= op.value_ && op.value_ < num_general_registers()); | 72         CHECK(0 <= op.value_ && op.value_ < num_general_registers()); | 
| 75         return RegisterOperand::New(zone(), op.value_); | 73         return RegisterOperand(op.value_); | 
| 76       default: | 74       default: | 
| 77         break; | 75         break; | 
| 78     } | 76     } | 
| 79     CHECK(false); | 77     CHECK(false); | 
| 80     return nullptr; | 78     return InstructionOperand(); | 
| 81   } | 79   } | 
| 82 }; | 80 }; | 
| 83 | 81 | 
| 84 | 82 | 
| 85 TEST_F(MoveOptimizerTest, RemovesRedundant) { | 83 TEST_F(MoveOptimizerTest, RemovesRedundant) { | 
| 86   StartBlock(); | 84   StartBlock(); | 
| 87   auto first_instr = EmitNop(); | 85   auto first_instr = EmitNop(); | 
| 88   AddMove(first_instr, Reg(0), Reg(1)); | 86   AddMove(first_instr, Reg(0), Reg(1)); | 
| 89   auto last_instr = EmitNop(); | 87   auto last_instr = EmitNop(); | 
| 90   AddMove(last_instr, Reg(1), Reg(0)); | 88   AddMove(last_instr, Reg(1), Reg(0)); | 
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 171   CHECK(gap_1->AreMovesRedundant()); | 169   CHECK(gap_1->AreMovesRedundant()); | 
| 172   auto move = LastInstruction()->parallel_moves()[0]; | 170   auto move = LastInstruction()->parallel_moves()[0]; | 
| 173   CHECK_EQ(2, NonRedundantSize(move)); | 171   CHECK_EQ(2, NonRedundantSize(move)); | 
| 174   CHECK(Contains(move, Reg(0), Reg(1))); | 172   CHECK(Contains(move, Reg(0), Reg(1))); | 
| 175   CHECK(Contains(move, Reg(1), Reg(0))); | 173   CHECK(Contains(move, Reg(1), Reg(0))); | 
| 176 } | 174 } | 
| 177 | 175 | 
| 178 }  // namespace compiler | 176 }  // namespace compiler | 
| 179 }  // namespace internal | 177 }  // namespace internal | 
| 180 }  // namespace v8 | 178 }  // namespace v8 | 
| OLD | NEW | 
|---|