| Index: test/unittests/compiler/register-allocator-unittest.cc
|
| diff --git a/test/unittests/compiler/register-allocator-unittest.cc b/test/unittests/compiler/register-allocator-unittest.cc
|
| deleted file mode 100644
|
| index ed3558dc609606daaf366e83e02cbb704147a6ec..0000000000000000000000000000000000000000
|
| --- a/test/unittests/compiler/register-allocator-unittest.cc
|
| +++ /dev/null
|
| @@ -1,798 +0,0 @@
|
| -// Copyright 2014 the V8 project authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "src/compiler/pipeline.h"
|
| -#include "test/unittests/compiler/instruction-sequence-unittest.h"
|
| -
|
| -namespace v8 {
|
| -namespace internal {
|
| -namespace compiler {
|
| -
|
| -
|
| -namespace {
|
| -
|
| -// We can't just use the size of the moves collection, because of
|
| -// redundant moves which need to be discounted.
|
| -int GetMoveCount(const ParallelMove& moves) {
|
| - int move_count = 0;
|
| - for (auto move : moves) {
|
| - if (move->IsEliminated() || move->IsRedundant()) continue;
|
| - ++move_count;
|
| - }
|
| - return move_count;
|
| -}
|
| -
|
| -
|
| -bool AreOperandsOfSameType(
|
| - const AllocatedOperand& op,
|
| - const InstructionSequenceTest::TestOperand& test_op) {
|
| - bool test_op_is_reg =
|
| - (test_op.type_ ==
|
| - InstructionSequenceTest::TestOperandType::kFixedRegister ||
|
| - test_op.type_ == InstructionSequenceTest::TestOperandType::kRegister);
|
| -
|
| - return (op.IsRegister() && test_op_is_reg) ||
|
| - (op.IsStackSlot() && !test_op_is_reg);
|
| -}
|
| -
|
| -
|
| -bool AllocatedOperandMatches(
|
| - const AllocatedOperand& op,
|
| - const InstructionSequenceTest::TestOperand& test_op) {
|
| - return AreOperandsOfSameType(op, test_op) &&
|
| - ((op.IsRegister() ? op.GetRegister().code() : op.index()) ==
|
| - test_op.value_ ||
|
| - test_op.value_ == InstructionSequenceTest::kNoValue);
|
| -}
|
| -
|
| -
|
| -int GetParallelMoveCount(int instr_index, Instruction::GapPosition gap_pos,
|
| - const InstructionSequence* sequence) {
|
| - const ParallelMove* moves =
|
| - sequence->InstructionAt(instr_index)->GetParallelMove(gap_pos);
|
| - if (moves == nullptr) return 0;
|
| - return GetMoveCount(*moves);
|
| -}
|
| -
|
| -
|
| -bool IsParallelMovePresent(int instr_index, Instruction::GapPosition gap_pos,
|
| - const InstructionSequence* sequence,
|
| - const InstructionSequenceTest::TestOperand& src,
|
| - const InstructionSequenceTest::TestOperand& dest) {
|
| - const ParallelMove* moves =
|
| - sequence->InstructionAt(instr_index)->GetParallelMove(gap_pos);
|
| - EXPECT_NE(nullptr, moves);
|
| -
|
| - bool found_match = false;
|
| - for (auto move : *moves) {
|
| - if (move->IsEliminated() || move->IsRedundant()) continue;
|
| - if (AllocatedOperandMatches(AllocatedOperand::cast(move->source()), src) &&
|
| - AllocatedOperandMatches(AllocatedOperand::cast(move->destination()),
|
| - dest)) {
|
| - found_match = true;
|
| - break;
|
| - }
|
| - }
|
| - return found_match;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -
|
| -class RegisterAllocatorTest : public InstructionSequenceTest {
|
| - public:
|
| - void Allocate() {
|
| - WireBlocks();
|
| - Pipeline::AllocateRegistersForTesting(config(), sequence(), true);
|
| - }
|
| -};
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, CanAllocateThreeRegisters) {
|
| - // return p0 + p1;
|
| - StartBlock();
|
| - auto a_reg = Parameter();
|
| - auto b_reg = Parameter();
|
| - auto c_reg = EmitOI(Reg(1), Reg(a_reg, 1), Reg(b_reg, 0));
|
| - Return(c_reg);
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -TEST_F(RegisterAllocatorTest, CanAllocateFPRegisters) {
|
| - StartBlock();
|
| - TestOperand inputs[] = {
|
| - Reg(FPParameter(kFloat64)), Reg(FPParameter(kFloat64)),
|
| - Reg(FPParameter(kFloat32)), Reg(FPParameter(kFloat32)),
|
| - Reg(FPParameter(kSimd128)), Reg(FPParameter(kSimd128))};
|
| - VReg out1 = EmitOI(FPReg(1, kFloat64), arraysize(inputs), inputs);
|
| - Return(out1);
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -TEST_F(RegisterAllocatorTest, SimpleLoop) {
|
| - // i = K;
|
| - // while(true) { i++ }
|
| - StartBlock();
|
| - auto i_reg = DefineConstant();
|
| - EndBlock();
|
| -
|
| - {
|
| - StartLoop(1);
|
| -
|
| - StartBlock();
|
| - auto phi = Phi(i_reg, 2);
|
| - auto ipp = EmitOI(Same(), Reg(phi), Use(DefineConstant()));
|
| - SetInput(phi, 1, ipp);
|
| - EndBlock(Jump(0));
|
| -
|
| - EndLoop();
|
| - }
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SimpleBranch) {
|
| - // return i ? K1 : K2
|
| - StartBlock();
|
| - auto i = DefineConstant();
|
| - EndBlock(Branch(Reg(i), 1, 2));
|
| -
|
| - StartBlock();
|
| - Return(DefineConstant());
|
| - EndBlock(Last());
|
| -
|
| - StartBlock();
|
| - Return(DefineConstant());
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SimpleDiamond) {
|
| - // return p0 ? p0 : p0
|
| - StartBlock();
|
| - auto param = Parameter();
|
| - EndBlock(Branch(Reg(param), 1, 2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(1));
|
| -
|
| - StartBlock();
|
| - Return(param);
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SimpleDiamondPhi) {
|
| - // return i ? K1 : K2
|
| - StartBlock();
|
| - EndBlock(Branch(Reg(DefineConstant()), 1, 2));
|
| -
|
| - StartBlock();
|
| - auto t_val = DefineConstant();
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - auto f_val = DefineConstant();
|
| - EndBlock(Jump(1));
|
| -
|
| - StartBlock();
|
| - Return(Reg(Phi(t_val, f_val)));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, DiamondManyPhis) {
|
| - const int kPhis = kDefaultNRegs * 2;
|
| -
|
| - StartBlock();
|
| - EndBlock(Branch(Reg(DefineConstant()), 1, 2));
|
| -
|
| - StartBlock();
|
| - VReg t_vals[kPhis];
|
| - for (int i = 0; i < kPhis; ++i) {
|
| - t_vals[i] = DefineConstant();
|
| - }
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - VReg f_vals[kPhis];
|
| - for (int i = 0; i < kPhis; ++i) {
|
| - f_vals[i] = DefineConstant();
|
| - }
|
| - EndBlock(Jump(1));
|
| -
|
| - StartBlock();
|
| - TestOperand merged[kPhis];
|
| - for (int i = 0; i < kPhis; ++i) {
|
| - merged[i] = Use(Phi(t_vals[i], f_vals[i]));
|
| - }
|
| - Return(EmitCall(Slot(-1), kPhis, merged));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, DoubleDiamondManyRedundantPhis) {
|
| - const int kPhis = kDefaultNRegs * 2;
|
| -
|
| - // First diamond.
|
| - StartBlock();
|
| - VReg vals[kPhis];
|
| - for (int i = 0; i < kPhis; ++i) {
|
| - vals[i] = Parameter(Slot(-1 - i));
|
| - }
|
| - EndBlock(Branch(Reg(DefineConstant()), 1, 2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(1));
|
| -
|
| - // Second diamond.
|
| - StartBlock();
|
| - EndBlock(Branch(Reg(DefineConstant()), 1, 2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(1));
|
| -
|
| - StartBlock();
|
| - TestOperand merged[kPhis];
|
| - for (int i = 0; i < kPhis; ++i) {
|
| - merged[i] = Use(Phi(vals[i], vals[i]));
|
| - }
|
| - Return(EmitCall(Reg(0), kPhis, merged));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, RegressionPhisNeedTooManyRegisters) {
|
| - const size_t kNumRegs = 3;
|
| - const size_t kParams = kNumRegs + 1;
|
| - // Override number of registers.
|
| - SetNumRegs(kNumRegs, kNumRegs);
|
| -
|
| - StartBlock();
|
| - auto constant = DefineConstant();
|
| - VReg parameters[kParams];
|
| - for (size_t i = 0; i < arraysize(parameters); ++i) {
|
| - parameters[i] = DefineConstant();
|
| - }
|
| - EndBlock();
|
| -
|
| - PhiInstruction* phis[kParams];
|
| - {
|
| - StartLoop(2);
|
| -
|
| - // Loop header.
|
| - StartBlock();
|
| -
|
| - for (size_t i = 0; i < arraysize(parameters); ++i) {
|
| - phis[i] = Phi(parameters[i], 2);
|
| - }
|
| -
|
| - // Perform some computations.
|
| - // something like phi[i] += const
|
| - for (size_t i = 0; i < arraysize(parameters); ++i) {
|
| - auto result = EmitOI(Same(), Reg(phis[i]), Use(constant));
|
| - SetInput(phis[i], 1, result);
|
| - }
|
| -
|
| - EndBlock(Branch(Reg(DefineConstant()), 1, 2));
|
| -
|
| - // Jump back to loop header.
|
| - StartBlock();
|
| - EndBlock(Jump(-1));
|
| -
|
| - EndLoop();
|
| - }
|
| -
|
| - StartBlock();
|
| - Return(DefineConstant());
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SpillPhi) {
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 2));
|
| -
|
| - StartBlock();
|
| - auto left = Define(Reg(0));
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - auto right = Define(Reg(0));
|
| - EndBlock();
|
| -
|
| - StartBlock();
|
| - auto phi = Phi(left, right);
|
| - EmitCall(Slot(-1));
|
| - Return(Reg(phi));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, MoveLotsOfConstants) {
|
| - StartBlock();
|
| - VReg constants[kDefaultNRegs];
|
| - for (size_t i = 0; i < arraysize(constants); ++i) {
|
| - constants[i] = DefineConstant();
|
| - }
|
| - TestOperand call_ops[kDefaultNRegs * 2];
|
| - for (int i = 0; i < kDefaultNRegs; ++i) {
|
| - call_ops[i] = Reg(constants[i], i);
|
| - }
|
| - for (int i = 0; i < kDefaultNRegs; ++i) {
|
| - call_ops[i + kDefaultNRegs] = Slot(constants[i], i);
|
| - }
|
| - EmitCall(Slot(-1), arraysize(call_ops), call_ops);
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SplitBeforeInstruction) {
|
| - const int kNumRegs = 6;
|
| - SetNumRegs(kNumRegs, kNumRegs);
|
| -
|
| - StartBlock();
|
| -
|
| - // Stack parameters/spilled values.
|
| - auto p_0 = Define(Slot(-1));
|
| - auto p_1 = Define(Slot(-2));
|
| -
|
| - // Fill registers.
|
| - VReg values[kNumRegs];
|
| - for (size_t i = 0; i < arraysize(values); ++i) {
|
| - values[i] = Define(Reg(static_cast<int>(i)));
|
| - }
|
| -
|
| - // values[0] will be split in the second half of this instruction.
|
| - // Models Intel mod instructions.
|
| - EmitOI(Reg(0), Reg(p_0, 1), UniqueReg(p_1));
|
| - EmitI(Reg(values[0], 0));
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SplitBeforeInstruction2) {
|
| - const int kNumRegs = 6;
|
| - SetNumRegs(kNumRegs, kNumRegs);
|
| -
|
| - StartBlock();
|
| -
|
| - // Stack parameters/spilled values.
|
| - auto p_0 = Define(Slot(-1));
|
| - auto p_1 = Define(Slot(-2));
|
| -
|
| - // Fill registers.
|
| - VReg values[kNumRegs];
|
| - for (size_t i = 0; i < arraysize(values); ++i) {
|
| - values[i] = Define(Reg(static_cast<int>(i)));
|
| - }
|
| -
|
| - // values[0] and [1] will be split in the second half of this instruction.
|
| - EmitOOI(Reg(0), Reg(1), Reg(p_0, 0), Reg(p_1, 1));
|
| - EmitI(Reg(values[0]), Reg(values[1]));
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, NestedDiamondPhiMerge) {
|
| - // Outer diamond.
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 5));
|
| -
|
| - // Diamond 1
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 2));
|
| -
|
| - StartBlock();
|
| - auto ll = Define(Reg());
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - auto lr = Define(Reg());
|
| - EndBlock();
|
| -
|
| - StartBlock();
|
| - auto l_phi = Phi(ll, lr);
|
| - EndBlock(Jump(5));
|
| -
|
| - // Diamond 2
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 2));
|
| -
|
| - StartBlock();
|
| - auto rl = Define(Reg());
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - auto rr = Define(Reg());
|
| - EndBlock();
|
| -
|
| - StartBlock();
|
| - auto r_phi = Phi(rl, rr);
|
| - EndBlock();
|
| -
|
| - // Outer diamond merge.
|
| - StartBlock();
|
| - auto phi = Phi(l_phi, r_phi);
|
| - Return(Reg(phi));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, NestedDiamondPhiMergeDifferent) {
|
| - // Outer diamond.
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 5));
|
| -
|
| - // Diamond 1
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 2));
|
| -
|
| - StartBlock();
|
| - auto ll = Define(Reg(0));
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - auto lr = Define(Reg(1));
|
| - EndBlock();
|
| -
|
| - StartBlock();
|
| - auto l_phi = Phi(ll, lr);
|
| - EndBlock(Jump(5));
|
| -
|
| - // Diamond 2
|
| - StartBlock();
|
| - EndBlock(Branch(Imm(), 1, 2));
|
| -
|
| - StartBlock();
|
| - auto rl = Define(Reg(2));
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - auto rr = Define(Reg(3));
|
| - EndBlock();
|
| -
|
| - StartBlock();
|
| - auto r_phi = Phi(rl, rr);
|
| - EndBlock();
|
| -
|
| - // Outer diamond merge.
|
| - StartBlock();
|
| - auto phi = Phi(l_phi, r_phi);
|
| - Return(Reg(phi));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, RegressionSplitBeforeAndMove) {
|
| - StartBlock();
|
| -
|
| - // Fill registers.
|
| - VReg values[kDefaultNRegs];
|
| - for (size_t i = 0; i < arraysize(values); ++i) {
|
| - if (i == 0 || i == 1) continue; // Leave a hole for c_1 to take.
|
| - values[i] = Define(Reg(static_cast<int>(i)));
|
| - }
|
| -
|
| - auto c_0 = DefineConstant();
|
| - auto c_1 = DefineConstant();
|
| -
|
| - EmitOI(Reg(1), Reg(c_0, 0), UniqueReg(c_1));
|
| -
|
| - // Use previous values to force c_1 to split before the previous instruction.
|
| - for (size_t i = 0; i < arraysize(values); ++i) {
|
| - if (i == 0 || i == 1) continue;
|
| - EmitI(Reg(values[i], static_cast<int>(i)));
|
| - }
|
| -
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, RegressionSpillTwice) {
|
| - StartBlock();
|
| - auto p_0 = Parameter(Reg(1));
|
| - EmitCall(Slot(-2), Unique(p_0), Reg(p_0, 1));
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, RegressionLoadConstantBeforeSpill) {
|
| - StartBlock();
|
| - // Fill registers.
|
| - VReg values[kDefaultNRegs];
|
| - for (size_t i = arraysize(values); i > 0; --i) {
|
| - values[i - 1] = Define(Reg(static_cast<int>(i - 1)));
|
| - }
|
| - auto c = DefineConstant();
|
| - auto to_spill = Define(Reg());
|
| - EndBlock(Jump(1));
|
| -
|
| - {
|
| - StartLoop(1);
|
| -
|
| - StartBlock();
|
| - // Create a use for c in second half of prev block's last gap
|
| - Phi(c);
|
| - for (size_t i = arraysize(values); i > 0; --i) {
|
| - Phi(values[i - 1]);
|
| - }
|
| - EndBlock(Jump(1));
|
| -
|
| - EndLoop();
|
| - }
|
| -
|
| - StartBlock();
|
| - // Force c to split within to_spill's definition.
|
| - EmitI(Reg(c));
|
| - EmitI(Reg(to_spill));
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, DiamondWithCallFirstBlock) {
|
| - StartBlock();
|
| - auto x = EmitOI(Reg(0));
|
| - EndBlock(Branch(Reg(x), 1, 2));
|
| -
|
| - StartBlock();
|
| - EmitCall(Slot(-1));
|
| - auto occupy = EmitOI(Reg(0));
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - EndBlock(FallThrough());
|
| -
|
| - StartBlock();
|
| - Use(occupy);
|
| - Return(Reg(x));
|
| - EndBlock();
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, DiamondWithCallSecondBlock) {
|
| - StartBlock();
|
| - auto x = EmitOI(Reg(0));
|
| - EndBlock(Branch(Reg(x), 1, 2));
|
| -
|
| - StartBlock();
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock();
|
| - EmitCall(Slot(-1));
|
| - auto occupy = EmitOI(Reg(0));
|
| - EndBlock(FallThrough());
|
| -
|
| - StartBlock();
|
| - Use(occupy);
|
| - Return(Reg(x));
|
| - EndBlock();
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, SingleDeferredBlockSpill) {
|
| - StartBlock(); // B0
|
| - auto var = EmitOI(Reg(0));
|
| - EndBlock(Branch(Reg(var), 1, 2));
|
| -
|
| - StartBlock(); // B1
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock(true); // B2
|
| - EmitCall(Slot(-1), Slot(var));
|
| - EndBlock();
|
| -
|
| - StartBlock(); // B3
|
| - EmitNop();
|
| - EndBlock();
|
| -
|
| - StartBlock(); // B4
|
| - Return(Reg(var, 0));
|
| - EndBlock();
|
| -
|
| - Allocate();
|
| -
|
| - const int var_def_index = 1;
|
| - const int call_index = 3;
|
| - int expect_no_moves =
|
| - FLAG_turbo_preprocess_ranges ? var_def_index : call_index;
|
| - int expect_spill_move =
|
| - FLAG_turbo_preprocess_ranges ? call_index : var_def_index;
|
| -
|
| - // We should have no parallel moves at the "expect_no_moves" position.
|
| - EXPECT_EQ(
|
| - 0, GetParallelMoveCount(expect_no_moves, Instruction::START, sequence()));
|
| -
|
| - // The spill should be performed at the position expect_spill_move.
|
| - EXPECT_TRUE(IsParallelMovePresent(expect_spill_move, Instruction::START,
|
| - sequence(), Reg(0), Slot(0)));
|
| -}
|
| -
|
| -
|
| -TEST_F(RegisterAllocatorTest, MultipleDeferredBlockSpills) {
|
| - if (!FLAG_turbo_preprocess_ranges) return;
|
| -
|
| - StartBlock(); // B0
|
| - auto var1 = EmitOI(Reg(0));
|
| - auto var2 = EmitOI(Reg(1));
|
| - auto var3 = EmitOI(Reg(2));
|
| - EndBlock(Branch(Reg(var1, 0), 1, 2));
|
| -
|
| - StartBlock(true); // B1
|
| - EmitCall(Slot(-2), Slot(var1));
|
| - EndBlock(Jump(2));
|
| -
|
| - StartBlock(true); // B2
|
| - EmitCall(Slot(-1), Slot(var2));
|
| - EndBlock();
|
| -
|
| - StartBlock(); // B3
|
| - EmitNop();
|
| - EndBlock();
|
| -
|
| - StartBlock(); // B4
|
| - Return(Reg(var3, 2));
|
| - EndBlock();
|
| -
|
| - const int def_of_v2 = 3;
|
| - const int call_in_b1 = 4;
|
| - const int call_in_b2 = 6;
|
| - const int end_of_b1 = 5;
|
| - const int end_of_b2 = 7;
|
| - const int start_of_b3 = 8;
|
| -
|
| - Allocate();
|
| - // TODO(mtrofin): at the moment, the linear allocator spills var1 and var2,
|
| - // so only var3 is spilled in deferred blocks.
|
| - const int var3_reg = 2;
|
| - const int var3_slot = 2;
|
| -
|
| - EXPECT_FALSE(IsParallelMovePresent(def_of_v2, Instruction::START, sequence(),
|
| - Reg(var3_reg), Slot()));
|
| - EXPECT_TRUE(IsParallelMovePresent(call_in_b1, Instruction::START, sequence(),
|
| - Reg(var3_reg), Slot(var3_slot)));
|
| - EXPECT_TRUE(IsParallelMovePresent(end_of_b1, Instruction::START, sequence(),
|
| - Slot(var3_slot), Reg()));
|
| -
|
| - EXPECT_TRUE(IsParallelMovePresent(call_in_b2, Instruction::START, sequence(),
|
| - Reg(var3_reg), Slot(var3_slot)));
|
| - EXPECT_TRUE(IsParallelMovePresent(end_of_b2, Instruction::START, sequence(),
|
| - Slot(var3_slot), Reg()));
|
| -
|
| -
|
| - EXPECT_EQ(0,
|
| - GetParallelMoveCount(start_of_b3, Instruction::START, sequence()));
|
| -}
|
| -
|
| -
|
| -namespace {
|
| -
|
| -enum class ParameterType { kFixedSlot, kSlot, kRegister, kFixedRegister };
|
| -
|
| -const ParameterType kParameterTypes[] = {
|
| - ParameterType::kFixedSlot, ParameterType::kSlot, ParameterType::kRegister,
|
| - ParameterType::kFixedRegister};
|
| -
|
| -class SlotConstraintTest : public RegisterAllocatorTest,
|
| - public ::testing::WithParamInterface<
|
| - ::testing::tuple<ParameterType, int>> {
|
| - public:
|
| - static const int kMaxVariant = 5;
|
| -
|
| - protected:
|
| - ParameterType parameter_type() const {
|
| - return ::testing::get<0>(B::GetParam());
|
| - }
|
| - int variant() const { return ::testing::get<1>(B::GetParam()); }
|
| -
|
| - private:
|
| - typedef ::testing::WithParamInterface<::testing::tuple<ParameterType, int>> B;
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -
|
| -#if GTEST_HAS_COMBINE
|
| -
|
| -TEST_P(SlotConstraintTest, SlotConstraint) {
|
| - StartBlock();
|
| - VReg p_0;
|
| - switch (parameter_type()) {
|
| - case ParameterType::kFixedSlot:
|
| - p_0 = Parameter(Slot(-1));
|
| - break;
|
| - case ParameterType::kSlot:
|
| - p_0 = Parameter(Slot(-1));
|
| - break;
|
| - case ParameterType::kRegister:
|
| - p_0 = Parameter(Reg());
|
| - break;
|
| - case ParameterType::kFixedRegister:
|
| - p_0 = Parameter(Reg(1));
|
| - break;
|
| - }
|
| - switch (variant()) {
|
| - case 0:
|
| - EmitI(Slot(p_0), Reg(p_0));
|
| - break;
|
| - case 1:
|
| - EmitI(Slot(p_0));
|
| - break;
|
| - case 2:
|
| - EmitI(Reg(p_0));
|
| - EmitI(Slot(p_0));
|
| - break;
|
| - case 3:
|
| - EmitI(Slot(p_0));
|
| - EmitI(Reg(p_0));
|
| - break;
|
| - case 4:
|
| - EmitI(Slot(p_0, -1), Slot(p_0), Reg(p_0), Reg(p_0, 1));
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - break;
|
| - }
|
| - EndBlock(Last());
|
| -
|
| - Allocate();
|
| -}
|
| -
|
| -
|
| -INSTANTIATE_TEST_CASE_P(
|
| - RegisterAllocatorTest, SlotConstraintTest,
|
| - ::testing::Combine(::testing::ValuesIn(kParameterTypes),
|
| - ::testing::Range(0, SlotConstraintTest::kMaxVariant)));
|
| -
|
| -#endif // GTEST_HAS_COMBINE
|
| -
|
| -} // namespace compiler
|
| -} // namespace internal
|
| -} // namespace v8
|
|
|