blob: b6be0bff17cb26c8198c25042d903e978f9c1caf [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <limits>
6
7#include "src/compiler/graph.h"
8#include "src/compiler/value-numbering-reducer.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "test/unittests/test-utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010
11namespace v8 {
12namespace internal {
13namespace compiler {
14
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015struct TestOperator : public Operator {
16 TestOperator(Operator::Opcode opcode, Operator::Properties properties,
17 size_t value_in, size_t value_out)
18 : Operator(opcode, properties, "TestOp", value_in, 0, 0, value_out, 0,
19 0) {}
20};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023static const TestOperator kOp0(0, Operator::kEliminatable, 0, 1);
24static const TestOperator kOp1(1, Operator::kEliminatable, 1, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025
26
27class ValueNumberingReducerTest : public TestWithZone {
28 public:
29 ValueNumberingReducerTest() : graph_(zone()), reducer_(zone()) {}
30
31 protected:
32 Reduction Reduce(Node* node) { return reducer_.Reduce(node); }
33
34 Graph* graph() { return &graph_; }
35
36 private:
37 Graph graph_;
38 ValueNumberingReducer reducer_;
39};
40
41
42TEST_F(ValueNumberingReducerTest, AllInputsAreChecked) {
43 Node* na = graph()->NewNode(&kOp0);
44 Node* nb = graph()->NewNode(&kOp0);
45 Node* n1 = graph()->NewNode(&kOp0, na);
46 Node* n2 = graph()->NewNode(&kOp0, nb);
47 EXPECT_FALSE(Reduce(n1).Changed());
48 EXPECT_FALSE(Reduce(n2).Changed());
49}
50
51
52TEST_F(ValueNumberingReducerTest, DeadNodesAreNeverReturned) {
53 Node* n0 = graph()->NewNode(&kOp0);
54 Node* n1 = graph()->NewNode(&kOp1, n0);
55 EXPECT_FALSE(Reduce(n1).Changed());
56 n1->Kill();
57 EXPECT_FALSE(Reduce(graph()->NewNode(&kOp1, n0)).Changed());
58}
59
60
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061TEST_F(ValueNumberingReducerTest, OnlyEliminatableNodesAreReduced) {
62 TestOperator op(0, Operator::kNoProperties, 0, 1);
63 Node* n0 = graph()->NewNode(&op);
64 Node* n1 = graph()->NewNode(&op);
65 EXPECT_FALSE(Reduce(n0).Changed());
66 EXPECT_FALSE(Reduce(n1).Changed());
67}
68
69
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070TEST_F(ValueNumberingReducerTest, OperatorEqualityNotIdentity) {
71 static const size_t kMaxInputCount = 16;
72 Node* inputs[kMaxInputCount];
73 for (size_t i = 0; i < arraysize(inputs); ++i) {
74 Operator::Opcode opcode = static_cast<Operator::Opcode>(
75 std::numeric_limits<Operator::Opcode>::max() - i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076 inputs[i] = graph()->NewNode(
77 new (zone()) TestOperator(opcode, Operator::kEliminatable, 0, 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 }
79 TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 const TestOperator op1(static_cast<Operator::Opcode>(input_count),
81 Operator::kEliminatable, input_count, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 Node* n1 = graph()->NewNode(&op1, static_cast<int>(input_count), inputs);
83 Reduction r1 = Reduce(n1);
84 EXPECT_FALSE(r1.Changed());
85
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086 const TestOperator op2(static_cast<Operator::Opcode>(input_count),
87 Operator::kEliminatable, input_count, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 Node* n2 = graph()->NewNode(&op2, static_cast<int>(input_count), inputs);
89 Reduction r2 = Reduce(n2);
90 EXPECT_TRUE(r2.Changed());
91 EXPECT_EQ(n1, r2.replacement());
92 }
93}
94
95
96TEST_F(ValueNumberingReducerTest, SubsequentReductionsYieldTheSameNode) {
97 static const size_t kMaxInputCount = 16;
98 Node* inputs[kMaxInputCount];
99 for (size_t i = 0; i < arraysize(inputs); ++i) {
100 Operator::Opcode opcode = static_cast<Operator::Opcode>(
101 std::numeric_limits<Operator::Opcode>::max() - i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102 inputs[i] = graph()->NewNode(
103 new (zone()) TestOperator(opcode, Operator::kEliminatable, 0, 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 }
105 TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400106 const TestOperator op1(1, Operator::kEliminatable, input_count, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 Node* n = graph()->NewNode(&op1, static_cast<int>(input_count), inputs);
108 Reduction r = Reduce(n);
109 EXPECT_FALSE(r.Changed());
110
111 r = Reduce(graph()->NewNode(&op1, static_cast<int>(input_count), inputs));
112 ASSERT_TRUE(r.Changed());
113 EXPECT_EQ(n, r.replacement());
114
115 r = Reduce(graph()->NewNode(&op1, static_cast<int>(input_count), inputs));
116 ASSERT_TRUE(r.Changed());
117 EXPECT_EQ(n, r.replacement());
118 }
119}
120
121
122TEST_F(ValueNumberingReducerTest, WontReplaceNodeWithItself) {
123 Node* n = graph()->NewNode(&kOp0);
124 EXPECT_FALSE(Reduce(n).Changed());
125 EXPECT_FALSE(Reduce(n).Changed());
126}
127
128} // namespace compiler
129} // namespace internal
130} // namespace v8