Line data Source code
1 : // 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 "src/compiler/state-values-utils.h"
6 : #include "src/bit-vector.h"
7 : #include "test/unittests/compiler/graph-unittest.h"
8 : #include "test/unittests/compiler/node-test-utils.h"
9 : #include "test/unittests/test-utils.h"
10 : #include "testing/gmock/include/gmock/gmock.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace compiler {
15 :
16 7 : class StateValuesIteratorTest : public GraphTest {
17 : public:
18 7 : StateValuesIteratorTest() : GraphTest(3) {}
19 :
20 6 : Node* StateValuesFromVector(NodeVector* nodes) {
21 6 : int count = static_cast<int>(nodes->size());
22 12 : return graph()->NewNode(
23 : common()->StateValues(count, SparseInputMask::Dense()), count,
24 6 : count == 0 ? nullptr : &(nodes->front()));
25 : }
26 : };
27 :
28 :
29 15444 : TEST_F(StateValuesIteratorTest, SimpleIteration) {
30 : NodeVector inputs(zone());
31 1 : const int count = 10;
32 21 : for (int i = 0; i < count; i++) {
33 20 : inputs.push_back(Int32Constant(i));
34 : }
35 1 : Node* state_values = StateValuesFromVector(&inputs);
36 1 : int i = 0;
37 21 : for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
38 50 : EXPECT_THAT(node.node, IsInt32Constant(i));
39 10 : i++;
40 : }
41 1 : EXPECT_EQ(count, i);
42 1 : }
43 :
44 :
45 15444 : TEST_F(StateValuesIteratorTest, EmptyIteration) {
46 : NodeVector inputs(zone());
47 1 : Node* state_values = StateValuesFromVector(&inputs);
48 : bool empty = true;
49 1 : for (auto node : StateValuesAccess(state_values)) {
50 : USE(node);
51 : empty = false;
52 : }
53 1 : EXPECT_TRUE(empty);
54 1 : }
55 :
56 :
57 15444 : TEST_F(StateValuesIteratorTest, NestedIteration) {
58 : NodeVector inputs(zone());
59 1 : int count = 0;
60 17 : for (int i = 0; i < 8; i++) {
61 8 : if (i == 2) {
62 : // Single nested in index 2.
63 : NodeVector nested_inputs(zone());
64 17 : for (int j = 0; j < 8; j++) {
65 16 : nested_inputs.push_back(Int32Constant(count++));
66 : }
67 2 : inputs.push_back(StateValuesFromVector(&nested_inputs));
68 7 : } else if (i == 5) {
69 : // Double nested at index 5.
70 : NodeVector nested_inputs(zone());
71 17 : for (int j = 0; j < 8; j++) {
72 8 : if (j == 7) {
73 : NodeVector doubly_nested_inputs(zone());
74 5 : for (int k = 0; k < 2; k++) {
75 4 : doubly_nested_inputs.push_back(Int32Constant(count++));
76 : }
77 2 : nested_inputs.push_back(StateValuesFromVector(&doubly_nested_inputs));
78 : } else {
79 14 : nested_inputs.push_back(Int32Constant(count++));
80 : }
81 : }
82 2 : inputs.push_back(StateValuesFromVector(&nested_inputs));
83 : } else {
84 12 : inputs.push_back(Int32Constant(count++));
85 : }
86 : }
87 1 : Node* state_values = StateValuesFromVector(&inputs);
88 1 : int i = 0;
89 47 : for (StateValuesAccess::TypedNode node : StateValuesAccess(state_values)) {
90 115 : EXPECT_THAT(node.node, IsInt32Constant(i));
91 23 : i++;
92 : }
93 1 : EXPECT_EQ(count, i);
94 1 : }
95 :
96 :
97 15444 : TEST_F(StateValuesIteratorTest, TreeFromVector) {
98 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
99 25 : TRACED_FOREACH(int, count, sizes) {
100 6 : JSOperatorBuilder javascript(zone());
101 6 : MachineOperatorBuilder machine(zone());
102 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
103 6 : &machine);
104 :
105 : // Generate the input vector.
106 : NodeVector inputs(zone());
107 70212 : for (int i = 0; i < count; i++) {
108 70206 : inputs.push_back(Int32Constant(i));
109 : }
110 :
111 : // Build the tree.
112 6 : StateValuesCache builder(&jsgraph);
113 6 : Node* values_node = builder.GetNodeForValues(
114 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
115 6 : nullptr);
116 :
117 : // Check the tree contents with vector.
118 : int i = 0;
119 70212 : for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
120 175515 : EXPECT_THAT(node.node, IsInt32Constant(i));
121 35103 : i++;
122 : }
123 18 : EXPECT_EQ(inputs.size(), static_cast<size_t>(i));
124 : }
125 1 : }
126 :
127 15444 : TEST_F(StateValuesIteratorTest, TreeFromVectorWithLiveness) {
128 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
129 25 : TRACED_FOREACH(int, count, sizes) {
130 6 : JSOperatorBuilder javascript(zone());
131 6 : MachineOperatorBuilder machine(zone());
132 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
133 6 : &machine);
134 :
135 : // Generate the input vector.
136 : NodeVector inputs(zone());
137 70212 : for (int i = 0; i < count; i++) {
138 70206 : inputs.push_back(Int32Constant(i));
139 : }
140 : // Generate the input liveness.
141 6 : BitVector liveness(count, zone());
142 70212 : for (int i = 0; i < count; i++) {
143 35103 : if (i % 3 == 0) {
144 : liveness.Add(i);
145 : }
146 : }
147 :
148 : // Build the tree.
149 6 : StateValuesCache builder(&jsgraph);
150 6 : Node* values_node = builder.GetNodeForValues(
151 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
152 6 : &liveness);
153 :
154 : // Check the tree contents with vector.
155 : int i = 0;
156 70212 : for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) {
157 35103 : if (liveness.Contains(i)) {
158 58515 : EXPECT_THAT(node.node, IsInt32Constant(i));
159 : } else {
160 46800 : EXPECT_EQ(node.node, nullptr);
161 : }
162 35103 : i++;
163 : }
164 18 : EXPECT_EQ(inputs.size(), static_cast<size_t>(i));
165 : }
166 1 : }
167 :
168 15444 : TEST_F(StateValuesIteratorTest, BuildTreeIdentical) {
169 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
170 25 : TRACED_FOREACH(int, count, sizes) {
171 6 : JSOperatorBuilder javascript(zone());
172 6 : MachineOperatorBuilder machine(zone());
173 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
174 6 : &machine);
175 :
176 : // Generate the input vector.
177 : NodeVector inputs(zone());
178 70212 : for (int i = 0; i < count; i++) {
179 70206 : inputs.push_back(Int32Constant(i));
180 : }
181 :
182 : // Build two trees from the same data.
183 6 : StateValuesCache builder(&jsgraph);
184 6 : Node* node1 = builder.GetNodeForValues(
185 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
186 6 : nullptr);
187 6 : Node* node2 = builder.GetNodeForValues(
188 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
189 6 : nullptr);
190 :
191 : // The trees should be equal since the data was the same.
192 6 : EXPECT_EQ(node1, node2);
193 : }
194 1 : }
195 :
196 15444 : TEST_F(StateValuesIteratorTest, BuildTreeWithLivenessIdentical) {
197 1 : int sizes[] = {0, 1, 2, 100, 5000, 30000};
198 25 : TRACED_FOREACH(int, count, sizes) {
199 6 : JSOperatorBuilder javascript(zone());
200 6 : MachineOperatorBuilder machine(zone());
201 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
202 6 : &machine);
203 :
204 : // Generate the input vector.
205 : NodeVector inputs(zone());
206 70212 : for (int i = 0; i < count; i++) {
207 70206 : inputs.push_back(Int32Constant(i));
208 : }
209 : // Generate the input liveness.
210 6 : BitVector liveness(count, zone());
211 70212 : for (int i = 0; i < count; i++) {
212 35103 : if (i % 3 == 0) {
213 : liveness.Add(i);
214 : }
215 : }
216 :
217 : // Build two trees from the same data.
218 6 : StateValuesCache builder(&jsgraph);
219 6 : Node* node1 = builder.GetNodeForValues(
220 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
221 6 : &liveness);
222 6 : Node* node2 = builder.GetNodeForValues(
223 : inputs.size() == 0 ? nullptr : &(inputs.front()), inputs.size(),
224 6 : &liveness);
225 :
226 : // The trees should be equal since the data was the same.
227 6 : EXPECT_EQ(node1, node2);
228 : }
229 1 : }
230 :
231 : } // namespace compiler
232 : } // namespace internal
233 9264 : } // namespace v8
|