Index: test/compiler-unittests/instruction-selector-unittest.cc |
diff --git a/test/compiler-unittests/instruction-selector-unittest.cc b/test/compiler-unittests/instruction-selector-unittest.cc |
index d6fef2e8070d02d43882a42ac10f060019fe9d10..27241898a7beaa013a666d00e4d5d2189f835fbb 100644 |
--- a/test/compiler-unittests/instruction-selector-unittest.cc |
+++ b/test/compiler-unittests/instruction-selector-unittest.cc |
@@ -10,6 +10,13 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
+namespace { |
+ |
+typedef RawMachineAssembler::Label MLabel; |
+ |
+} // namespace |
+ |
+ |
InstructionSelectorTest::InstructionSelectorTest() : rng_(FLAG_random_seed) {} |
@@ -34,6 +41,7 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build( |
<< sequence; |
} |
Stream s; |
+ std::set<int> virtual_registers; |
for (InstructionSequence::const_iterator i = sequence.begin(); |
i != sequence.end(); ++i) { |
Instruction* instr = *i; |
@@ -55,6 +63,10 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build( |
if (output->IsConstant()) { |
s.constants_.insert(std::make_pair( |
output->index(), sequence.GetConstant(output->index()))); |
+ virtual_registers.insert(output->index()); |
+ } else if (output->IsUnallocated()) { |
+ virtual_registers.insert( |
+ UnallocatedOperand::cast(output)->virtual_register()); |
} |
} |
for (size_t i = 0; i < instr->InputCount(); ++i) { |
@@ -63,10 +75,25 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build( |
if (input->IsImmediate()) { |
s.immediates_.insert(std::make_pair( |
input->index(), sequence.GetImmediate(input->index()))); |
+ } else if (input->IsUnallocated()) { |
+ virtual_registers.insert( |
+ UnallocatedOperand::cast(input)->virtual_register()); |
} |
} |
s.instructions_.push_back(instr); |
} |
+ for (std::set<int>::const_iterator i = virtual_registers.begin(); |
+ i != virtual_registers.end(); ++i) { |
+ int virtual_register = *i; |
+ if (sequence.IsDouble(virtual_register)) { |
+ EXPECT_FALSE(sequence.IsReference(virtual_register)); |
+ s.doubles_.insert(virtual_register); |
+ } |
+ if (sequence.IsReference(virtual_register)) { |
+ EXPECT_FALSE(sequence.IsDouble(virtual_register)); |
+ s.references_.insert(virtual_register); |
+ } |
+ } |
return s; |
} |
@@ -117,6 +144,172 @@ TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) { |
EXPECT_EQ(kArchRet, s[2]->arch_opcode()); |
} |
+ |
+// ----------------------------------------------------------------------------- |
+// Parameters. |
+ |
+ |
+TARGET_TEST_F(InstructionSelectorTest, DoubleParameter) { |
+ StreamBuilder m(this, kMachFloat64, kMachFloat64); |
+ Node* param = m.Parameter(0); |
+ m.Return(param); |
+ Stream s = m.Build(kAllInstructions); |
+ EXPECT_TRUE(s.IsDouble(param->id())); |
+} |
+ |
+ |
+TARGET_TEST_F(InstructionSelectorTest, ReferenceParameter) { |
+ StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged); |
+ Node* param = m.Parameter(0); |
+ m.Return(param); |
+ Stream s = m.Build(kAllInstructions); |
+ EXPECT_TRUE(s.IsReference(param->id())); |
+} |
+ |
+ |
+// ----------------------------------------------------------------------------- |
+// Finish. |
+ |
+ |
+typedef InstructionSelectorTestWithParam<MachineType> |
+ InstructionSelectorFinishTest; |
+ |
+ |
+TARGET_TEST_P(InstructionSelectorFinishTest, Parameter) { |
+ const MachineType type = GetParam(); |
+ StreamBuilder m(this, type, type); |
+ Node* param = m.Parameter(0); |
+ Node* finish = m.NewNode(m.common()->Finish(1), param, m.graph()->start()); |
+ m.Return(finish); |
+ Stream s = m.Build(kAllInstructions); |
+ ASSERT_EQ(3U, s.size()); |
+ EXPECT_EQ(kArchNop, s[0]->arch_opcode()); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ ASSERT_TRUE(s[0]->Output()->IsUnallocated()); |
+ EXPECT_EQ(param->id(), |
+ UnallocatedOperand::cast(s[0]->Output())->virtual_register()); |
+ EXPECT_EQ(kArchNop, s[1]->arch_opcode()); |
+ ASSERT_EQ(1U, s[1]->InputCount()); |
+ ASSERT_TRUE(s[1]->InputAt(0)->IsUnallocated()); |
+ EXPECT_EQ(param->id(), |
+ UnallocatedOperand::cast(s[1]->InputAt(0))->virtual_register()); |
+ ASSERT_EQ(1U, s[1]->OutputCount()); |
+ ASSERT_TRUE(s[1]->Output()->IsUnallocated()); |
+ EXPECT_TRUE(UnallocatedOperand::cast(s[1]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(finish->id(), |
+ UnallocatedOperand::cast(s[1]->Output())->virtual_register()); |
+} |
+ |
+ |
+TARGET_TEST_P(InstructionSelectorFinishTest, PropagateDoubleness) { |
+ const MachineType type = GetParam(); |
+ StreamBuilder m(this, type, type); |
+ Node* param = m.Parameter(0); |
+ Node* finish = m.NewNode(m.common()->Finish(1), param, m.graph()->start()); |
+ m.Return(finish); |
+ Stream s = m.Build(kAllInstructions); |
+ EXPECT_EQ(s.IsDouble(param->id()), s.IsDouble(finish->id())); |
+} |
+ |
+ |
+TARGET_TEST_P(InstructionSelectorFinishTest, PropagateReferenceness) { |
+ const MachineType type = GetParam(); |
+ StreamBuilder m(this, type, type); |
+ Node* param = m.Parameter(0); |
+ Node* finish = m.NewNode(m.common()->Finish(1), param, m.graph()->start()); |
+ m.Return(finish); |
+ Stream s = m.Build(kAllInstructions); |
+ EXPECT_EQ(s.IsReference(param->id()), s.IsReference(finish->id())); |
+} |
+ |
+ |
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFinishTest, |
+ ::testing::Values(kMachFloat64, kMachInt8, kMachUint8, |
+ kMachInt16, kMachUint16, kMachInt32, |
+ kMachUint32, kMachInt64, kMachUint64, |
+ kMachPtr, kMachAnyTagged)); |
+ |
+ |
+// ----------------------------------------------------------------------------- |
+// Finish. |
+ |
+ |
+typedef InstructionSelectorTestWithParam<MachineType> |
+ InstructionSelectorPhiTest; |
+ |
+ |
+TARGET_TEST_P(InstructionSelectorPhiTest, PropagateDoubleness) { |
+ const MachineType type = GetParam(); |
+ StreamBuilder m(this, type, type, type); |
+ Node* param0 = m.Parameter(0); |
+ Node* param1 = m.Parameter(1); |
+ MLabel a, b, c; |
+ m.Branch(m.Int32Constant(0), &a, &b); |
+ m.Bind(&a); |
+ m.Goto(&c); |
+ m.Bind(&b); |
+ m.Goto(&c); |
+ m.Bind(&c); |
+ Node* phi = m.Phi(param0, param1); |
+ m.Return(phi); |
+ Stream s = m.Build(kAllInstructions); |
+ EXPECT_EQ(s.IsDouble(phi->id()), s.IsDouble(param0->id())); |
+ EXPECT_EQ(s.IsDouble(phi->id()), s.IsDouble(param1->id())); |
+} |
+ |
+ |
+TARGET_TEST_P(InstructionSelectorPhiTest, PropagateReferenceness) { |
+ const MachineType type = GetParam(); |
+ StreamBuilder m(this, type, type, type); |
+ Node* param0 = m.Parameter(0); |
+ Node* param1 = m.Parameter(1); |
+ MLabel a, b, c; |
+ m.Branch(m.Int32Constant(1), &a, &b); |
+ m.Bind(&a); |
+ m.Goto(&c); |
+ m.Bind(&b); |
+ m.Goto(&c); |
+ m.Bind(&c); |
+ Node* phi = m.Phi(param0, param1); |
+ m.Return(phi); |
+ Stream s = m.Build(kAllInstructions); |
+ EXPECT_EQ(s.IsReference(phi->id()), s.IsReference(param0->id())); |
+ EXPECT_EQ(s.IsReference(phi->id()), s.IsReference(param1->id())); |
+} |
+ |
+ |
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorPhiTest, |
+ ::testing::Values(kMachFloat64, kMachInt8, kMachUint8, |
+ kMachInt16, kMachUint16, kMachInt32, |
+ kMachUint32, kMachInt64, kMachUint64, |
+ kMachPtr, kMachAnyTagged)); |
+ |
+ |
+// ----------------------------------------------------------------------------- |
+// ValueEffect. |
+ |
+ |
+TARGET_TEST_F(InstructionSelectorTest, ValueEffect) { |
+ StreamBuilder m1(this, kMachInt32, kMachPtr); |
+ Node* p1 = m1.Parameter(0); |
+ m1.Return(m1.Load(kMachInt32, p1, m1.Int32Constant(0))); |
+ Stream s1 = m1.Build(kAllInstructions); |
+ StreamBuilder m2(this, kMachInt32, kMachPtr); |
+ Node* p2 = m2.Parameter(0); |
+ m2.Return(m2.NewNode(m2.machine()->Load(kMachInt32), p2, m2.Int32Constant(0), |
+ m2.NewNode(m2.common()->ValueEffect(1), p2))); |
+ Stream s2 = m2.Build(kAllInstructions); |
+ EXPECT_LE(3U, s1.size()); |
+ ASSERT_EQ(s1.size(), s2.size()); |
+ TRACED_FORRANGE(size_t, i, 0, s1.size() - 1) { |
+ const Instruction* i1 = s1[i]; |
+ const Instruction* i2 = s2[i]; |
+ EXPECT_EQ(i1->arch_opcode(), i2->arch_opcode()); |
+ EXPECT_EQ(i1->InputCount(), i2->InputCount()); |
+ EXPECT_EQ(i1->OutputCount(), i2->OutputCount()); |
+ } |
+} |
+ |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |