1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler/move-optimizer.h"
6342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#include "src/compiler/pipeline.h"
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "test/unittests/compiler/instruction-sequence-unittest.h"
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace compiler {
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass MoveOptimizerTest : public InstructionSequenceTest {
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instruction* LastInstruction() { return sequence()->instructions().back(); }
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AddMove(Instruction* instr, TestOperand from, TestOperand to,
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               Instruction::GapPosition pos = Instruction::START) {
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    auto parallel_move = instr->GetOrCreateParallelMove(pos, zone());
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    parallel_move->AddMove(ConvertMoveArg(from), ConvertMoveArg(to));
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int NonRedundantSize(ParallelMove* moves) {
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int i = 0;
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (auto move : *moves) {
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (move->IsRedundant()) continue;
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      i++;
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return i;
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool Contains(ParallelMove* moves, TestOperand from_op, TestOperand to_op) {
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    auto from = ConvertMoveArg(from_op);
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    auto to = ConvertMoveArg(to_op);
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (auto move : *moves) {
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (move->IsRedundant()) continue;
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (move->source().Equals(from) && move->destination().Equals(to)) {
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return true;
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return false;
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // TODO(dcarney): add a verifier.
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Optimize() {
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    WireBlocks();
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (FLAG_trace_turbo) {
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      OFStream os(stdout);
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintableInstructionSequence printable = {config(), sequence()};
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      os << "----- Instruction sequence before move optimization -----\n"
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         << printable;
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MoveOptimizer move_optimizer(zone(), sequence());
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    move_optimizer.Run();
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (FLAG_trace_turbo) {
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      OFStream os(stdout);
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintableInstructionSequence printable = {config(), sequence()};
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      os << "----- Instruction sequence after move optimization -----\n"
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         << printable;
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  InstructionOperand ConvertMoveArg(TestOperand op) {
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CHECK_EQ(kNoValue, op.vreg_.value_);
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CHECK_NE(kNoValue, op.value_);
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (op.type_) {
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kConstant:
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ConstantOperand(op.value_);
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kFixedSlot:
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return AllocatedOperand(LocationOperand::STACK_SLOT,
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                MachineRepresentation::kWord32, op.value_);
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case kFixedRegister:
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        CHECK(0 <= op.value_ && op.value_ < num_general_registers());
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return AllocatedOperand(LocationOperand::REGISTER,
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                MachineRepresentation::kWord32, op.value_);
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case kExplicit:
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        CHECK(0 <= op.value_ && op.value_ < num_general_registers());
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return ExplicitOperand(LocationOperand::REGISTER,
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               MachineRepresentation::kWord32, op.value_);
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CHECK(false);
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return InstructionOperand();
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST_F(MoveOptimizerTest, RemovesRedundant) {
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StartBlock();
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto first_instr = EmitNop();
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(first_instr, Reg(0), Reg(1));
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto last_instr = EmitNop();
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(last_instr, Reg(1), Reg(0));
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EndBlock(Last());
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Optimize();
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0]));
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto move = last_instr->parallel_moves()[0];
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK_EQ(1, NonRedundantSize(move));
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(Contains(move, Reg(0), Reg(1)));
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTEST_F(MoveOptimizerTest, RemovesRedundantExplicit) {
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int first_reg_index =
10921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      RegisterConfiguration::Turbofan()->GetAllocatableGeneralCode(0);
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int second_reg_index =
11121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      RegisterConfiguration::Turbofan()->GetAllocatableGeneralCode(1);
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto first_instr = EmitNop();
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(first_instr, Reg(first_reg_index), ExplicitReg(second_reg_index));
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto last_instr = EmitNop();
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(last_instr, Reg(second_reg_index), Reg(first_reg_index));
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Last());
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Optimize();
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0]));
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto move = last_instr->parallel_moves()[0];
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(1, NonRedundantSize(move));
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(Contains(move, Reg(first_reg_index), ExplicitReg(second_reg_index)));
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST_F(MoveOptimizerTest, SplitsConstants) {
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StartBlock();
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EndBlock(Last());
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto gap = LastInstruction();
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AddMove(gap, Const(1), Slot(0));
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AddMove(gap, Const(1), Slot(1));
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AddMove(gap, Const(1), Reg(0));
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AddMove(gap, Const(1), Slot(2));
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Optimize();
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  auto move = gap->parallel_moves()[0];
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK_EQ(1, NonRedundantSize(move));
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(Contains(move, Const(1), Reg(0)));
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  move = gap->parallel_moves()[1];
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK_EQ(3, NonRedundantSize(move));
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(Contains(move, Reg(0), Slot(0)));
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(Contains(move, Reg(0), Slot(1)));
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CHECK(Contains(move, Reg(0), Slot(2)));
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTEST_F(MoveOptimizerTest, SimpleMerge) {
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Branch(Imm(), 1, 2));
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Jump(2));
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(LastInstruction(), Reg(0), Reg(1));
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Jump(1));
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(LastInstruction(), Reg(0), Reg(1));
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Last());
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto last = LastInstruction();
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Optimize();
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto move = last->parallel_moves()[0];
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(1, NonRedundantSize(move));
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(Contains(move, Reg(0), Reg(1)));
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTEST_F(MoveOptimizerTest, SimpleMergeCycle) {
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Branch(Imm(), 1, 2));
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Jump(2));
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto gap_0 = LastInstruction();
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(gap_0, Reg(0), Reg(1));
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(LastInstruction(), Reg(1), Reg(0));
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Jump(1));
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto gap_1 = LastInstruction();
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(gap_1, Reg(0), Reg(1));
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(gap_1, Reg(1), Reg(0));
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Last());
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto last = LastInstruction();
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Optimize();
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(gap_0->AreMovesRedundant());
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(gap_1->AreMovesRedundant());
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  auto move = last->parallel_moves()[0];
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(2, NonRedundantSize(move));
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(Contains(move, Reg(0), Reg(1)));
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(Contains(move, Reg(1), Reg(0)));
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTEST_F(MoveOptimizerTest, GapsCanMoveOverInstruction) {
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StartBlock();
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const_index = 1;
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DefineConstant(const_index);
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instruction* ctant_def = LastInstruction();
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(ctant_def, Reg(1), Reg(0));
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Instruction* last = EmitNop();
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(last, Const(const_index), Reg(0));
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddMove(last, Reg(0), Reg(1));
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EndBlock(Last());
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Optimize();
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ParallelMove* inst1_start =
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ctant_def->GetParallelMove(Instruction::GapPosition::START);
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ParallelMove* inst1_end =
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ctant_def->GetParallelMove(Instruction::GapPosition::END);
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ParallelMove* last_start =
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      last->GetParallelMove(Instruction::GapPosition::START);
229342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(inst1_start == nullptr || NonRedundantSize(inst1_start) == 0);
230342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(inst1_end == nullptr || NonRedundantSize(inst1_end) == 0);
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(last_start->size() == 2);
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int redundants = 0;
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int assignment = 0;
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (MoveOperands* move : *last_start) {
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (move->IsRedundant()) {
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ++redundants;
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ++assignment;
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CHECK(move->destination().IsRegister());
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CHECK(move->source().IsConstant());
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(1, redundants);
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK_EQ(1, assignment);
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
248342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen MurdochTEST_F(MoveOptimizerTest, SubsetMovesMerge) {
249342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
250342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Branch(Imm(), 1, 2));
251342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
252342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
253342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Jump(2));
254342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last_move_b1 = LastInstruction();
255342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b1, Reg(0), Reg(1));
256342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b1, Reg(2), Reg(3));
257342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
258342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
259342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Jump(1));
260342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last_move_b2 = LastInstruction();
261342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b2, Reg(0), Reg(1));
262342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b2, Reg(4), Reg(5));
263342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
264342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
265342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Last());
266342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
267342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last = LastInstruction();
268342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
269342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Optimize();
270342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
271342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* last_move = last->parallel_moves()[0];
272342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(1, NonRedundantSize(last_move));
273342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(last_move, Reg(0), Reg(1)));
274342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
275342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* b1_move = last_move_b1->parallel_moves()[0];
276342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(1, NonRedundantSize(b1_move));
277342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(b1_move, Reg(2), Reg(3)));
278342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
279342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* b2_move = last_move_b2->parallel_moves()[0];
280342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(1, NonRedundantSize(b2_move));
281342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(b2_move, Reg(4), Reg(5)));
282342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch}
283342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
284342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
285342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen MurdochTEST_F(MoveOptimizerTest, GapConflictSubsetMovesDoNotMerge) {
286342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
287342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Branch(Imm(), 1, 2));
288342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
289342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
290342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Jump(2));
291342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last_move_b1 = LastInstruction();
292342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b1, Reg(0), Reg(1));
293342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b1, Reg(2), Reg(0));
294342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b1, Reg(4), Reg(5));
295342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
296342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
297342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Jump(1));
298342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last_move_b2 = LastInstruction();
299342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b2, Reg(0), Reg(1));
300342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(last_move_b2, Reg(4), Reg(5));
301342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
302342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
303342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock(Last());
304342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
305342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last = LastInstruction();
306342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
307342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Optimize();
308342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
309342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* last_move = last->parallel_moves()[0];
310342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(1, NonRedundantSize(last_move));
311342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(last_move, Reg(4), Reg(5)));
312342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
313342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* b1_move = last_move_b1->parallel_moves()[0];
314342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(2, NonRedundantSize(b1_move));
315342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(b1_move, Reg(0), Reg(1)));
316342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(b1_move, Reg(2), Reg(0)));
317342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
318342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* b2_move = last_move_b2->parallel_moves()[0];
319342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(1, NonRedundantSize(b2_move));
320342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK(Contains(b1_move, Reg(0), Reg(1)));
321342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch}
322342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
323342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen MurdochTEST_F(MoveOptimizerTest, ClobberedDestinationsAreEliminated) {
324342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  StartBlock();
325342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EmitNop();
326342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* first_instr = LastInstruction();
327342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  AddMove(first_instr, Reg(0), Reg(1));
328342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EmitOI(Reg(1), 0, nullptr);
329342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Instruction* last_instr = LastInstruction();
330342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  EndBlock();
331342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  Optimize();
332342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
333342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* first_move = first_instr->parallel_moves()[0];
334342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(0, NonRedundantSize(first_move));
335342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
336342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  ParallelMove* last_move = last_instr->parallel_moves()[0];
337342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  CHECK_EQ(0, NonRedundantSize(last_move));
338342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch}
339342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace compiler
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace internal
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
343