| 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_;
|
| + };
|
| +
|
| + 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
|
|
|