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