| 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 "src/compiler/pipeline.h" | 6 #include "src/compiler/pipeline.h" | 
| 7 #include "test/unittests/compiler/instruction-sequence-unittest.h" | 7 #include "test/unittests/compiler/instruction-sequence-unittest.h" | 
| 8 | 8 | 
| 9 namespace v8 { | 9 namespace v8 { | 
| 10 namespace internal { | 10 namespace internal { | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 54     move_optimizer.Run(); | 54     move_optimizer.Run(); | 
| 55     if (FLAG_trace_turbo) { | 55     if (FLAG_trace_turbo) { | 
| 56       OFStream os(stdout); | 56       OFStream os(stdout); | 
| 57       PrintableInstructionSequence printable = {config(), sequence()}; | 57       PrintableInstructionSequence printable = {config(), sequence()}; | 
| 58       os << "----- Instruction sequence after move optimization -----\n" | 58       os << "----- Instruction sequence after move optimization -----\n" | 
| 59          << printable; | 59          << printable; | 
| 60     } | 60     } | 
| 61   } | 61   } | 
| 62 | 62 | 
| 63  private: | 63  private: | 
|  | 64   bool DoesRegisterAllocation() const override { return false; } | 
|  | 65 | 
| 64   InstructionOperand ConvertMoveArg(TestOperand op) { | 66   InstructionOperand ConvertMoveArg(TestOperand op) { | 
| 65     CHECK_EQ(kNoValue, op.vreg_.value_); | 67     CHECK_EQ(kNoValue, op.vreg_.value_); | 
| 66     CHECK_NE(kNoValue, op.value_); | 68     CHECK_NE(kNoValue, op.value_); | 
| 67     switch (op.type_) { | 69     switch (op.type_) { | 
| 68       case kConstant: | 70       case kConstant: | 
| 69         return ConstantOperand(op.value_); | 71         return ConstantOperand(op.value_); | 
| 70       case kFixedSlot: | 72       case kFixedSlot: | 
| 71         return AllocatedOperand(LocationOperand::STACK_SLOT, | 73         return AllocatedOperand(LocationOperand::STACK_SLOT, | 
| 72                                 MachineRepresentation::kWord32, op.value_); | 74                                 MachineRepresentation::kWord32, op.value_); | 
| 73       case kFixedRegister: | 75       case kFixedRegister: { | 
| 74         CHECK(0 <= op.value_ && op.value_ < num_general_registers()); | 76         MachineRepresentation rep = GetCanonicalRep(op); | 
| 75         return AllocatedOperand(LocationOperand::REGISTER, | 77         CHECK(0 <= op.value_ && op.value_ < GetNumRegs(rep)); | 
| 76                                 MachineRepresentation::kWord32, op.value_); | 78         return AllocatedOperand(LocationOperand::REGISTER, rep, op.value_); | 
| 77       case kExplicit: | 79       } | 
| 78         CHECK(0 <= op.value_ && op.value_ < num_general_registers()); | 80       case kExplicit: { | 
| 79         return ExplicitOperand(LocationOperand::REGISTER, | 81         MachineRepresentation rep = GetCanonicalRep(op); | 
| 80                                MachineRepresentation::kWord32, op.value_); | 82         CHECK(0 <= op.value_ && op.value_ < GetNumRegs(rep)); | 
|  | 83         return ExplicitOperand(LocationOperand::REGISTER, rep, op.value_); | 
|  | 84       } | 
| 81       default: | 85       default: | 
| 82         break; | 86         break; | 
| 83     } | 87     } | 
| 84     CHECK(false); | 88     CHECK(false); | 
| 85     return InstructionOperand(); | 89     return InstructionOperand(); | 
| 86   } | 90   } | 
| 87 }; | 91 }; | 
| 88 | 92 | 
| 89 | 93 | 
| 90 TEST_F(MoveOptimizerTest, RemovesRedundant) { | 94 TEST_F(MoveOptimizerTest, RemovesRedundant) { | 
| 91   StartBlock(); | 95   StartBlock(); | 
| 92   auto first_instr = EmitNop(); | 96   auto first_instr = EmitNop(); | 
|  | 97   auto last_instr = EmitNop(); | 
|  | 98 | 
| 93   AddMove(first_instr, Reg(0), Reg(1)); | 99   AddMove(first_instr, Reg(0), Reg(1)); | 
| 94   auto last_instr = EmitNop(); |  | 
| 95   AddMove(last_instr, Reg(1), Reg(0)); | 100   AddMove(last_instr, Reg(1), Reg(0)); | 
|  | 101 | 
|  | 102   AddMove(first_instr, FPReg(0), FPReg(1)); | 
|  | 103   AddMove(last_instr, FPReg(1), FPReg(0)); | 
|  | 104 | 
| 96   EndBlock(Last()); | 105   EndBlock(Last()); | 
| 97 | 106 | 
| 98   Optimize(); | 107   Optimize(); | 
| 99 | 108 | 
| 100   CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0])); | 109   CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0])); | 
| 101   auto move = last_instr->parallel_moves()[0]; | 110   auto move = last_instr->parallel_moves()[0]; | 
| 102   CHECK_EQ(1, NonRedundantSize(move)); | 111   CHECK_EQ(2, NonRedundantSize(move)); | 
| 103   CHECK(Contains(move, Reg(0), Reg(1))); | 112   CHECK(Contains(move, Reg(0), Reg(1))); | 
|  | 113   CHECK(Contains(move, FPReg(0), FPReg(1))); | 
| 104 } | 114 } | 
| 105 | 115 | 
| 106 | 116 | 
| 107 TEST_F(MoveOptimizerTest, RemovesRedundantExplicit) { | 117 TEST_F(MoveOptimizerTest, RemovesRedundantExplicit) { | 
| 108   int first_reg_index = | 118   int first_reg_index = GetAllocatableCode(0); | 
| 109       RegisterConfiguration::Turbofan()->GetAllocatableGeneralCode(0); | 119   int second_reg_index = GetAllocatableCode(1); | 
| 110   int second_reg_index = |  | 
| 111       RegisterConfiguration::Turbofan()->GetAllocatableGeneralCode(1); |  | 
| 112 | 120 | 
| 113   StartBlock(); | 121   StartBlock(); | 
| 114   auto first_instr = EmitNop(); | 122   auto first_instr = EmitNop(); | 
|  | 123   auto last_instr = EmitNop(); | 
|  | 124 | 
| 115   AddMove(first_instr, Reg(first_reg_index), ExplicitReg(second_reg_index)); | 125   AddMove(first_instr, Reg(first_reg_index), ExplicitReg(second_reg_index)); | 
| 116   auto last_instr = EmitNop(); |  | 
| 117   AddMove(last_instr, Reg(second_reg_index), Reg(first_reg_index)); | 126   AddMove(last_instr, Reg(second_reg_index), Reg(first_reg_index)); | 
|  | 127 | 
| 118   EndBlock(Last()); | 128   EndBlock(Last()); | 
| 119 | 129 | 
| 120   Optimize(); | 130   Optimize(); | 
| 121 | 131 | 
| 122   CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0])); | 132   CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0])); | 
| 123   auto move = last_instr->parallel_moves()[0]; | 133   auto move = last_instr->parallel_moves()[0]; | 
| 124   CHECK_EQ(1, NonRedundantSize(move)); | 134   CHECK_EQ(1, NonRedundantSize(move)); | 
| 125   CHECK(Contains(move, Reg(first_reg_index), ExplicitReg(second_reg_index))); | 135   CHECK(Contains(move, Reg(first_reg_index), ExplicitReg(second_reg_index))); | 
| 126 } | 136 } | 
| 127 | 137 | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 178 TEST_F(MoveOptimizerTest, SimpleMergeCycle) { | 188 TEST_F(MoveOptimizerTest, SimpleMergeCycle) { | 
| 179   StartBlock(); | 189   StartBlock(); | 
| 180   EndBlock(Branch(Imm(), 1, 2)); | 190   EndBlock(Branch(Imm(), 1, 2)); | 
| 181 | 191 | 
| 182   StartBlock(); | 192   StartBlock(); | 
| 183   EndBlock(Jump(2)); | 193   EndBlock(Jump(2)); | 
| 184   auto gap_0 = LastInstruction(); | 194   auto gap_0 = LastInstruction(); | 
| 185   AddMove(gap_0, Reg(0), Reg(1)); | 195   AddMove(gap_0, Reg(0), Reg(1)); | 
| 186   AddMove(LastInstruction(), Reg(1), Reg(0)); | 196   AddMove(LastInstruction(), Reg(1), Reg(0)); | 
| 187 | 197 | 
|  | 198   AddMove(gap_0, FPReg(0), FPReg(1)); | 
|  | 199   AddMove(LastInstruction(), FPReg(1), FPReg(0)); | 
|  | 200 | 
| 188   StartBlock(); | 201   StartBlock(); | 
| 189   EndBlock(Jump(1)); | 202   EndBlock(Jump(1)); | 
| 190   auto gap_1 = LastInstruction(); | 203   auto gap_1 = LastInstruction(); | 
| 191   AddMove(gap_1, Reg(0), Reg(1)); | 204   AddMove(gap_1, Reg(0), Reg(1)); | 
| 192   AddMove(gap_1, Reg(1), Reg(0)); | 205   AddMove(gap_1, Reg(1), Reg(0)); | 
|  | 206   AddMove(gap_1, FPReg(0), FPReg(1)); | 
|  | 207   AddMove(gap_1, FPReg(1), FPReg(0)); | 
| 193 | 208 | 
| 194   StartBlock(); | 209   StartBlock(); | 
| 195   EndBlock(Last()); | 210   EndBlock(Last()); | 
| 196 | 211 | 
| 197   auto last = LastInstruction(); | 212   auto last = LastInstruction(); | 
| 198 | 213 | 
| 199   Optimize(); | 214   Optimize(); | 
| 200 | 215 | 
| 201   CHECK(gap_0->AreMovesRedundant()); | 216   CHECK(gap_0->AreMovesRedundant()); | 
| 202   CHECK(gap_1->AreMovesRedundant()); | 217   CHECK(gap_1->AreMovesRedundant()); | 
| 203   auto move = last->parallel_moves()[0]; | 218   auto move = last->parallel_moves()[0]; | 
| 204   CHECK_EQ(2, NonRedundantSize(move)); | 219   CHECK_EQ(4, NonRedundantSize(move)); | 
| 205   CHECK(Contains(move, Reg(0), Reg(1))); | 220   CHECK(Contains(move, Reg(0), Reg(1))); | 
| 206   CHECK(Contains(move, Reg(1), Reg(0))); | 221   CHECK(Contains(move, Reg(1), Reg(0))); | 
|  | 222   CHECK(Contains(move, FPReg(0), FPReg(1))); | 
|  | 223   CHECK(Contains(move, FPReg(1), FPReg(0))); | 
| 207 } | 224 } | 
| 208 | 225 | 
| 209 | 226 | 
| 210 TEST_F(MoveOptimizerTest, GapsCanMoveOverInstruction) { | 227 TEST_F(MoveOptimizerTest, GapsCanMoveOverInstruction) { | 
| 211   StartBlock(); | 228   StartBlock(); | 
| 212   int const_index = 1; | 229   int const_index = 1; | 
| 213   DefineConstant(const_index); | 230   DefineConstant(const_index); | 
| 214   Instruction* ctant_def = LastInstruction(); | 231   Instruction* ctant_def = LastInstruction(); | 
| 215   AddMove(ctant_def, Reg(1), Reg(0)); | 232   AddMove(ctant_def, Reg(1), Reg(0)); | 
| 216 | 233 | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 318   ParallelMove* b2_move = last_move_b2->parallel_moves()[0]; | 335   ParallelMove* b2_move = last_move_b2->parallel_moves()[0]; | 
| 319   CHECK_EQ(1, NonRedundantSize(b2_move)); | 336   CHECK_EQ(1, NonRedundantSize(b2_move)); | 
| 320   CHECK(Contains(b1_move, Reg(0), Reg(1))); | 337   CHECK(Contains(b1_move, Reg(0), Reg(1))); | 
| 321 } | 338 } | 
| 322 | 339 | 
| 323 TEST_F(MoveOptimizerTest, ClobberedDestinationsAreEliminated) { | 340 TEST_F(MoveOptimizerTest, ClobberedDestinationsAreEliminated) { | 
| 324   StartBlock(); | 341   StartBlock(); | 
| 325   EmitNop(); | 342   EmitNop(); | 
| 326   Instruction* first_instr = LastInstruction(); | 343   Instruction* first_instr = LastInstruction(); | 
| 327   AddMove(first_instr, Reg(0), Reg(1)); | 344   AddMove(first_instr, Reg(0), Reg(1)); | 
| 328   EmitOI(Reg(1), 0, nullptr); | 345   AddMove(first_instr, FPReg(0), FPReg(1)); | 
|  | 346   EmitOOI(Reg(1), FPReg(1), 0, nullptr); | 
| 329   Instruction* last_instr = LastInstruction(); | 347   Instruction* last_instr = LastInstruction(); | 
| 330   EndBlock(); | 348   EndBlock(); | 
| 331   Optimize(); | 349   Optimize(); | 
| 332 | 350 | 
| 333   ParallelMove* first_move = first_instr->parallel_moves()[0]; | 351   ParallelMove* first_move = first_instr->parallel_moves()[0]; | 
| 334   CHECK_EQ(0, NonRedundantSize(first_move)); | 352   CHECK_EQ(0, NonRedundantSize(first_move)); | 
| 335 | 353 | 
| 336   ParallelMove* last_move = last_instr->parallel_moves()[0]; | 354   ParallelMove* last_move = last_instr->parallel_moves()[0]; | 
| 337   CHECK_EQ(0, NonRedundantSize(last_move)); | 355   CHECK_EQ(0, NonRedundantSize(last_move)); | 
| 338 } | 356 } | 
| 339 | 357 | 
| 340 }  // namespace compiler | 358 }  // namespace compiler | 
| 341 }  // namespace internal | 359 }  // namespace internal | 
| 342 }  // namespace v8 | 360 }  // namespace v8 | 
| OLD | NEW | 
|---|