| OLD | NEW |
| 1 // Copyright 2014 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/access-builder.h" | 6 #include "src/compiler/access-builder.h" |
| 6 #include "src/compiler/load-elimination.h" | 7 #include "src/compiler/node.h" |
| 7 #include "src/compiler/simplified-operator.h" | 8 #include "src/compiler/simplified-operator.h" |
| 8 #include "test/unittests/compiler/graph-unittest.h" | 9 #include "test/unittests/compiler/graph-unittest.h" |
| 9 #include "test/unittests/compiler/node-test-utils.h" | 10 #include "test/unittests/compiler/node-test-utils.h" |
| 10 | 11 |
| 11 namespace v8 { | 12 namespace v8 { |
| 12 namespace internal { | 13 namespace internal { |
| 13 namespace compiler { | 14 namespace compiler { |
| 14 | 15 |
| 15 class LoadEliminationTest : public TypedGraphTest { | 16 class LoadEliminationTest : public TypedGraphTest { |
| 16 public: | 17 public: |
| 17 LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {} | 18 LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {} |
| 18 ~LoadEliminationTest() override {} | 19 ~LoadEliminationTest() override {} |
| 19 | 20 |
| 20 protected: | 21 protected: |
| 21 Reduction Reduce(Node* node) { | 22 void Run() { |
| 22 // TODO(titzer): mock the GraphReducer here for better unit testing. | 23 LoadElimination load_elimination(graph(), zone()); |
| 23 GraphReducer graph_reducer(zone(), graph()); | 24 load_elimination.Run(); |
| 24 LoadElimination reducer(&graph_reducer, graph(), simplified()); | |
| 25 return reducer.Reduce(node); | |
| 26 } | 25 } |
| 27 | 26 |
| 28 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 27 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
| 29 | 28 |
| 30 private: | 29 private: |
| 31 SimplifiedOperatorBuilder simplified_; | 30 SimplifiedOperatorBuilder simplified_; |
| 32 }; | 31 }; |
| 33 | 32 |
| 34 | 33 TEST_F(LoadEliminationTest, LoadFieldAndLoadField) { |
| 35 TEST_F(LoadEliminationTest, LoadFieldWithStoreField) { | 34 Node* object = Parameter(Type::Any(), 0); |
| 36 Node* object1 = Parameter(Type::Any(), 0); | |
| 37 Node* object2 = Parameter(Type::Any(), 1); | |
| 38 Node* value = Parameter(Type::Any(), 2); | |
| 39 Node* effect = graph()->start(); | 35 Node* effect = graph()->start(); |
| 40 Node* control = graph()->start(); | 36 Node* control = graph()->start(); |
| 37 FieldAccess access = {kTaggedBase, |
| 38 kPointerSize, |
| 39 MaybeHandle<Name>(), |
| 40 Type::Any(), |
| 41 MachineType::AnyTagged(), |
| 42 kNoWriteBarrier}; |
| 43 Node* load1 = effect = graph()->NewNode(simplified()->LoadField(access), |
| 44 object, effect, control); |
| 45 Node* load2 = effect = graph()->NewNode(simplified()->LoadField(access), |
| 46 object, effect, control); |
| 47 control = graph()->NewNode(common()->Return(), load2, effect, control); |
| 48 graph()->end()->ReplaceInput(0, control); |
| 41 | 49 |
| 42 FieldAccess access1 = AccessBuilder::ForContextSlot(42); | 50 Run(); |
| 43 Node* store1 = graph()->NewNode(simplified()->StoreField(access1), object1, | |
| 44 value, effect, control); | |
| 45 Reduction r1 = Reduce(graph()->NewNode(simplified()->LoadField(access1), | |
| 46 object1, store1, control)); | |
| 47 ASSERT_TRUE(r1.Changed()); | |
| 48 EXPECT_EQ(value, r1.replacement()); | |
| 49 | 51 |
| 50 FieldAccess access2 = AccessBuilder::ForMap(); | 52 EXPECT_THAT(graph()->end(), IsEnd(IsReturn(load1, load1, graph()->start()))); |
| 51 Node* store2 = graph()->NewNode(simplified()->StoreField(access2), object1, | 53 } |
| 52 object2, store1, control); | |
| 53 Reduction r2 = Reduce(graph()->NewNode(simplified()->LoadField(access2), | |
| 54 object1, store2, control)); | |
| 55 ASSERT_TRUE(r2.Changed()); | |
| 56 EXPECT_EQ(object2, r2.replacement()); | |
| 57 | 54 |
| 58 Node* store3 = graph()->NewNode( | 55 TEST_F(LoadEliminationTest, StoreFieldAndLoadField) { |
| 59 simplified()->StoreBuffer(BufferAccess(kExternalInt8Array)), object2, | 56 Node* object = Parameter(Type::Any(), 0); |
| 60 value, Int32Constant(10), object1, store2, control); | 57 Node* value = Parameter(Type::Any(), 1); |
| 58 Node* effect = graph()->start(); |
| 59 Node* control = graph()->start(); |
| 60 FieldAccess access = {kTaggedBase, |
| 61 kPointerSize, |
| 62 MaybeHandle<Name>(), |
| 63 Type::Any(), |
| 64 MachineType::AnyTagged(), |
| 65 kNoWriteBarrier}; |
| 66 Node* store = effect = graph()->NewNode(simplified()->StoreField(access), |
| 67 object, value, effect, control); |
| 68 Node* load = effect = graph()->NewNode(simplified()->LoadField(access), |
| 69 object, effect, control); |
| 70 control = graph()->NewNode(common()->Return(), load, effect, control); |
| 71 graph()->end()->ReplaceInput(0, control); |
| 61 | 72 |
| 62 Reduction r3 = Reduce(graph()->NewNode(simplified()->LoadField(access1), | 73 Run(); |
| 63 object2, store3, control)); | |
| 64 ASSERT_FALSE(r3.Changed()); | |
| 65 | 74 |
| 66 Reduction r4 = Reduce(graph()->NewNode(simplified()->LoadField(access1), | 75 EXPECT_THAT(graph()->end(), IsEnd(IsReturn(value, store, graph()->start()))); |
| 67 object1, store3, control)); | |
| 68 ASSERT_TRUE(r4.Changed()); | |
| 69 EXPECT_EQ(value, r4.replacement()); | |
| 70 } | 76 } |
| 71 | 77 |
| 72 } // namespace compiler | 78 } // namespace compiler |
| 73 } // namespace internal | 79 } // namespace internal |
| 74 } // namespace v8 | 80 } // namespace v8 |
| OLD | NEW |