 Chromium Code Reviews
 Chromium Code Reviews Issue 2164253002:
  [turbofan] New GraphReducer based LoadElimination.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 2164253002:
  [turbofan] New GraphReducer based LoadElimination.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| 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 |