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