2014-09-04 09:22:10 +00:00
|
|
|
// 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/graph.h"
|
|
|
|
#include "src/compiler/graph-reducer.h"
|
|
|
|
#include "src/compiler/operator.h"
|
2014-10-01 08:34:25 +00:00
|
|
|
#include "test/unittests/test-utils.h"
|
2014-09-04 09:22:10 +00:00
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
|
|
|
|
|
using testing::_;
|
|
|
|
using testing::DefaultValue;
|
|
|
|
using testing::Return;
|
|
|
|
using testing::Sequence;
|
|
|
|
using testing::StrictMock;
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
2014-10-29 14:40:47 +00:00
|
|
|
struct TestOperator : public Operator {
|
|
|
|
TestOperator(Operator::Opcode opcode, Operator::Properties properties,
|
|
|
|
size_t value_in, size_t value_out)
|
|
|
|
: Operator(opcode, properties, "TestOp", value_in, 0, 0, value_out, 0,
|
|
|
|
0) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-09-04 09:22:10 +00:00
|
|
|
namespace {
|
|
|
|
|
2014-10-29 14:40:47 +00:00
|
|
|
TestOperator OP0(0, Operator::kNoWrite, 0, 1);
|
|
|
|
TestOperator OP1(1, Operator::kNoProperties, 1, 1);
|
2014-09-04 09:22:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
struct MockReducer : public Reducer {
|
|
|
|
MOCK_METHOD1(Reduce, Reduction(Node*));
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
|
|
class GraphReducerTest : public TestWithZone {
|
|
|
|
public:
|
|
|
|
GraphReducerTest() : graph_(zone()) {}
|
|
|
|
|
|
|
|
static void SetUpTestCase() {
|
|
|
|
TestWithZone::SetUpTestCase();
|
|
|
|
DefaultValue<Reduction>::Set(Reducer::NoChange());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TearDownTestCase() {
|
|
|
|
DefaultValue<Reduction>::Clear();
|
|
|
|
TestWithZone::TearDownTestCase();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void ReduceNode(Node* node, Reducer* r) {
|
2014-11-14 08:00:24 +00:00
|
|
|
GraphReducer reducer(graph(), zone());
|
2014-09-04 09:22:10 +00:00
|
|
|
reducer.AddReducer(r);
|
|
|
|
reducer.ReduceNode(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReduceNode(Node* node, Reducer* r1, Reducer* r2) {
|
2014-11-14 08:00:24 +00:00
|
|
|
GraphReducer reducer(graph(), zone());
|
2014-09-04 09:22:10 +00:00
|
|
|
reducer.AddReducer(r1);
|
|
|
|
reducer.AddReducer(r2);
|
|
|
|
reducer.ReduceNode(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) {
|
2014-11-14 08:00:24 +00:00
|
|
|
GraphReducer reducer(graph(), zone());
|
2014-09-04 09:22:10 +00:00
|
|
|
reducer.AddReducer(r1);
|
|
|
|
reducer.AddReducer(r2);
|
|
|
|
reducer.AddReducer(r3);
|
|
|
|
reducer.ReduceNode(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
Graph* graph() { return &graph_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Graph graph_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-09-05 11:10:28 +00:00
|
|
|
TEST_F(GraphReducerTest, NodeIsDeadAfterReplace) {
|
|
|
|
StrictMock<MockReducer> r;
|
|
|
|
Node* node0 = graph()->NewNode(&OP0);
|
|
|
|
Node* node1 = graph()->NewNode(&OP1, node0);
|
|
|
|
Node* node2 = graph()->NewNode(&OP1, node0);
|
2014-11-14 08:00:24 +00:00
|
|
|
EXPECT_CALL(r, Reduce(node0)).WillOnce(Return(Reducer::NoChange()));
|
2014-09-05 11:10:28 +00:00
|
|
|
EXPECT_CALL(r, Reduce(node1)).WillOnce(Return(Reducer::Replace(node2)));
|
|
|
|
ReduceNode(node1, &r);
|
|
|
|
EXPECT_FALSE(node0->IsDead());
|
|
|
|
EXPECT_TRUE(node1->IsDead());
|
|
|
|
EXPECT_FALSE(node2->IsDead());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-04 09:22:10 +00:00
|
|
|
TEST_F(GraphReducerTest, ReduceOnceForEveryReducer) {
|
|
|
|
StrictMock<MockReducer> r1, r2;
|
|
|
|
Node* node0 = graph()->NewNode(&OP0);
|
|
|
|
EXPECT_CALL(r1, Reduce(node0));
|
|
|
|
EXPECT_CALL(r2, Reduce(node0));
|
|
|
|
ReduceNode(node0, &r1, &r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_F(GraphReducerTest, ReduceAgainAfterChanged) {
|
2014-09-26 06:40:07 +00:00
|
|
|
Sequence s1, s2, s3;
|
2014-09-04 09:22:10 +00:00
|
|
|
StrictMock<MockReducer> r1, r2, r3;
|
|
|
|
Node* node0 = graph()->NewNode(&OP0);
|
|
|
|
EXPECT_CALL(r1, Reduce(node0));
|
|
|
|
EXPECT_CALL(r2, Reduce(node0));
|
2014-09-26 06:40:07 +00:00
|
|
|
EXPECT_CALL(r3, Reduce(node0)).InSequence(s1, s2, s3).WillOnce(
|
2014-09-04 09:22:10 +00:00
|
|
|
Return(Reducer::Changed(node0)));
|
|
|
|
EXPECT_CALL(r1, Reduce(node0)).InSequence(s1);
|
|
|
|
EXPECT_CALL(r2, Reduce(node0)).InSequence(s2);
|
|
|
|
ReduceNode(node0, &r1, &r2, &r3);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|