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