OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/load-elimination.h" | 5 #include "src/compiler/load-elimination.h" |
6 #include "src/compiler/access-builder.h" | 6 #include "src/compiler/access-builder.h" |
| 7 #include "src/compiler/js-graph.h" |
7 #include "src/compiler/node.h" | 8 #include "src/compiler/node.h" |
8 #include "src/compiler/simplified-operator.h" | 9 #include "src/compiler/simplified-operator.h" |
9 #include "test/unittests/compiler/graph-reducer-unittest.h" | 10 #include "test/unittests/compiler/graph-reducer-unittest.h" |
10 #include "test/unittests/compiler/graph-unittest.h" | 11 #include "test/unittests/compiler/graph-unittest.h" |
11 #include "test/unittests/compiler/node-test-utils.h" | 12 #include "test/unittests/compiler/node-test-utils.h" |
12 #include "testing/gmock-support.h" | 13 #include "testing/gmock-support.h" |
13 | 14 |
14 using testing::_; | 15 using testing::_; |
15 using testing::StrictMock; | 16 using testing::StrictMock; |
16 | 17 |
17 namespace v8 { | 18 namespace v8 { |
18 namespace internal { | 19 namespace internal { |
19 namespace compiler { | 20 namespace compiler { |
20 | 21 |
21 class LoadEliminationTest : public TypedGraphTest { | 22 class LoadEliminationTest : public TypedGraphTest { |
22 public: | 23 public: |
23 LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {} | 24 LoadEliminationTest() |
| 25 : TypedGraphTest(3), |
| 26 simplified_(zone()), |
| 27 jsgraph_(isolate(), graph(), common(), nullptr, simplified(), nullptr) { |
| 28 } |
24 ~LoadEliminationTest() override {} | 29 ~LoadEliminationTest() override {} |
25 | 30 |
26 protected: | 31 protected: |
| 32 JSGraph* jsgraph() { return &jsgraph_; } |
27 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 33 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
28 | 34 |
29 private: | 35 private: |
30 SimplifiedOperatorBuilder simplified_; | 36 SimplifiedOperatorBuilder simplified_; |
| 37 JSGraph jsgraph_; |
31 }; | 38 }; |
32 | 39 |
33 TEST_F(LoadEliminationTest, LoadElementAndLoadElement) { | 40 TEST_F(LoadEliminationTest, LoadElementAndLoadElement) { |
34 Node* object = Parameter(Type::Any(), 0); | 41 Node* object = Parameter(Type::Any(), 0); |
35 Node* effect = graph()->start(); | 42 Node* effect = graph()->start(); |
36 Node* control = graph()->start(); | 43 Node* control = graph()->start(); |
37 Node* index = Parameter(Type::UnsignedSmall(), 1); | 44 Node* index = Parameter(Type::UnsignedSmall(), 1); |
38 ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(), | 45 ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(), |
39 MachineType::AnyTagged(), kNoWriteBarrier}; | 46 MachineType::AnyTagged(), kNoWriteBarrier}; |
40 | 47 |
41 StrictMock<MockAdvancedReducerEditor> editor; | 48 StrictMock<MockAdvancedReducerEditor> editor; |
42 LoadElimination load_elimination(&editor, zone()); | 49 LoadElimination load_elimination(&editor, jsgraph(), zone()); |
43 | 50 |
44 load_elimination.Reduce(graph()->start()); | 51 load_elimination.Reduce(graph()->start()); |
45 | 52 |
46 Node* load1 = effect = graph()->NewNode(simplified()->LoadElement(access), | 53 Node* load1 = effect = graph()->NewNode(simplified()->LoadElement(access), |
47 object, index, effect, control); | 54 object, index, effect, control); |
48 load_elimination.Reduce(load1); | 55 load_elimination.Reduce(load1); |
49 | 56 |
50 Node* load2 = effect = graph()->NewNode(simplified()->LoadElement(access), | 57 Node* load2 = effect = graph()->NewNode(simplified()->LoadElement(access), |
51 object, index, effect, control); | 58 object, index, effect, control); |
52 EXPECT_CALL(editor, ReplaceWithValue(load2, load1, load1, _)); | 59 EXPECT_CALL(editor, ReplaceWithValue(load2, load1, load1, _)); |
53 Reduction r = load_elimination.Reduce(load2); | 60 Reduction r = load_elimination.Reduce(load2); |
54 ASSERT_TRUE(r.Changed()); | 61 ASSERT_TRUE(r.Changed()); |
55 EXPECT_EQ(load1, r.replacement()); | 62 EXPECT_EQ(load1, r.replacement()); |
56 } | 63 } |
57 | 64 |
58 TEST_F(LoadEliminationTest, StoreElementAndLoadElement) { | 65 TEST_F(LoadEliminationTest, StoreElementAndLoadElement) { |
59 Node* object = Parameter(Type::Any(), 0); | 66 Node* object = Parameter(Type::Any(), 0); |
60 Node* effect = graph()->start(); | 67 Node* effect = graph()->start(); |
61 Node* control = graph()->start(); | 68 Node* control = graph()->start(); |
62 Node* index = Parameter(Type::UnsignedSmall(), 1); | 69 Node* index = Parameter(Type::UnsignedSmall(), 1); |
63 Node* value = Parameter(Type::Any(), 2); | 70 Node* value = Parameter(Type::Any(), 2); |
64 ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(), | 71 ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(), |
65 MachineType::AnyTagged(), kNoWriteBarrier}; | 72 MachineType::AnyTagged(), kNoWriteBarrier}; |
66 | 73 |
67 StrictMock<MockAdvancedReducerEditor> editor; | 74 StrictMock<MockAdvancedReducerEditor> editor; |
68 LoadElimination load_elimination(&editor, zone()); | 75 LoadElimination load_elimination(&editor, jsgraph(), zone()); |
69 | 76 |
70 load_elimination.Reduce(graph()->start()); | 77 load_elimination.Reduce(graph()->start()); |
71 | 78 |
72 Node* store = effect = | 79 Node* store = effect = |
73 graph()->NewNode(simplified()->StoreElement(access), object, index, value, | 80 graph()->NewNode(simplified()->StoreElement(access), object, index, value, |
74 effect, control); | 81 effect, control); |
75 load_elimination.Reduce(store); | 82 load_elimination.Reduce(store); |
76 | 83 |
77 Node* load = effect = graph()->NewNode(simplified()->LoadElement(access), | 84 Node* load = effect = graph()->NewNode(simplified()->LoadElement(access), |
78 object, index, effect, control); | 85 object, index, effect, control); |
79 EXPECT_CALL(editor, ReplaceWithValue(load, value, store, _)); | 86 EXPECT_CALL(editor, ReplaceWithValue(load, value, store, _)); |
80 Reduction r = load_elimination.Reduce(load); | 87 Reduction r = load_elimination.Reduce(load); |
81 ASSERT_TRUE(r.Changed()); | 88 ASSERT_TRUE(r.Changed()); |
82 EXPECT_EQ(value, r.replacement()); | 89 EXPECT_EQ(value, r.replacement()); |
83 } | 90 } |
84 | 91 |
85 TEST_F(LoadEliminationTest, StoreElementAndStoreFieldAndLoadElement) { | 92 TEST_F(LoadEliminationTest, StoreElementAndStoreFieldAndLoadElement) { |
86 Node* object = Parameter(Type::Any(), 0); | 93 Node* object = Parameter(Type::Any(), 0); |
87 Node* effect = graph()->start(); | 94 Node* effect = graph()->start(); |
88 Node* control = graph()->start(); | 95 Node* control = graph()->start(); |
89 Node* index = Parameter(Type::UnsignedSmall(), 1); | 96 Node* index = Parameter(Type::UnsignedSmall(), 1); |
90 Node* value = Parameter(Type::Any(), 2); | 97 Node* value = Parameter(Type::Any(), 2); |
91 ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(), | 98 ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(), |
92 MachineType::AnyTagged(), kNoWriteBarrier}; | 99 MachineType::AnyTagged(), kNoWriteBarrier}; |
93 | 100 |
94 StrictMock<MockAdvancedReducerEditor> editor; | 101 StrictMock<MockAdvancedReducerEditor> editor; |
95 LoadElimination load_elimination(&editor, zone()); | 102 LoadElimination load_elimination(&editor, jsgraph(), zone()); |
96 | 103 |
97 load_elimination.Reduce(graph()->start()); | 104 load_elimination.Reduce(graph()->start()); |
98 | 105 |
99 Node* store1 = effect = | 106 Node* store1 = effect = |
100 graph()->NewNode(simplified()->StoreElement(access), object, index, value, | 107 graph()->NewNode(simplified()->StoreElement(access), object, index, value, |
101 effect, control); | 108 effect, control); |
102 load_elimination.Reduce(store1); | 109 load_elimination.Reduce(store1); |
103 | 110 |
104 Node* store2 = effect = | 111 Node* store2 = effect = |
105 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), | 112 graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), |
(...skipping 13 matching lines...) Expand all Loading... |
119 Node* effect = graph()->start(); | 126 Node* effect = graph()->start(); |
120 Node* control = graph()->start(); | 127 Node* control = graph()->start(); |
121 FieldAccess const access = {kTaggedBase, | 128 FieldAccess const access = {kTaggedBase, |
122 kPointerSize, | 129 kPointerSize, |
123 MaybeHandle<Name>(), | 130 MaybeHandle<Name>(), |
124 Type::Any(), | 131 Type::Any(), |
125 MachineType::AnyTagged(), | 132 MachineType::AnyTagged(), |
126 kNoWriteBarrier}; | 133 kNoWriteBarrier}; |
127 | 134 |
128 StrictMock<MockAdvancedReducerEditor> editor; | 135 StrictMock<MockAdvancedReducerEditor> editor; |
129 LoadElimination load_elimination(&editor, zone()); | 136 LoadElimination load_elimination(&editor, jsgraph(), zone()); |
130 | 137 |
131 load_elimination.Reduce(graph()->start()); | 138 load_elimination.Reduce(graph()->start()); |
132 | 139 |
133 Node* load1 = effect = graph()->NewNode(simplified()->LoadField(access), | 140 Node* load1 = effect = graph()->NewNode(simplified()->LoadField(access), |
134 object, effect, control); | 141 object, effect, control); |
135 load_elimination.Reduce(load1); | 142 load_elimination.Reduce(load1); |
136 | 143 |
137 Node* load2 = effect = graph()->NewNode(simplified()->LoadField(access), | 144 Node* load2 = effect = graph()->NewNode(simplified()->LoadField(access), |
138 object, effect, control); | 145 object, effect, control); |
139 EXPECT_CALL(editor, ReplaceWithValue(load2, load1, load1, _)); | 146 EXPECT_CALL(editor, ReplaceWithValue(load2, load1, load1, _)); |
140 Reduction r = load_elimination.Reduce(load2); | 147 Reduction r = load_elimination.Reduce(load2); |
141 ASSERT_TRUE(r.Changed()); | 148 ASSERT_TRUE(r.Changed()); |
142 EXPECT_EQ(load1, r.replacement()); | 149 EXPECT_EQ(load1, r.replacement()); |
143 } | 150 } |
144 | 151 |
145 TEST_F(LoadEliminationTest, StoreFieldAndLoadField) { | 152 TEST_F(LoadEliminationTest, StoreFieldAndLoadField) { |
146 Node* object = Parameter(Type::Any(), 0); | 153 Node* object = Parameter(Type::Any(), 0); |
147 Node* value = Parameter(Type::Any(), 1); | 154 Node* value = Parameter(Type::Any(), 1); |
148 Node* effect = graph()->start(); | 155 Node* effect = graph()->start(); |
149 Node* control = graph()->start(); | 156 Node* control = graph()->start(); |
150 FieldAccess access = {kTaggedBase, | 157 FieldAccess access = {kTaggedBase, |
151 kPointerSize, | 158 kPointerSize, |
152 MaybeHandle<Name>(), | 159 MaybeHandle<Name>(), |
153 Type::Any(), | 160 Type::Any(), |
154 MachineType::AnyTagged(), | 161 MachineType::AnyTagged(), |
155 kNoWriteBarrier}; | 162 kNoWriteBarrier}; |
156 | 163 |
157 StrictMock<MockAdvancedReducerEditor> editor; | 164 StrictMock<MockAdvancedReducerEditor> editor; |
158 LoadElimination load_elimination(&editor, zone()); | 165 LoadElimination load_elimination(&editor, jsgraph(), zone()); |
159 | 166 |
160 load_elimination.Reduce(graph()->start()); | 167 load_elimination.Reduce(graph()->start()); |
161 | 168 |
162 Node* store = effect = graph()->NewNode(simplified()->StoreField(access), | 169 Node* store = effect = graph()->NewNode(simplified()->StoreField(access), |
163 object, value, effect, control); | 170 object, value, effect, control); |
164 load_elimination.Reduce(store); | 171 load_elimination.Reduce(store); |
165 | 172 |
166 Node* load = effect = graph()->NewNode(simplified()->LoadField(access), | 173 Node* load = effect = graph()->NewNode(simplified()->LoadField(access), |
167 object, effect, control); | 174 object, effect, control); |
168 EXPECT_CALL(editor, ReplaceWithValue(load, value, store, _)); | 175 EXPECT_CALL(editor, ReplaceWithValue(load, value, store, _)); |
169 Reduction r = load_elimination.Reduce(load); | 176 Reduction r = load_elimination.Reduce(load); |
170 ASSERT_TRUE(r.Changed()); | 177 ASSERT_TRUE(r.Changed()); |
171 EXPECT_EQ(value, r.replacement()); | 178 EXPECT_EQ(value, r.replacement()); |
172 } | 179 } |
173 | 180 |
174 TEST_F(LoadEliminationTest, StoreFieldAndStoreElementAndLoadField) { | 181 TEST_F(LoadEliminationTest, StoreFieldAndStoreElementAndLoadField) { |
175 Node* object = Parameter(Type::Any(), 0); | 182 Node* object = Parameter(Type::Any(), 0); |
176 Node* value = Parameter(Type::Any(), 1); | 183 Node* value = Parameter(Type::Any(), 1); |
177 Node* index = Parameter(Type::UnsignedSmall(), 2); | 184 Node* index = Parameter(Type::UnsignedSmall(), 2); |
178 Node* effect = graph()->start(); | 185 Node* effect = graph()->start(); |
179 Node* control = graph()->start(); | 186 Node* control = graph()->start(); |
180 FieldAccess access = {kTaggedBase, | 187 FieldAccess access = {kTaggedBase, |
181 kPointerSize, | 188 kPointerSize, |
182 MaybeHandle<Name>(), | 189 MaybeHandle<Name>(), |
183 Type::Any(), | 190 Type::Any(), |
184 MachineType::AnyTagged(), | 191 MachineType::AnyTagged(), |
185 kNoWriteBarrier}; | 192 kNoWriteBarrier}; |
186 | 193 |
187 StrictMock<MockAdvancedReducerEditor> editor; | 194 StrictMock<MockAdvancedReducerEditor> editor; |
188 LoadElimination load_elimination(&editor, zone()); | 195 LoadElimination load_elimination(&editor, jsgraph(), zone()); |
189 | 196 |
190 load_elimination.Reduce(graph()->start()); | 197 load_elimination.Reduce(graph()->start()); |
191 | 198 |
192 Node* store1 = effect = graph()->NewNode(simplified()->StoreField(access), | 199 Node* store1 = effect = graph()->NewNode(simplified()->StoreField(access), |
193 object, value, effect, control); | 200 object, value, effect, control); |
194 load_elimination.Reduce(store1); | 201 load_elimination.Reduce(store1); |
195 | 202 |
196 Node* store2 = effect = graph()->NewNode( | 203 Node* store2 = effect = graph()->NewNode( |
197 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), object, | 204 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), object, |
198 index, object, effect, control); | 205 index, object, effect, control); |
199 load_elimination.Reduce(store2); | 206 load_elimination.Reduce(store2); |
200 | 207 |
201 Node* load = effect = graph()->NewNode(simplified()->LoadField(access), | 208 Node* load = effect = graph()->NewNode(simplified()->LoadField(access), |
202 object, effect, control); | 209 object, effect, control); |
203 EXPECT_CALL(editor, ReplaceWithValue(load, value, store2, _)); | 210 EXPECT_CALL(editor, ReplaceWithValue(load, value, store2, _)); |
204 Reduction r = load_elimination.Reduce(load); | 211 Reduction r = load_elimination.Reduce(load); |
205 ASSERT_TRUE(r.Changed()); | 212 ASSERT_TRUE(r.Changed()); |
206 EXPECT_EQ(value, r.replacement()); | 213 EXPECT_EQ(value, r.replacement()); |
207 } | 214 } |
208 | 215 |
209 } // namespace compiler | 216 } // namespace compiler |
210 } // namespace internal | 217 } // namespace internal |
211 } // namespace v8 | 218 } // namespace v8 |
OLD | NEW |