Chromium Code Reviews| Index: src/compiler/load-elimination.h |
| diff --git a/src/compiler/load-elimination.h b/src/compiler/load-elimination.h |
| index 5b926488d5a1c4645fcb452c115d1613572c35c6..4b5cf4e2be2e41843ed29a33f7e955c81bbc0881 100644 |
| --- a/src/compiler/load-elimination.h |
| +++ b/src/compiler/load-elimination.h |
| @@ -5,30 +5,172 @@ |
| #ifndef V8_COMPILER_LOAD_ELIMINATION_H_ |
| #define V8_COMPILER_LOAD_ELIMINATION_H_ |
| +#include "src/compiler/graph-reducer.h" |
| + |
| namespace v8 { |
| namespace internal { |
| - |
| -// Forward declarations. |
| -class Zone; |
| - |
| namespace compiler { |
| -// Forward declarations. |
| -class Graph; |
| +// Foward declarations. |
| +struct FieldAccess; |
| -// Eliminates redundant loads via scalar replacement of aggregates. |
| -class LoadElimination final { |
| +class LoadElimination final : public AdvancedReducer { |
| public: |
| - LoadElimination(Graph* graph, Zone* zone) : graph_(graph), zone_(zone) {} |
| + LoadElimination(Editor* editor, Zone* zone) |
| + : AdvancedReducer(editor), node_states_(zone) {} |
| + ~LoadElimination() final {} |
| - void Run(); |
| + Reduction Reduce(Node* node) final; |
| private: |
| - Graph* graph() const { return graph_; } |
| - Zone* zone() const { return zone_; } |
| + static const size_t kMaxTrackedElements = 8; |
| + |
| + // Abstract state to approximate the current state of an element along the |
| + // effect paths through the graph. |
| + class AbstractElements final : public ZoneObject { |
| + public: |
| + explicit AbstractElements(Zone* zone) { |
| + for (size_t i = 0; i < arraysize(elements_); ++i) { |
| + elements_[i] = Element(); |
| + } |
| + } |
| + AbstractElements(Node* object, Node* index, Node* value, Zone* zone) |
| + : AbstractElements(zone) { |
| + elements_[next_index_++] = Element(object, index, value); |
| + } |
| + |
| + AbstractElements const* Extend(Node* object, Node* index, Node* value, |
| + Zone* zone) const { |
| + AbstractElements* that = new (zone) AbstractElements(*this); |
| + that->elements_[that->next_index_] = Element(object, index, value); |
| + that->next_index_ = (that->next_index_ + 1) % arraysize(elements_); |
| + return that; |
| + } |
| + Node* Lookup(Node* object, Node* index) const; |
| + AbstractElements const* Kill(Node* object, Node* index, Zone* zone) const; |
| + bool Equals(AbstractElements const* that) const; |
| + AbstractElements const* Merge(AbstractElements const* that, |
| + Zone* zone) const; |
| + |
| + private: |
| + struct Element { |
| + Element() {} |
| + Element(Node* object, Node* index, Node* value) |
| + : object(object), index(index), value(value) {} |
| + |
| + Node* object = nullptr; |
| + Node* index = nullptr; |
| + Node* value = nullptr; |
| + }; |
| + |
| + Element elements_[kMaxTrackedElements]; |
| + size_t next_index_ = 0; |
| + }; |
| + |
| + // Abstract state to approximate the current state of a certain field along |
| + // the effect paths through the graph. |
| + class AbstractField final : public ZoneObject { |
| + public: |
| + explicit AbstractField(Zone* zone) : info_for_node_(zone) {} |
| + AbstractField(Node* object, Node* value, Zone* zone) |
| + : info_for_node_(zone) { |
| + info_for_node_.insert(std::make_pair(object, value)); |
| + } |
| + |
| + AbstractField const* Extend(Node* object, Node* value, Zone* zone) const { |
| + AbstractField* that = new (zone) AbstractField(zone); |
| + that->info_for_node_ = this->info_for_node_; |
| + that->info_for_node_.insert(std::make_pair(object, value)); |
| + return that; |
| + } |
| + Node* Lookup(Node* object) const; |
| + AbstractField const* Kill(Node* object, Zone* zone) const; |
| + bool Equals(AbstractField const* that) const { |
| + return this == that || this->info_for_node_ == that->info_for_node_; |
| + } |
| + AbstractField const* Merge(AbstractField const* that, Zone* zone) const { |
| + if (this->Equals(that)) return this; |
| + AbstractField* copy = new (zone) AbstractField(zone); |
| + for (auto this_it : this->info_for_node_) { |
| + Node* this_object = this_it.first; |
| + Node* this_value = this_it.second; |
| + auto that_it = that->info_for_node_.find(this_object); |
| + if (that_it != that->info_for_node_.end() && |
| + that_it->second == this_value) { |
| + copy->info_for_node_.insert(this_it); |
| + } |
| + } |
| + return copy; |
| + } |
| + |
| + private: |
| + ZoneMap<Node*, Node*> info_for_node_; |
|
Jarin
2016/07/25 11:22:27
Please, use the id on the left-hand side.
Benedikt Meurer
2016/07/25 11:28:42
We cannot fix this currently, as we need the objec
|
| + }; |
| + |
| + static size_t const kMaxTrackedFields = 16; |
| + |
| + class AbstractState final : public ZoneObject { |
| + public: |
| + AbstractState() { |
| + for (size_t i = 0; i < arraysize(fields_); ++i) { |
| + fields_[i] = nullptr; |
| + } |
| + } |
| + |
| + bool Equals(AbstractState const* that) const; |
| + void Merge(AbstractState const* that, Zone* zone); |
| + |
| + AbstractState const* AddField(Node* object, size_t index, Node* value, |
| + Zone* zone) const; |
| + AbstractState const* KillField(Node* object, size_t index, |
| + Zone* zone) const; |
| + Node* LookupField(Node* object, size_t index) const; |
| + |
| + AbstractState const* AddElement(Node* object, Node* index, Node* value, |
| + Zone* zone) const; |
| + AbstractState const* KillElement(Node* object, Node* index, |
| + Zone* zone) const; |
| + Node* LookupElement(Node* object, Node* index) const; |
| + |
| + private: |
| + AbstractElements const* elements_ = nullptr; |
| + AbstractField const* fields_[kMaxTrackedFields]; |
| + }; |
| + |
| + class AbstractStateForEffectNodes final : public ZoneObject { |
| + public: |
| + explicit AbstractStateForEffectNodes(Zone* zone) : info_for_node_(zone) {} |
| + AbstractState const* Get(Node* node) const; |
| + void Set(Node* node, AbstractState const* state); |
| + |
| + Zone* zone() const { return info_for_node_.get_allocator().zone(); } |
| + |
| + private: |
| + ZoneVector<AbstractState const*> info_for_node_; |
| + }; |
| + |
| + Reduction ReduceLoadField(Node* node); |
| + Reduction ReduceStoreField(Node* node); |
| + Reduction ReduceLoadElement(Node* node); |
| + Reduction ReduceStoreElement(Node* node); |
| + Reduction ReduceEffectPhi(Node* node); |
| + Reduction ReduceStart(Node* node); |
| + Reduction ReduceOtherNode(Node* node); |
| + |
| + Reduction UpdateState(Node* node, AbstractState const* state); |
| + |
| + AbstractState const* ComputeLoopState(Node* node, |
| + AbstractState const* state) const; |
| + |
| + static int FieldIndexOf(FieldAccess const& access); |
| + |
| + AbstractState const* empty_state() const { return &empty_state_; } |
| + Zone* zone() const { return node_states_.zone(); } |
| + |
| + AbstractState const empty_state_; |
| + AbstractStateForEffectNodes node_states_; |
| - Graph* const graph_; |
| - Zone* const zone_; |
| + DISALLOW_COPY_AND_ASSIGN(LoadElimination); |
| }; |
| } // namespace compiler |