Revision: 23686
Author: [email protected]
Date: Thu Sep 4 11:13:35 2014 UTC
Log: [turbofan] Initial version of ValueNumberingReducer.
TEST=compiler-unittests,cctest,mjsunit
[email protected], [email protected]
Review URL: https://codereview.chromium.org/539503002
https://code.google.com/p/v8/source/detail?r=23686
Added:
/branches/bleeding_edge/src/compiler/value-numbering-reducer-unittest.cc
/branches/bleeding_edge/src/compiler/value-numbering-reducer.cc
/branches/bleeding_edge/src/compiler/value-numbering-reducer.h
Modified:
/branches/bleeding_edge/BUILD.gn
/branches/bleeding_edge/src/compiler/compiler.gyp
/branches/bleeding_edge/src/compiler/js-graph.cc
/branches/bleeding_edge/src/compiler/machine-operator.h
/branches/bleeding_edge/src/compiler/pipeline.cc
/branches/bleeding_edge/tools/gyp/v8.gyp
=======================================
--- /dev/null
+++
/branches/bleeding_edge/src/compiler/value-numbering-reducer-unittest.cc
Thu Sep 4 11:13:35 2014 UTC
@@ -0,0 +1,108 @@
+// 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 <limits>
+
+#include "src/compiler/graph.h"
+#include "src/compiler/value-numbering-reducer.h"
+#include "src/test/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+const SimpleOperator kOp0(0, Operator::kNoProperties, 0, 1, "op0");
+
+} // namespace
+
+
+class ValueNumberingReducerTest : public TestWithZone {
+ public:
+ ValueNumberingReducerTest() : graph_(zone()), reducer_(zone()) {}
+
+ protected:
+ Reduction Reduce(Node* node) { return reducer_.Reduce(node); }
+
+ Graph* graph() { return &graph_; }
+
+ private:
+ Graph graph_;
+ ValueNumberingReducer reducer_;
+};
+
+
+TEST_F(ValueNumberingReducerTest, AllInputsAreChecked) {
+ Node* na = graph()->NewNode(&kOp0);
+ Node* nb = graph()->NewNode(&kOp0);
+ Node* n1 = graph()->NewNode(&kOp0, na);
+ Node* n2 = graph()->NewNode(&kOp0, nb);
+ EXPECT_FALSE(Reduce(n1).Changed());
+ EXPECT_FALSE(Reduce(n2).Changed());
+}
+
+
+TEST_F(ValueNumberingReducerTest, KilledNodesAreNeverReturned) {
+ Node* n1 = graph()->NewNode(&kOp0);
+ EXPECT_FALSE(Reduce(n1).Changed());
+ n1->Kill();
+ EXPECT_FALSE(Reduce(graph()->NewNode(&kOp0)).Changed());
+}
+
+
+TEST_F(ValueNumberingReducerTest, OperatorEqualityNotIdentity) {
+ static const size_t kMaxInputCount = 16;
+ Node* inputs[kMaxInputCount];
+ for (size_t i = 0; i < arraysize(inputs); ++i) {
+ Operator::Opcode opcode = static_cast<Operator::Opcode>(
+ std::numeric_limits<Operator::Opcode>::max() - i);
+ inputs[i] = graph()->NewNode(new (zone()) SimpleOperator(
+ opcode, Operator::kNoProperties, 0, 1, "Operator"));
+ }
+ TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
+ const SimpleOperator op1(static_cast<Operator::Opcode>(input_count),
+ Operator::kNoProperties, input_count,
1, "op");
+ Node* n1 = graph()->NewNode(&op1, input_count, inputs);
+ Reduction r1 = Reduce(n1);
+ EXPECT_FALSE(r1.Changed());
+
+ const SimpleOperator op2(static_cast<Operator::Opcode>(input_count),
+ Operator::kNoProperties, input_count,
1, "op");
+ Node* n2 = graph()->NewNode(&op2, input_count, inputs);
+ Reduction r2 = Reduce(n2);
+ EXPECT_TRUE(r2.Changed());
+ EXPECT_EQ(n1, r2.replacement());
+ }
+}
+
+
+TEST_F(ValueNumberingReducerTest, SubsequentReductionsYieldTheSameNode) {
+ static const size_t kMaxInputCount = 16;
+ Node* inputs[kMaxInputCount];
+ for (size_t i = 0; i < arraysize(inputs); ++i) {
+ Operator::Opcode opcode = static_cast<Operator::Opcode>(
+ std::numeric_limits<Operator::Opcode>::max() - i);
+ inputs[i] = graph()->NewNode(new (zone()) SimpleOperator(
+ opcode, Operator::kNoProperties, 0, 1, "Operator"));
+ }
+ TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
+ const SimpleOperator op1(1, Operator::kNoProperties, input_count,
1, "op1");
+ Node* n = graph()->NewNode(&op1, input_count, inputs);
+ Reduction r = Reduce(n);
+ EXPECT_FALSE(r.Changed());
+
+ r = Reduce(graph()->NewNode(&op1, input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(n, r.replacement());
+
+ r = Reduce(graph()->NewNode(&op1, input_count, inputs));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(n, r.replacement());
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/compiler/value-numbering-reducer.cc Thu
Sep 4 11:13:35 2014 UTC
@@ -0,0 +1,73 @@
+// 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/value-numbering-reducer.h"
+
+#include "src/compiler/node.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+size_t HashCode(Node* node) { return node->op()->HashCode(); }
+
+
+bool Equals(Node* a, Node* b) {
+ DCHECK_NOT_NULL(a);
+ DCHECK_NOT_NULL(b);
+ DCHECK_NOT_NULL(a->op());
+ DCHECK_NOT_NULL(b->op());
+ if (!a->op()->Equals(b->op())) return false;
+ if (a->InputCount() != b->InputCount()) return false;
+ for (int j = 0; j < a->InputCount(); ++j) {
+ DCHECK_NOT_NULL(a->InputAt(j));
+ DCHECK_NOT_NULL(b->InputAt(j));
+ if (a->InputAt(j)->id() != b->InputAt(j)->id()) return false;
+ }
+ return true;
+}
+
+} // namespace
+
+
+class ValueNumberingReducer::Entry FINAL : public ZoneObject {
+ public:
+ Entry(Node* node, Entry* next) : node_(node), next_(next) {}
+
+ Node* node() const { return node_; }
+ Entry* next() const { return next_; }
+
+ private:
+ Node* node_;
+ Entry* next_;
+};
+
+
+ValueNumberingReducer::ValueNumberingReducer(Zone* zone) : zone_(zone) {
+ for (size_t i = 0; i < arraysize(buckets_); ++i) {
+ buckets_[i] = NULL;
+ }
+}
+
+
+ValueNumberingReducer::~ValueNumberingReducer() {}
+
+
+Reduction ValueNumberingReducer::Reduce(Node* node) {
+ Entry** head = &buckets_[HashCode(node) % arraysize(buckets_)];
+ for (Entry* entry = *head; entry; entry = entry->next()) {
+ if (entry->node()->op() == NULL) continue;
+ if (Equals(node, entry->node())) {
+ return Replace(entry->node());
+ }
+ }
+ *head = new (zone()) Entry(node, *head);
+ return NoChange();
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/compiler/value-numbering-reducer.h Thu Sep
4 11:13:35 2014 UTC
@@ -0,0 +1,36 @@
+// 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.
+
+#ifndef V8_COMPILER_VALUE_NUMBERING_REDUCER_H_
+#define V8_COMPILER_VALUE_NUMBERING_REDUCER_H_
+
+#include "src/compiler/graph-reducer.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class ValueNumberingReducer FINAL : public Reducer {
+ public:
+ explicit ValueNumberingReducer(Zone* zone);
+ ~ValueNumberingReducer();
+
+ virtual Reduction Reduce(Node* node) OVERRIDE;
+
+ private:
+ Zone* zone() const { return zone_; }
+
+ // TODO(turbofan): We currently use separate chaining with linked lists
here,
+ // we may want to replace that with a more sophisticated data structure
at
+ // some point in the future.
+ class Entry;
+ Entry* buckets_[117u];
+ Zone* zone_;
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_VALUE_NUMBERING_REDUCER_H_
=======================================
--- /branches/bleeding_edge/BUILD.gn Thu Sep 4 10:23:51 2014 UTC
+++ /branches/bleeding_edge/BUILD.gn Thu Sep 4 11:13:35 2014 UTC
@@ -554,6 +554,8 @@
"src/compiler/source-position.h",
"src/compiler/typer.cc",
"src/compiler/typer.h",
+ "src/compiler/value-numbering-reducer.cc",
+ "src/compiler/value-numbering-reducer.h",
"src/compiler/verifier.cc",
"src/compiler/verifier.h",
"src/compiler.cc",
=======================================
--- /branches/bleeding_edge/src/compiler/compiler.gyp Thu Sep 4 09:22:10
2014 UTC
+++ /branches/bleeding_edge/src/compiler/compiler.gyp Thu Sep 4 11:13:35
2014 UTC
@@ -29,6 +29,7 @@
'machine-operator-reducer-unittest.cc',
'machine-operator-unittest.cc',
'simplified-operator-reducer-unittest.cc',
+ 'value-numbering-reducer-unittest.cc',
],
'conditions': [
['v8_target_arch=="arm"', {
=======================================
--- /branches/bleeding_edge/src/compiler/js-graph.cc Mon Aug 18 06:54:07
2014 UTC
+++ /branches/bleeding_edge/src/compiler/js-graph.cc Thu Sep 4 11:13:35
2014 UTC
@@ -104,8 +104,14 @@
// TODO(titzer): We could also match against the addresses of immortable
// immovables here, even without access to the heap, thus always
// canonicalizing references to them.
- return HeapConstant(
- PrintableUnique<Object>::CreateUninitialized(zone(), value));
+ // return HeapConstant(
+ // PrintableUnique<Object>::CreateUninitialized(zone(), value));
+ // TODO(turbofan): This is a work-around to make Unique::HashCode() work
for
+ // value numbering. We need some sane way to compute a unique hash code
for
+ // arbitrary handles here.
+ PrintableUnique<Object> unique(
+ zone(), reinterpret_cast<Address>(*value.location()), value);
+ return HeapConstant(unique);
}
=======================================
--- /branches/bleeding_edge/src/compiler/machine-operator.h Wed Sep 3
12:43:41 2014 UTC
+++ /branches/bleeding_edge/src/compiler/machine-operator.h Thu Sep 4
11:13:35 2014 UTC
@@ -26,6 +26,17 @@
};
+// TODO(bmeurer): Phi will probably also need this in the future.
+template <>
+struct StaticParameterTraits<MachineType> {
+ static OStream& PrintTo(OStream& os, MachineType type) { // NOLINT
+ return os << type;
+ }
+ static int HashCode(MachineType type) { return type; }
+ static bool Equals(MachineType lhs, MachineType rhs) { return lhs ==
rhs; }
+};
+
+
// Interface for building machine-level operators. These operators are
// machine-level but machine-independent and thus define a language
suitable
// for generating code to run on architectures such as ia32, x64, arm, etc.
=======================================
--- /branches/bleeding_edge/src/compiler/pipeline.cc Tue Sep 2 07:07:52
2014 UTC
+++ /branches/bleeding_edge/src/compiler/pipeline.cc Thu Sep 4 11:13:35
2014 UTC
@@ -24,6 +24,7 @@
#include "src/compiler/simplified-lowering.h"
#include "src/compiler/simplified-operator-reducer.h"
#include "src/compiler/typer.h"
+#include "src/compiler/value-numbering-reducer.h"
#include "src/compiler/verifier.h"
#include "src/hydrogen.h"
#include "src/ostreams.h"
@@ -255,11 +256,13 @@
SourcePosition::Unknown());
Linkage linkage(info());
MachineOperatorBuilder machine(zone());
+ ValueNumberingReducer vn_reducer(zone());
SimplifiedOperatorReducer simple_reducer(&jsgraph, &machine);
ChangeLowering lowering(&jsgraph, &linkage, &machine);
MachineOperatorReducer mach_reducer(&jsgraph);
GraphReducer graph_reducer(&graph);
// TODO(titzer): Figure out if we should run all reducers at once
here.
+ graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&mach_reducer);
=======================================
--- /branches/bleeding_edge/tools/gyp/v8.gyp Thu Sep 4 10:23:51 2014 UTC
+++ /branches/bleeding_edge/tools/gyp/v8.gyp Thu Sep 4 11:13:35 2014 UTC
@@ -466,6 +466,8 @@
'../../src/compiler/source-position.h',
'../../src/compiler/typer.cc',
'../../src/compiler/typer.h',
+ '../../src/compiler/value-numbering-reducer.cc',
+ '../../src/compiler/value-numbering-reducer.h',
'../../src/compiler/verifier.cc',
'../../src/compiler/verifier.h',
'../../src/compiler.cc',
--
--
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.