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 #ifndef V8_COMPILER_LOAD_ELIMINATION_H_ | 5 #ifndef V8_COMPILER_LOAD_ELIMINATION_H_ |
6 #define V8_COMPILER_LOAD_ELIMINATION_H_ | 6 #define V8_COMPILER_LOAD_ELIMINATION_H_ |
7 | 7 |
| 8 #include "src/compiler/graph-reducer.h" |
| 9 |
8 namespace v8 { | 10 namespace v8 { |
9 namespace internal { | 11 namespace internal { |
10 | |
11 // Forward declarations. | |
12 class Zone; | |
13 | |
14 namespace compiler { | 12 namespace compiler { |
15 | 13 |
16 // Forward declarations. | 14 // Foward declarations. |
17 class Graph; | 15 struct FieldAccess; |
18 | 16 |
19 // Eliminates redundant loads via scalar replacement of aggregates. | 17 class LoadElimination final : public AdvancedReducer { |
20 class LoadElimination final { | |
21 public: | 18 public: |
22 LoadElimination(Graph* graph, Zone* zone) : graph_(graph), zone_(zone) {} | 19 LoadElimination(Editor* editor, Zone* zone) |
| 20 : AdvancedReducer(editor), node_states_(zone) {} |
| 21 ~LoadElimination() final {} |
23 | 22 |
24 void Run(); | 23 Reduction Reduce(Node* node) final; |
25 | 24 |
26 private: | 25 private: |
27 Graph* graph() const { return graph_; } | 26 static const size_t kMaxTrackedElements = 8; |
28 Zone* zone() const { return zone_; } | |
29 | 27 |
30 Graph* const graph_; | 28 // Abstract state to approximate the current state of an element along the |
31 Zone* const zone_; | 29 // effect paths through the graph. |
| 30 class AbstractElements final : public ZoneObject { |
| 31 public: |
| 32 explicit AbstractElements(Zone* zone) { |
| 33 for (size_t i = 0; i < arraysize(elements_); ++i) { |
| 34 elements_[i] = Element(); |
| 35 } |
| 36 } |
| 37 AbstractElements(Node* object, Node* index, Node* value, Zone* zone) |
| 38 : AbstractElements(zone) { |
| 39 elements_[next_index_++] = Element(object, index, value); |
| 40 } |
| 41 |
| 42 AbstractElements const* Extend(Node* object, Node* index, Node* value, |
| 43 Zone* zone) const { |
| 44 AbstractElements* that = new (zone) AbstractElements(*this); |
| 45 that->elements_[that->next_index_] = Element(object, index, value); |
| 46 that->next_index_ = (that->next_index_ + 1) % arraysize(elements_); |
| 47 return that; |
| 48 } |
| 49 Node* Lookup(Node* object, Node* index) const; |
| 50 AbstractElements const* Kill(Node* object, Node* index, Zone* zone) const; |
| 51 bool Equals(AbstractElements const* that) const; |
| 52 AbstractElements const* Merge(AbstractElements const* that, |
| 53 Zone* zone) const; |
| 54 |
| 55 private: |
| 56 struct Element { |
| 57 Element() {} |
| 58 Element(Node* object, Node* index, Node* value) |
| 59 : object(object), index(index), value(value) {} |
| 60 |
| 61 Node* object = nullptr; |
| 62 Node* index = nullptr; |
| 63 Node* value = nullptr; |
| 64 }; |
| 65 |
| 66 Element elements_[kMaxTrackedElements]; |
| 67 size_t next_index_ = 0; |
| 68 }; |
| 69 |
| 70 // Abstract state to approximate the current state of a certain field along |
| 71 // the effect paths through the graph. |
| 72 class AbstractField final : public ZoneObject { |
| 73 public: |
| 74 explicit AbstractField(Zone* zone) : info_for_node_(zone) {} |
| 75 AbstractField(Node* object, Node* value, Zone* zone) |
| 76 : info_for_node_(zone) { |
| 77 info_for_node_.insert(std::make_pair(object, value)); |
| 78 } |
| 79 |
| 80 AbstractField const* Extend(Node* object, Node* value, Zone* zone) const { |
| 81 AbstractField* that = new (zone) AbstractField(zone); |
| 82 that->info_for_node_ = this->info_for_node_; |
| 83 that->info_for_node_.insert(std::make_pair(object, value)); |
| 84 return that; |
| 85 } |
| 86 Node* Lookup(Node* object) const; |
| 87 AbstractField const* Kill(Node* object, Zone* zone) const; |
| 88 bool Equals(AbstractField const* that) const { |
| 89 return this == that || this->info_for_node_ == that->info_for_node_; |
| 90 } |
| 91 AbstractField const* Merge(AbstractField const* that, Zone* zone) const { |
| 92 if (this->Equals(that)) return this; |
| 93 AbstractField* copy = new (zone) AbstractField(zone); |
| 94 for (auto this_it : this->info_for_node_) { |
| 95 Node* this_object = this_it.first; |
| 96 Node* this_value = this_it.second; |
| 97 auto that_it = that->info_for_node_.find(this_object); |
| 98 if (that_it != that->info_for_node_.end() && |
| 99 that_it->second == this_value) { |
| 100 copy->info_for_node_.insert(this_it); |
| 101 } |
| 102 } |
| 103 return copy; |
| 104 } |
| 105 |
| 106 private: |
| 107 ZoneMap<Node*, Node*> info_for_node_; |
| 108 }; |
| 109 |
| 110 static size_t const kMaxTrackedFields = 16; |
| 111 |
| 112 class AbstractState final : public ZoneObject { |
| 113 public: |
| 114 AbstractState() { |
| 115 for (size_t i = 0; i < arraysize(fields_); ++i) { |
| 116 fields_[i] = nullptr; |
| 117 } |
| 118 } |
| 119 |
| 120 bool Equals(AbstractState const* that) const; |
| 121 void Merge(AbstractState const* that, Zone* zone); |
| 122 |
| 123 AbstractState const* AddField(Node* object, size_t index, Node* value, |
| 124 Zone* zone) const; |
| 125 AbstractState const* KillField(Node* object, size_t index, |
| 126 Zone* zone) const; |
| 127 Node* LookupField(Node* object, size_t index) const; |
| 128 |
| 129 AbstractState const* AddElement(Node* object, Node* index, Node* value, |
| 130 Zone* zone) const; |
| 131 AbstractState const* KillElement(Node* object, Node* index, |
| 132 Zone* zone) const; |
| 133 Node* LookupElement(Node* object, Node* index) const; |
| 134 |
| 135 private: |
| 136 AbstractElements const* elements_ = nullptr; |
| 137 AbstractField const* fields_[kMaxTrackedFields]; |
| 138 }; |
| 139 |
| 140 class AbstractStateForEffectNodes final : public ZoneObject { |
| 141 public: |
| 142 explicit AbstractStateForEffectNodes(Zone* zone) : info_for_node_(zone) {} |
| 143 AbstractState const* Get(Node* node) const; |
| 144 void Set(Node* node, AbstractState const* state); |
| 145 |
| 146 Zone* zone() const { return info_for_node_.get_allocator().zone(); } |
| 147 |
| 148 private: |
| 149 ZoneVector<AbstractState const*> info_for_node_; |
| 150 }; |
| 151 |
| 152 Reduction ReduceLoadField(Node* node); |
| 153 Reduction ReduceStoreField(Node* node); |
| 154 Reduction ReduceLoadElement(Node* node); |
| 155 Reduction ReduceStoreElement(Node* node); |
| 156 Reduction ReduceEffectPhi(Node* node); |
| 157 Reduction ReduceStart(Node* node); |
| 158 Reduction ReduceOtherNode(Node* node); |
| 159 |
| 160 Reduction UpdateState(Node* node, AbstractState const* state); |
| 161 |
| 162 AbstractState const* ComputeLoopState(Node* node, |
| 163 AbstractState const* state) const; |
| 164 |
| 165 static int FieldIndexOf(FieldAccess const& access); |
| 166 |
| 167 AbstractState const* empty_state() const { return &empty_state_; } |
| 168 Zone* zone() const { return node_states_.zone(); } |
| 169 |
| 170 AbstractState const empty_state_; |
| 171 AbstractStateForEffectNodes node_states_; |
| 172 |
| 173 DISALLOW_COPY_AND_ASSIGN(LoadElimination); |
32 }; | 174 }; |
33 | 175 |
34 } // namespace compiler | 176 } // namespace compiler |
35 } // namespace internal | 177 } // namespace internal |
36 } // namespace v8 | 178 } // namespace v8 |
37 | 179 |
38 #endif // V8_COMPILER_LOAD_ELIMINATION_H_ | 180 #endif // V8_COMPILER_LOAD_ELIMINATION_H_ |
OLD | NEW |