| 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 |