Revision: 23219
Author: [email protected]
Date: Wed Aug 20 09:16:30 2014 UTC
Log: [turbofan] Add support for Finish to the InstructionSelector.
Also fix an off-by-one bug in the handling of Parameter nodes, and
improve test coverage for pointer map computation.
TEST=compiler-unittest
[email protected]
Review URL: https://codereview.chromium.org/490673006
http://code.google.com/p/v8/source/detail?r=23219
Modified:
/branches/bleeding_edge/src/compiler/instruction-selector.cc
/branches/bleeding_edge/src/compiler/instruction-selector.h
/branches/bleeding_edge/test/compiler-unittests/instruction-selector-unittest.cc
/branches/bleeding_edge/test/compiler-unittests/instruction-selector-unittest.h
=======================================
--- /branches/bleeding_edge/src/compiler/instruction-selector.cc Wed Aug 20
04:01:00 2014 UTC
+++ /branches/bleeding_edge/src/compiler/instruction-selector.cc Wed Aug 20
09:16:30 2014 UTC
@@ -199,12 +199,18 @@
DCHECK(!IsReference(node));
sequence()->MarkAsDouble(node->id());
- // Propagate "doubleness" throughout phis.
+ // Propagate "doubleness" throughout Finish/Phi nodes.
for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
Node* user = *i;
- if (user->opcode() != IrOpcode::kPhi) continue;
- if (IsDouble(user)) continue;
- MarkAsDouble(user);
+ switch (user->opcode()) {
+ case IrOpcode::kFinish:
+ case IrOpcode::kPhi:
+ if (IsDouble(user)) continue;
+ MarkAsDouble(user);
+ break;
+ default:
+ break;
+ }
}
}
@@ -220,12 +226,18 @@
DCHECK(!IsDouble(node));
sequence()->MarkAsReference(node->id());
- // Propagate "referenceness" throughout phis.
+ // Propagate "referenceness" throughout Finish/Phi nodes.
for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
Node* user = *i;
- if (user->opcode() != IrOpcode::kPhi) continue;
- if (IsReference(user)) continue;
- MarkAsReference(user);
+ switch (user->opcode()) {
+ case IrOpcode::kFinish:
+ case IrOpcode::kPhi:
+ if (IsReference(user)) continue;
+ MarkAsReference(user);
+ break;
+ default:
+ break;
+ }
}
}
@@ -464,13 +476,12 @@
case IrOpcode::kContinuation:
// No code needed for these graph artifacts.
return;
+ case IrOpcode::kFinish:
+ return VisitFinish(node);
case IrOpcode::kParameter: {
- int index = OpParameter<int>(node);
- MachineType rep = linkage()
- ->GetIncomingDescriptor()
- ->GetInputLocation(index)
- .representation();
- MarkAsRepresentation(rep, node);
+ LinkageLocation location =
+ linkage()->GetParameterLocation(OpParameter<int>(node));
+ MarkAsRepresentation(location.representation(), node);
return VisitParameter(node);
}
case IrOpcode::kPhi:
@@ -797,6 +808,13 @@
#endif // V8_TARGET_ARCH_32_BIT || !V8_TURBOFAN_BACKEND
+void InstructionSelector::VisitFinish(Node* node) {
+ OperandGenerator g(this);
+ Node* value = node->InputAt(0);
+ Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+}
+
+
void InstructionSelector::VisitParameter(Node* node) {
OperandGenerator g(this);
Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetParameterLocation(
=======================================
--- /branches/bleeding_edge/src/compiler/instruction-selector.h Mon Aug 11
15:55:28 2014 UTC
+++ /branches/bleeding_edge/src/compiler/instruction-selector.h Wed Aug 20
09:16:30 2014 UTC
@@ -169,6 +169,7 @@
void VisitWord64Compare(Node* node, FlagsContinuation* cont);
void VisitFloat64Compare(Node* node, FlagsContinuation* cont);
+ void VisitFinish(Node* node);
void VisitParameter(Node* node);
void VisitPhi(Node* node);
void VisitProjection(Node* node);
=======================================
---
/branches/bleeding_edge/test/compiler-unittests/instruction-selector-unittest.cc
Wed Aug 20 04:01:00 2014 UTC
+++
/branches/bleeding_edge/test/compiler-unittests/instruction-selector-unittest.cc
Wed Aug 20 09:16:30 2014 UTC
@@ -10,6 +10,13 @@
namespace internal {
namespace compiler {
+namespace {
+
+typedef RawMachineAssembler::Label MLabel;
+
+} // namespace
+
+
InstructionSelectorTest::InstructionSelectorTest() :
rng_(FLAG_random_seed) {}
@@ -34,6 +41,7 @@
<< 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 @@
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 @@
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;
}
@@ -116,6 +143,172 @@
EXPECT_EQ(1U, s[1]->OutputCount());
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
=======================================
---
/branches/bleeding_edge/test/compiler-unittests/instruction-selector-unittest.h
Tue Aug 19 08:27:33 2014 UTC
+++
/branches/bleeding_edge/test/compiler-unittests/instruction-selector-unittest.h
Wed Aug 20 09:16:30 2014 UTC
@@ -6,7 +6,7 @@
#define V8_COMPILER_UNITTESTS_INSTRUCTION_SELECTOR_UNITTEST_H_
#include <deque>
-#include <ostream> // NOLINT(readability/streams)
+#include <set>
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/instruction-selector.h"
@@ -115,6 +115,14 @@
EXPECT_LT(index, size());
return instructions_[index];
}
+
+ bool IsDouble(int virtual_register) const {
+ return doubles_.find(virtual_register) != doubles_.end();
+ }
+
+ bool IsReference(int virtual_register) const {
+ return references_.find(virtual_register) != references_.end();
+ }
int32_t ToInt32(const InstructionOperand* operand) const {
return ToConstant(operand).ToInt32();
@@ -147,6 +155,8 @@
ConstantMap constants_;
ConstantMap immediates_;
std::deque<Instruction*> instructions_;
+ std::set<int> doubles_;
+ std::set<int> references_;
};
base::RandomNumberGenerator rng_;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.