Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: src/hydrogen-gvn.cc

Issue 144423010: Improve inobject field tracking during GVN. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-gvn.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "hydrogen.h" 28 #include "hydrogen.h"
29 #include "hydrogen-gvn.h" 29 #include "hydrogen-gvn.h"
30 #include "v8.h" 30 #include "v8.h"
31 31
32 namespace v8 { 32 namespace v8 {
33 namespace internal { 33 namespace internal {
34 34
35 class HValueMap: public ZoneObject { 35 class HInstructionMap V8_FINAL : public ZoneObject {
36 public: 36 public:
37 explicit HValueMap(Zone* zone) 37 HInstructionMap(Zone* zone, SideEffectsTracker* side_effects_tracker)
38 : array_size_(0), 38 : array_size_(0),
39 lists_size_(0), 39 lists_size_(0),
40 count_(0), 40 count_(0),
41 present_flags_(0),
42 array_(NULL), 41 array_(NULL),
43 lists_(NULL), 42 lists_(NULL),
44 free_list_head_(kNil) { 43 free_list_head_(kNil),
44 side_effects_tracker_(side_effects_tracker) {
45 ResizeLists(kInitialSize, zone); 45 ResizeLists(kInitialSize, zone);
46 Resize(kInitialSize, zone); 46 Resize(kInitialSize, zone);
47 } 47 }
48 48
49 void Kill(GVNFlagSet flags); 49 void Kill(SideEffects side_effects);
50 50
51 void Add(HValue* value, Zone* zone) { 51 void Add(HInstruction* instr, Zone* zone) {
52 present_flags_.Add(value->gvn_flags()); 52 present_depends_on_.Add(side_effects_tracker_->ComputeDependsOn(instr));
53 Insert(value, zone); 53 Insert(instr, zone);
54 } 54 }
55 55
56 HValue* Lookup(HValue* value) const; 56 HInstruction* Lookup(HInstruction* instr) const;
57 57
58 HValueMap* Copy(Zone* zone) const { 58 HInstructionMap* Copy(Zone* zone) const {
59 return new(zone) HValueMap(zone, this); 59 return new(zone) HInstructionMap(zone, this);
60 } 60 }
61 61
62 bool IsEmpty() const { return count_ == 0; } 62 bool IsEmpty() const { return count_ == 0; }
63 63
64 private: 64 private:
65 // A linked list of HValue* values. Stored in arrays. 65 // A linked list of HInstruction* values. Stored in arrays.
66 struct HValueMapListElement { 66 struct HInstructionMapListElement {
67 HValue* value; 67 HInstruction* instr;
68 int next; // Index in the array of the next list element. 68 int next; // Index in the array of the next list element.
69 }; 69 };
70 static const int kNil = -1; // The end of a linked list 70 static const int kNil = -1; // The end of a linked list
71 71
72 // Must be a power of 2. 72 // Must be a power of 2.
73 static const int kInitialSize = 16; 73 static const int kInitialSize = 16;
74 74
75 HValueMap(Zone* zone, const HValueMap* other); 75 HInstructionMap(Zone* zone, const HInstructionMap* other);
76 76
77 void Resize(int new_size, Zone* zone); 77 void Resize(int new_size, Zone* zone);
78 void ResizeLists(int new_size, Zone* zone); 78 void ResizeLists(int new_size, Zone* zone);
79 void Insert(HValue* value, Zone* zone); 79 void Insert(HInstruction* instr, Zone* zone);
80 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); } 80 uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
81 81
82 int array_size_; 82 int array_size_;
83 int lists_size_; 83 int lists_size_;
84 int count_; // The number of values stored in the HValueMap. 84 int count_; // The number of values stored in the HInstructionMap.
85 GVNFlagSet present_flags_; // All flags that are in any value in the 85 SideEffects present_depends_on_;
86 // HValueMap. 86 HInstructionMapListElement* array_;
87 HValueMapListElement* array_; // Primary store - contains the first value 87 // Primary store - contains the first value
88 // with a given hash. Colliding elements are stored in linked lists. 88 // with a given hash. Colliding elements are stored in linked lists.
89 HValueMapListElement* lists_; // The linked lists containing hash collisions. 89 HInstructionMapListElement* lists_;
90 // The linked lists containing hash collisions.
90 int free_list_head_; // Unused elements in lists_ are on the free list. 91 int free_list_head_; // Unused elements in lists_ are on the free list.
92 SideEffectsTracker* side_effects_tracker_;
91 }; 93 };
92 94
93 95
94 class HSideEffectMap BASE_EMBEDDED { 96 class HSideEffectMap V8_FINAL BASE_EMBEDDED {
95 public: 97 public:
96 HSideEffectMap(); 98 HSideEffectMap();
97 explicit HSideEffectMap(HSideEffectMap* other); 99 explicit HSideEffectMap(HSideEffectMap* other);
98 HSideEffectMap& operator= (const HSideEffectMap& other); 100 HSideEffectMap& operator= (const HSideEffectMap& other);
99 101
100 void Kill(GVNFlagSet flags); 102 void Kill(SideEffects side_effects);
101 103
102 void Store(GVNFlagSet flags, HInstruction* instr); 104 void Store(SideEffects side_effects, HInstruction* instr);
103 105
104 bool IsEmpty() const { return count_ == 0; } 106 bool IsEmpty() const { return count_ == 0; }
105 107
106 inline HInstruction* operator[](int i) const { 108 inline HInstruction* operator[](int i) const {
107 ASSERT(0 <= i); 109 ASSERT(0 <= i);
108 ASSERT(i < kNumberOfTrackedSideEffects); 110 ASSERT(i < kNumberOfTrackedSideEffects);
109 return data_[i]; 111 return data_[i];
110 } 112 }
111 inline HInstruction* at(int i) const { return operator[](i); } 113 inline HInstruction* at(int i) const { return operator[](i); }
112 114
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 if (FLAG_trace_gvn) { \ 147 if (FLAG_trace_gvn) { \
146 TraceGVN(msg, a1, a2, a3, a4); \ 148 TraceGVN(msg, a1, a2, a3, a4); \
147 } 149 }
148 150
149 #define TRACE_GVN_5(msg, a1, a2, a3, a4, a5) \ 151 #define TRACE_GVN_5(msg, a1, a2, a3, a4, a5) \
150 if (FLAG_trace_gvn) { \ 152 if (FLAG_trace_gvn) { \
151 TraceGVN(msg, a1, a2, a3, a4, a5); \ 153 TraceGVN(msg, a1, a2, a3, a4, a5); \
152 } 154 }
153 155
154 156
155 HValueMap::HValueMap(Zone* zone, const HValueMap* other) 157 HInstructionMap::HInstructionMap(Zone* zone, const HInstructionMap* other)
156 : array_size_(other->array_size_), 158 : array_size_(other->array_size_),
157 lists_size_(other->lists_size_), 159 lists_size_(other->lists_size_),
158 count_(other->count_), 160 count_(other->count_),
159 present_flags_(other->present_flags_), 161 present_depends_on_(other->present_depends_on_),
160 array_(zone->NewArray<HValueMapListElement>(other->array_size_)), 162 array_(zone->NewArray<HInstructionMapListElement>(other->array_size_)),
161 lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)), 163 lists_(zone->NewArray<HInstructionMapListElement>(other->lists_size_)),
162 free_list_head_(other->free_list_head_) { 164 free_list_head_(other->free_list_head_),
165 side_effects_tracker_(other->side_effects_tracker_) {
163 OS::MemCopy( 166 OS::MemCopy(
164 array_, other->array_, array_size_ * sizeof(HValueMapListElement)); 167 array_, other->array_, array_size_ * sizeof(HInstructionMapListElement));
165 OS::MemCopy( 168 OS::MemCopy(
166 lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); 169 lists_, other->lists_, lists_size_ * sizeof(HInstructionMapListElement));
167 } 170 }
168 171
169 172
170 void HValueMap::Kill(GVNFlagSet flags) { 173 void HInstructionMap::Kill(SideEffects changes) {
171 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags); 174 if (!present_depends_on_.ContainsAnyOf(changes)) return;
172 if (!present_flags_.ContainsAnyOf(depends_flags)) return; 175 present_depends_on_.RemoveAll();
173 present_flags_.RemoveAll();
174 for (int i = 0; i < array_size_; ++i) { 176 for (int i = 0; i < array_size_; ++i) {
175 HValue* value = array_[i].value; 177 HInstruction* instr = array_[i].instr;
176 if (value != NULL) { 178 if (instr != NULL) {
177 // Clear list of collisions first, so we know if it becomes empty. 179 // Clear list of collisions first, so we know if it becomes empty.
178 int kept = kNil; // List of kept elements. 180 int kept = kNil; // List of kept elements.
179 int next; 181 int next;
180 for (int current = array_[i].next; current != kNil; current = next) { 182 for (int current = array_[i].next; current != kNil; current = next) {
181 next = lists_[current].next; 183 next = lists_[current].next;
182 HValue* value = lists_[current].value; 184 HInstruction* instr = lists_[current].instr;
183 if (value->gvn_flags().ContainsAnyOf(depends_flags)) { 185 SideEffects depends_on = side_effects_tracker_->ComputeDependsOn(instr);
186 if (depends_on.ContainsAnyOf(changes)) {
184 // Drop it. 187 // Drop it.
185 count_--; 188 count_--;
186 lists_[current].next = free_list_head_; 189 lists_[current].next = free_list_head_;
187 free_list_head_ = current; 190 free_list_head_ = current;
188 } else { 191 } else {
189 // Keep it. 192 // Keep it.
190 lists_[current].next = kept; 193 lists_[current].next = kept;
191 kept = current; 194 kept = current;
192 present_flags_.Add(value->gvn_flags()); 195 present_depends_on_.Add(depends_on);
193 } 196 }
194 } 197 }
195 array_[i].next = kept; 198 array_[i].next = kept;
196 199
197 // Now possibly drop directly indexed element. 200 // Now possibly drop directly indexed element.
198 value = array_[i].value; 201 instr = array_[i].instr;
199 if (value->gvn_flags().ContainsAnyOf(depends_flags)) { // Drop it. 202 SideEffects depends_on = side_effects_tracker_->ComputeDependsOn(instr);
203 if (depends_on.ContainsAnyOf(changes)) { // Drop it.
200 count_--; 204 count_--;
201 int head = array_[i].next; 205 int head = array_[i].next;
202 if (head == kNil) { 206 if (head == kNil) {
203 array_[i].value = NULL; 207 array_[i].instr = NULL;
204 } else { 208 } else {
205 array_[i].value = lists_[head].value; 209 array_[i].instr = lists_[head].instr;
206 array_[i].next = lists_[head].next; 210 array_[i].next = lists_[head].next;
207 lists_[head].next = free_list_head_; 211 lists_[head].next = free_list_head_;
208 free_list_head_ = head; 212 free_list_head_ = head;
209 } 213 }
210 } else { 214 } else {
211 present_flags_.Add(value->gvn_flags()); // Keep it. 215 present_depends_on_.Add(depends_on); // Keep it.
212 } 216 }
213 } 217 }
214 } 218 }
215 } 219 }
216 220
217 221
218 HValue* HValueMap::Lookup(HValue* value) const { 222 HInstruction* HInstructionMap::Lookup(HInstruction* instr) const {
219 uint32_t hash = static_cast<uint32_t>(value->Hashcode()); 223 uint32_t hash = static_cast<uint32_t>(instr->Hashcode());
220 uint32_t pos = Bound(hash); 224 uint32_t pos = Bound(hash);
221 if (array_[pos].value != NULL) { 225 if (array_[pos].instr != NULL) {
222 if (array_[pos].value->Equals(value)) return array_[pos].value; 226 if (array_[pos].instr->Equals(instr)) return array_[pos].instr;
223 int next = array_[pos].next; 227 int next = array_[pos].next;
224 while (next != kNil) { 228 while (next != kNil) {
225 if (lists_[next].value->Equals(value)) return lists_[next].value; 229 if (lists_[next].instr->Equals(instr)) return lists_[next].instr;
226 next = lists_[next].next; 230 next = lists_[next].next;
227 } 231 }
228 } 232 }
229 return NULL; 233 return NULL;
230 } 234 }
231 235
232 236
233 void HValueMap::Resize(int new_size, Zone* zone) { 237 void HInstructionMap::Resize(int new_size, Zone* zone) {
234 ASSERT(new_size > count_); 238 ASSERT(new_size > count_);
235 // Hashing the values into the new array has no more collisions than in the 239 // Hashing the values into the new array has no more collisions than in the
236 // old hash map, so we can use the existing lists_ array, if we are careful. 240 // old hash map, so we can use the existing lists_ array, if we are careful.
237 241
238 // Make sure we have at least one free element. 242 // Make sure we have at least one free element.
239 if (free_list_head_ == kNil) { 243 if (free_list_head_ == kNil) {
240 ResizeLists(lists_size_ << 1, zone); 244 ResizeLists(lists_size_ << 1, zone);
241 } 245 }
242 246
243 HValueMapListElement* new_array = 247 HInstructionMapListElement* new_array =
244 zone->NewArray<HValueMapListElement>(new_size); 248 zone->NewArray<HInstructionMapListElement>(new_size);
245 memset(new_array, 0, sizeof(HValueMapListElement) * new_size); 249 memset(new_array, 0, sizeof(HInstructionMapListElement) * new_size);
246 250
247 HValueMapListElement* old_array = array_; 251 HInstructionMapListElement* old_array = array_;
248 int old_size = array_size_; 252 int old_size = array_size_;
249 253
250 int old_count = count_; 254 int old_count = count_;
251 count_ = 0; 255 count_ = 0;
252 // Do not modify present_flags_. It is currently correct. 256 // Do not modify present_depends_on_. It is currently correct.
253 array_size_ = new_size; 257 array_size_ = new_size;
254 array_ = new_array; 258 array_ = new_array;
255 259
256 if (old_array != NULL) { 260 if (old_array != NULL) {
257 // Iterate over all the elements in lists, rehashing them. 261 // Iterate over all the elements in lists, rehashing them.
258 for (int i = 0; i < old_size; ++i) { 262 for (int i = 0; i < old_size; ++i) {
259 if (old_array[i].value != NULL) { 263 if (old_array[i].instr != NULL) {
260 int current = old_array[i].next; 264 int current = old_array[i].next;
261 while (current != kNil) { 265 while (current != kNil) {
262 Insert(lists_[current].value, zone); 266 Insert(lists_[current].instr, zone);
263 int next = lists_[current].next; 267 int next = lists_[current].next;
264 lists_[current].next = free_list_head_; 268 lists_[current].next = free_list_head_;
265 free_list_head_ = current; 269 free_list_head_ = current;
266 current = next; 270 current = next;
267 } 271 }
268 // Rehash the directly stored value. 272 // Rehash the directly stored instruction.
269 Insert(old_array[i].value, zone); 273 Insert(old_array[i].instr, zone);
270 } 274 }
271 } 275 }
272 } 276 }
273 USE(old_count); 277 USE(old_count);
274 ASSERT(count_ == old_count); 278 ASSERT(count_ == old_count);
275 } 279 }
276 280
277 281
278 void HValueMap::ResizeLists(int new_size, Zone* zone) { 282 void HInstructionMap::ResizeLists(int new_size, Zone* zone) {
279 ASSERT(new_size > lists_size_); 283 ASSERT(new_size > lists_size_);
280 284
281 HValueMapListElement* new_lists = 285 HInstructionMapListElement* new_lists =
282 zone->NewArray<HValueMapListElement>(new_size); 286 zone->NewArray<HInstructionMapListElement>(new_size);
283 memset(new_lists, 0, sizeof(HValueMapListElement) * new_size); 287 memset(new_lists, 0, sizeof(HInstructionMapListElement) * new_size);
284 288
285 HValueMapListElement* old_lists = lists_; 289 HInstructionMapListElement* old_lists = lists_;
286 int old_size = lists_size_; 290 int old_size = lists_size_;
287 291
288 lists_size_ = new_size; 292 lists_size_ = new_size;
289 lists_ = new_lists; 293 lists_ = new_lists;
290 294
291 if (old_lists != NULL) { 295 if (old_lists != NULL) {
292 OS::MemCopy(lists_, old_lists, old_size * sizeof(HValueMapListElement)); 296 OS::MemCopy(
297 lists_, old_lists, old_size * sizeof(HInstructionMapListElement));
293 } 298 }
294 for (int i = old_size; i < lists_size_; ++i) { 299 for (int i = old_size; i < lists_size_; ++i) {
295 lists_[i].next = free_list_head_; 300 lists_[i].next = free_list_head_;
296 free_list_head_ = i; 301 free_list_head_ = i;
297 } 302 }
298 } 303 }
299 304
300 305
301 void HValueMap::Insert(HValue* value, Zone* zone) { 306 void HInstructionMap::Insert(HInstruction* instr, Zone* zone) {
302 ASSERT(value != NULL); 307 ASSERT(instr != NULL);
303 // Resizing when half of the hashtable is filled up. 308 // Resizing when half of the hashtable is filled up.
304 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1, zone); 309 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1, zone);
305 ASSERT(count_ < array_size_); 310 ASSERT(count_ < array_size_);
306 count_++; 311 count_++;
307 uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode())); 312 uint32_t pos = Bound(static_cast<uint32_t>(instr->Hashcode()));
308 if (array_[pos].value == NULL) { 313 if (array_[pos].instr == NULL) {
309 array_[pos].value = value; 314 array_[pos].instr = instr;
310 array_[pos].next = kNil; 315 array_[pos].next = kNil;
311 } else { 316 } else {
312 if (free_list_head_ == kNil) { 317 if (free_list_head_ == kNil) {
313 ResizeLists(lists_size_ << 1, zone); 318 ResizeLists(lists_size_ << 1, zone);
314 } 319 }
315 int new_element_pos = free_list_head_; 320 int new_element_pos = free_list_head_;
316 ASSERT(new_element_pos != kNil); 321 ASSERT(new_element_pos != kNil);
317 free_list_head_ = lists_[free_list_head_].next; 322 free_list_head_ = lists_[free_list_head_].next;
318 lists_[new_element_pos].value = value; 323 lists_[new_element_pos].instr = instr;
319 lists_[new_element_pos].next = array_[pos].next; 324 lists_[new_element_pos].next = array_[pos].next;
320 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); 325 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].instr != NULL);
321 array_[pos].next = new_element_pos; 326 array_[pos].next = new_element_pos;
322 } 327 }
323 } 328 }
324 329
325 330
326 HSideEffectMap::HSideEffectMap() : count_(0) { 331 HSideEffectMap::HSideEffectMap() : count_(0) {
327 memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize); 332 memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize);
328 } 333 }
329 334
330 335
331 HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) { 336 HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) {
332 *this = *other; // Calls operator=. 337 *this = *other; // Calls operator=.
333 } 338 }
334 339
335 340
336 HSideEffectMap& HSideEffectMap::operator= (const HSideEffectMap& other) { 341 HSideEffectMap& HSideEffectMap::operator= (const HSideEffectMap& other) {
337 if (this != &other) { 342 if (this != &other) {
338 OS::MemCopy(data_, other.data_, kNumberOfTrackedSideEffects * kPointerSize); 343 OS::MemCopy(data_, other.data_, kNumberOfTrackedSideEffects * kPointerSize);
339 } 344 }
340 return *this; 345 return *this;
341 } 346 }
342 347
343 348
344 void HSideEffectMap::Kill(GVNFlagSet flags) { 349 void HSideEffectMap::Kill(SideEffects side_effects) {
345 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { 350 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
346 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); 351 if (side_effects.ContainsFlag(GVNFlagFromInt(i))) {
347 if (flags.Contains(changes_flag)) {
348 if (data_[i] != NULL) count_--; 352 if (data_[i] != NULL) count_--;
349 data_[i] = NULL; 353 data_[i] = NULL;
350 } 354 }
351 } 355 }
352 } 356 }
353 357
354 358
355 void HSideEffectMap::Store(GVNFlagSet flags, HInstruction* instr) { 359 void HSideEffectMap::Store(SideEffects side_effects, HInstruction* instr) {
356 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { 360 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
357 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); 361 if (side_effects.ContainsFlag(GVNFlagFromInt(i))) {
358 if (flags.Contains(changes_flag)) {
359 if (data_[i] == NULL) count_++; 362 if (data_[i] == NULL) count_++;
360 data_[i] = instr; 363 data_[i] = instr;
361 } 364 }
362 } 365 }
363 } 366 }
364 367
365 368
369 SideEffects SideEffectsTracker::ComputeChanges(HInstruction* instr) {
370 SideEffects result(instr->ChangesFlags());
371 if (result.ContainsFlag(kInobjectFields)) {
372 int index;
373 if (instr->IsStoreNamedField() &&
374 ComputeInobjectField(HStoreNamedField::cast(instr)->access(), &index)) {
375 result.RemoveFlag(kInobjectFields);
376 result.AddSpecial(index);
377 } else {
378 result.AddAllSpecial();
379 }
380 }
381 return result;
382 }
383
384
385 SideEffects SideEffectsTracker::ComputeDependsOn(HInstruction* instr) {
386 SideEffects result(instr->DependsOnFlags());
387 if (result.ContainsFlag(kInobjectFields)) {
388 int index;
389 if (instr->IsLoadNamedField() &&
390 ComputeInobjectField(HLoadNamedField::cast(instr)->access(), &index)) {
391 result.RemoveFlag(kInobjectFields);
392 result.AddSpecial(index);
393 } else {
394 result.AddAllSpecial();
395 }
396 }
397 return result;
398 }
399
400
401 void SideEffectsTracker::PrintSideEffectsTo(StringStream* stream,
402 SideEffects side_effects) const {
403 const char* separator = "";
404 stream->Add("[");
405 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
406 GVNFlag flag = GVNFlagFromInt(bit);
407 if (side_effects.ContainsFlag(flag)) {
408 stream->Add(separator);
409 separator = ", ";
410 switch (flag) {
411 #define DECLARE_FLAG(Type) \
412 case k##Type: \
413 stream->Add(#Type); \
414 break;
415 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
416 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
417 #undef DECLARE_FLAG
418 default:
419 break;
420 }
421 }
422 }
423 for (int index = 0; index < num_inobject_fields_; ++index) {
424 if (side_effects.ContainsSpecial(index)) {
425 stream->Add(separator);
426 separator = ", ";
427 inobject_fields_[index].PrintTo(stream);
428 }
429 }
430 stream->Add("]");
431 }
432
433
434 bool SideEffectsTracker::ComputeInobjectField(HObjectAccess access,
435 int* index) {
436 for (int i = 0; i < num_inobject_fields_; ++i) {
437 if (access.Equals(inobject_fields_[i])) {
438 *index = i;
439 return true;
440 }
441 }
442 if (num_inobject_fields_ < SideEffects::kNumberOfSpecials) {
443 if (FLAG_trace_gvn) {
444 HeapStringAllocator allocator;
445 StringStream stream(&allocator);
446 stream.Add("Tracking inobject field access ");
447 access.PrintTo(&stream);
448 stream.Add(" (mapped to special index %d)\n", num_inobject_fields_);
449 stream.OutputToStdOut();
450 }
451 *index = num_inobject_fields_;
452 inobject_fields_[num_inobject_fields_++] = access;
453 return true;
454 }
455 return false;
456 }
457
458
366 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph) 459 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph)
367 : HPhase("H_Global value numbering", graph), 460 : HPhase("H_Global value numbering", graph),
368 removed_side_effects_(false), 461 removed_side_effects_(false),
369 block_side_effects_(graph->blocks()->length(), zone()), 462 block_side_effects_(graph->blocks()->length(), zone()),
370 loop_side_effects_(graph->blocks()->length(), zone()), 463 loop_side_effects_(graph->blocks()->length(), zone()),
371 visited_on_paths_(graph->blocks()->length(), zone()) { 464 visited_on_paths_(graph->blocks()->length(), zone()) {
372 ASSERT(!AllowHandleAllocation::IsAllowed()); 465 ASSERT(!AllowHandleAllocation::IsAllowed());
373 block_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(), 466 block_side_effects_.AddBlock(
374 zone()); 467 SideEffects(), graph->blocks()->length(), zone());
375 loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(), 468 loop_side_effects_.AddBlock(
376 zone()); 469 SideEffects(), graph->blocks()->length(), zone());
377 } 470 }
378 471
379 472
380 void HGlobalValueNumberingPhase::Run() { 473 void HGlobalValueNumberingPhase::Run() {
381 ASSERT(!removed_side_effects_); 474 ASSERT(!removed_side_effects_);
382 for (int i = FLAG_gvn_iterations; i > 0; --i) { 475 for (int i = FLAG_gvn_iterations; i > 0; --i) {
383 // Compute the side effects. 476 // Compute the side effects.
384 ComputeBlockSideEffects(); 477 ComputeBlockSideEffects();
385 478
386 // Perform loop invariant code motion if requested. 479 // Perform loop invariant code motion if requested.
(...skipping 15 matching lines...) Expand all
402 } 495 }
403 visited_on_paths_.Clear(); 496 visited_on_paths_.Clear();
404 } 497 }
405 } 498 }
406 499
407 500
408 void HGlobalValueNumberingPhase::ComputeBlockSideEffects() { 501 void HGlobalValueNumberingPhase::ComputeBlockSideEffects() {
409 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { 502 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
410 // Compute side effects for the block. 503 // Compute side effects for the block.
411 HBasicBlock* block = graph()->blocks()->at(i); 504 HBasicBlock* block = graph()->blocks()->at(i);
412 GVNFlagSet side_effects; 505 SideEffects side_effects;
413 if (block->IsReachable() && !block->IsDeoptimizing()) { 506 if (block->IsReachable() && !block->IsDeoptimizing()) {
414 int id = block->block_id(); 507 int id = block->block_id();
415 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { 508 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
416 HInstruction* instr = it.Current(); 509 HInstruction* instr = it.Current();
417 side_effects.Add(instr->ChangesFlags()); 510 side_effects.Add(side_effects_tracker_.ComputeChanges(instr));
418 } 511 }
419 block_side_effects_[id].Add(side_effects); 512 block_side_effects_[id].Add(side_effects);
420 513
421 // Loop headers are part of their loop. 514 // Loop headers are part of their loop.
422 if (block->IsLoopHeader()) { 515 if (block->IsLoopHeader()) {
423 loop_side_effects_[id].Add(side_effects); 516 loop_side_effects_[id].Add(side_effects);
424 } 517 }
425 518
426 // Propagate loop side effects upwards. 519 // Propagate loop side effects upwards.
427 if (block->HasParentLoopHeader()) { 520 if (block->HasParentLoopHeader()) {
428 HBasicBlock* with_parent = block; 521 HBasicBlock* with_parent = block;
429 if (block->IsLoopHeader()) side_effects = loop_side_effects_[id]; 522 if (block->IsLoopHeader()) side_effects = loop_side_effects_[id];
430 do { 523 do {
431 HBasicBlock* parent_block = with_parent->parent_loop_header(); 524 HBasicBlock* parent_block = with_parent->parent_loop_header();
432 loop_side_effects_[parent_block->block_id()].Add(side_effects); 525 loop_side_effects_[parent_block->block_id()].Add(side_effects);
433 with_parent = parent_block; 526 with_parent = parent_block;
434 } while (with_parent->HasParentLoopHeader()); 527 } while (with_parent->HasParentLoopHeader());
435 } 528 }
436 } 529 }
437 } 530 }
438 } 531 }
439 532
440 533
441 SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) {
442 char underlying_buffer[kNumberOfFlags * 128];
443 Vector<char> buffer(underlying_buffer, sizeof(underlying_buffer));
444 #if DEBUG
445 int offset = 0;
446 const char* separator = "";
447 const char* comma = ", ";
448 buffer[0] = 0;
449 uint32_t set_depends_on = 0;
450 uint32_t set_changes = 0;
451 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
452 if (flags.Contains(static_cast<GVNFlag>(bit))) {
453 if (bit % 2 == 0) {
454 set_changes++;
455 } else {
456 set_depends_on++;
457 }
458 }
459 }
460 bool positive_changes = set_changes < (kNumberOfFlags / 2);
461 bool positive_depends_on = set_depends_on < (kNumberOfFlags / 2);
462 if (set_changes > 0) {
463 if (positive_changes) {
464 offset += OS::SNPrintF(buffer + offset, "changes [");
465 } else {
466 offset += OS::SNPrintF(buffer + offset, "changes all except [");
467 }
468 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
469 if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_changes) {
470 switch (static_cast<GVNFlag>(bit)) {
471 #define DECLARE_FLAG(type) \
472 case kChanges##type: \
473 offset += OS::SNPrintF(buffer + offset, separator); \
474 offset += OS::SNPrintF(buffer + offset, #type); \
475 separator = comma; \
476 break;
477 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
478 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
479 #undef DECLARE_FLAG
480 default:
481 break;
482 }
483 }
484 }
485 offset += OS::SNPrintF(buffer + offset, "]");
486 }
487 if (set_depends_on > 0) {
488 separator = "";
489 if (set_changes > 0) {
490 offset += OS::SNPrintF(buffer + offset, ", ");
491 }
492 if (positive_depends_on) {
493 offset += OS::SNPrintF(buffer + offset, "depends on [");
494 } else {
495 offset += OS::SNPrintF(buffer + offset, "depends on all except [");
496 }
497 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
498 if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_depends_on) {
499 switch (static_cast<GVNFlag>(bit)) {
500 #define DECLARE_FLAG(type) \
501 case kDependsOn##type: \
502 offset += OS::SNPrintF(buffer + offset, separator); \
503 offset += OS::SNPrintF(buffer + offset, #type); \
504 separator = comma; \
505 break;
506 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
507 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
508 #undef DECLARE_FLAG
509 default:
510 break;
511 }
512 }
513 }
514 offset += OS::SNPrintF(buffer + offset, "]");
515 }
516 #else
517 OS::SNPrintF(buffer, "0x%08X", flags.ToIntegral());
518 #endif
519 size_t string_len = strlen(underlying_buffer) + 1;
520 ASSERT(string_len <= sizeof(underlying_buffer));
521 char* result = new char[strlen(underlying_buffer) + 1];
522 OS::MemCopy(result, underlying_buffer, string_len);
523 return SmartArrayPointer<char>(result);
524 }
525
526
527 void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() { 534 void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() {
528 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", 535 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n",
529 graph()->use_optimistic_licm() ? "yes" : "no"); 536 graph()->use_optimistic_licm() ? "yes" : "no");
530 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { 537 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
531 HBasicBlock* block = graph()->blocks()->at(i); 538 HBasicBlock* block = graph()->blocks()->at(i);
532 if (block->IsLoopHeader()) { 539 if (block->IsLoopHeader()) {
533 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; 540 SideEffects side_effects = loop_side_effects_[block->block_id()];
534 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", 541 if (FLAG_trace_gvn) {
535 block->block_id(), 542 HeapStringAllocator allocator;
536 GetGVNFlagsString(side_effects).get()); 543 StringStream stream(&allocator);
537 544 stream.Add("Try loop invariant motion for block B%d changes ",
545 block->block_id());
546 side_effects_tracker_.PrintSideEffectsTo(&stream, side_effects);
547 stream.Add("\n");
548 stream.OutputToStdOut();
549 }
538 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 550 HBasicBlock* last = block->loop_information()->GetLastBackEdge();
539 for (int j = block->block_id(); j <= last->block_id(); ++j) { 551 for (int j = block->block_id(); j <= last->block_id(); ++j) {
540 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects); 552 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects);
541 } 553 }
542 } 554 }
543 } 555 }
544 } 556 }
545 557
546 558
547 void HGlobalValueNumberingPhase::ProcessLoopBlock( 559 void HGlobalValueNumberingPhase::ProcessLoopBlock(
548 HBasicBlock* block, 560 HBasicBlock* block,
549 HBasicBlock* loop_header, 561 HBasicBlock* loop_header,
550 GVNFlagSet loop_kills) { 562 SideEffects loop_kills) {
551 HBasicBlock* pre_header = loop_header->predecessors()->at(0); 563 HBasicBlock* pre_header = loop_header->predecessors()->at(0);
552 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 564 if (FLAG_trace_gvn) {
553 TRACE_GVN_2("Loop invariant motion for B%d %s\n", 565 HeapStringAllocator allocator;
554 block->block_id(), 566 StringStream stream(&allocator);
555 GetGVNFlagsString(depends_flags).get()); 567 stream.Add("Loop invariant code motion for B%d depends on ",
568 block->block_id());
569 side_effects_tracker_.PrintSideEffectsTo(&stream, loop_kills);
570 stream.Add("\n");
571 stream.OutputToStdOut();
572 }
556 HInstruction* instr = block->first(); 573 HInstruction* instr = block->first();
557 while (instr != NULL) { 574 while (instr != NULL) {
558 HInstruction* next = instr->next(); 575 HInstruction* next = instr->next();
559 if (instr->CheckFlag(HValue::kUseGVN)) { 576 if (instr->CheckFlag(HValue::kUseGVN)) {
560 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", 577 SideEffects changes = side_effects_tracker_.ComputeChanges(instr);
561 instr->id(), 578 SideEffects depends_on = side_effects_tracker_.ComputeDependsOn(instr);
562 instr->Mnemonic(), 579 if (FLAG_trace_gvn) {
563 GetGVNFlagsString(instr->gvn_flags()).get(), 580 HeapStringAllocator allocator;
564 GetGVNFlagsString(loop_kills).get()); 581 StringStream stream(&allocator);
565 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); 582 stream.Add("Checking instruction i%d (%s) changes ",
583 instr->id(), instr->Mnemonic());
584 side_effects_tracker_.PrintSideEffectsTo(&stream, changes);
585 stream.Add(", depends on ");
586 side_effects_tracker_.PrintSideEffectsTo(&stream, depends_on);
587 stream.Add(". Loop changes ");
588 side_effects_tracker_.PrintSideEffectsTo(&stream, loop_kills);
589 stream.Add("\n");
590 stream.OutputToStdOut();
591 }
592 bool can_hoist = !depends_on.ContainsAnyOf(loop_kills);
566 if (can_hoist && !graph()->use_optimistic_licm()) { 593 if (can_hoist && !graph()->use_optimistic_licm()) {
567 can_hoist = block->IsLoopSuccessorDominator(); 594 can_hoist = block->IsLoopSuccessorDominator();
568 } 595 }
569 596
570 if (can_hoist) { 597 if (can_hoist) {
571 bool inputs_loop_invariant = true; 598 bool inputs_loop_invariant = true;
572 for (int i = 0; i < instr->OperandCount(); ++i) { 599 for (int i = 0; i < instr->OperandCount(); ++i) {
573 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 600 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
574 inputs_loop_invariant = false; 601 inputs_loop_invariant = false;
575 } 602 }
(...skipping 21 matching lines...) Expand all
597 624
598 bool HGlobalValueNumberingPhase::ShouldMove(HInstruction* instr, 625 bool HGlobalValueNumberingPhase::ShouldMove(HInstruction* instr,
599 HBasicBlock* loop_header) { 626 HBasicBlock* loop_header) {
600 // If we've disabled code motion or we're in a block that unconditionally 627 // If we've disabled code motion or we're in a block that unconditionally
601 // deoptimizes, don't move any instructions. 628 // deoptimizes, don't move any instructions.
602 return AllowCodeMotion() && !instr->block()->IsDeoptimizing() && 629 return AllowCodeMotion() && !instr->block()->IsDeoptimizing() &&
603 instr->block()->IsReachable(); 630 instr->block()->IsReachable();
604 } 631 }
605 632
606 633
607 GVNFlagSet 634 SideEffects
608 HGlobalValueNumberingPhase::CollectSideEffectsOnPathsToDominatedBlock( 635 HGlobalValueNumberingPhase::CollectSideEffectsOnPathsToDominatedBlock(
609 HBasicBlock* dominator, HBasicBlock* dominated) { 636 HBasicBlock* dominator, HBasicBlock* dominated) {
610 GVNFlagSet side_effects; 637 SideEffects side_effects;
611 for (int i = 0; i < dominated->predecessors()->length(); ++i) { 638 for (int i = 0; i < dominated->predecessors()->length(); ++i) {
612 HBasicBlock* block = dominated->predecessors()->at(i); 639 HBasicBlock* block = dominated->predecessors()->at(i);
613 if (dominator->block_id() < block->block_id() && 640 if (dominator->block_id() < block->block_id() &&
614 block->block_id() < dominated->block_id() && 641 block->block_id() < dominated->block_id() &&
615 !visited_on_paths_.Contains(block->block_id())) { 642 !visited_on_paths_.Contains(block->block_id())) {
616 visited_on_paths_.Add(block->block_id()); 643 visited_on_paths_.Add(block->block_id());
617 side_effects.Add(block_side_effects_[block->block_id()]); 644 side_effects.Add(block_side_effects_[block->block_id()]);
618 if (block->IsLoopHeader()) { 645 if (block->IsLoopHeader()) {
619 side_effects.Add(loop_side_effects_[block->block_id()]); 646 side_effects.Add(loop_side_effects_[block->block_id()]);
620 } 647 }
621 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( 648 side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
622 dominator, block)); 649 dominator, block));
623 } 650 }
624 } 651 }
625 return side_effects; 652 return side_effects;
626 } 653 }
627 654
628 655
629 // Each instance of this class is like a "stack frame" for the recursive 656 // Each instance of this class is like a "stack frame" for the recursive
630 // traversal of the dominator tree done during GVN (the stack is handled 657 // traversal of the dominator tree done during GVN (the stack is handled
631 // as a double linked list). 658 // as a double linked list).
632 // We reuse frames when possible so the list length is limited by the depth 659 // We reuse frames when possible so the list length is limited by the depth
633 // of the dominator tree but this forces us to initialize each frame calling 660 // of the dominator tree but this forces us to initialize each frame calling
634 // an explicit "Initialize" method instead of a using constructor. 661 // an explicit "Initialize" method instead of a using constructor.
635 class GvnBasicBlockState: public ZoneObject { 662 class GvnBasicBlockState: public ZoneObject {
636 public: 663 public:
637 static GvnBasicBlockState* CreateEntry(Zone* zone, 664 static GvnBasicBlockState* CreateEntry(Zone* zone,
638 HBasicBlock* entry_block, 665 HBasicBlock* entry_block,
639 HValueMap* entry_map) { 666 HInstructionMap* entry_map) {
640 return new(zone) 667 return new(zone)
641 GvnBasicBlockState(NULL, entry_block, entry_map, NULL, zone); 668 GvnBasicBlockState(NULL, entry_block, entry_map, NULL, zone);
642 } 669 }
643 670
644 HBasicBlock* block() { return block_; } 671 HBasicBlock* block() { return block_; }
645 HValueMap* map() { return map_; } 672 HInstructionMap* map() { return map_; }
646 HSideEffectMap* dominators() { return &dominators_; } 673 HSideEffectMap* dominators() { return &dominators_; }
647 674
648 GvnBasicBlockState* next_in_dominator_tree_traversal( 675 GvnBasicBlockState* next_in_dominator_tree_traversal(
649 Zone* zone, 676 Zone* zone,
650 HBasicBlock** dominator) { 677 HBasicBlock** dominator) {
651 // This assignment needs to happen before calling next_dominated() because 678 // This assignment needs to happen before calling next_dominated() because
652 // that call can reuse "this" if we are at the last dominated block. 679 // that call can reuse "this" if we are at the last dominated block.
653 *dominator = block(); 680 *dominator = block();
654 GvnBasicBlockState* result = next_dominated(zone); 681 GvnBasicBlockState* result = next_dominated(zone);
655 if (result == NULL) { 682 if (result == NULL) {
656 GvnBasicBlockState* dominator_state = pop(); 683 GvnBasicBlockState* dominator_state = pop();
657 if (dominator_state != NULL) { 684 if (dominator_state != NULL) {
658 // This branch is guaranteed not to return NULL because pop() never 685 // This branch is guaranteed not to return NULL because pop() never
659 // returns a state where "is_done() == true". 686 // returns a state where "is_done() == true".
660 *dominator = dominator_state->block(); 687 *dominator = dominator_state->block();
661 result = dominator_state->next_dominated(zone); 688 result = dominator_state->next_dominated(zone);
662 } else { 689 } else {
663 // Unnecessary (we are returning NULL) but done for cleanness. 690 // Unnecessary (we are returning NULL) but done for cleanness.
664 *dominator = NULL; 691 *dominator = NULL;
665 } 692 }
666 } 693 }
667 return result; 694 return result;
668 } 695 }
669 696
670 private: 697 private:
671 void Initialize(HBasicBlock* block, 698 void Initialize(HBasicBlock* block,
672 HValueMap* map, 699 HInstructionMap* map,
673 HSideEffectMap* dominators, 700 HSideEffectMap* dominators,
674 bool copy_map, 701 bool copy_map,
675 Zone* zone) { 702 Zone* zone) {
676 block_ = block; 703 block_ = block;
677 map_ = copy_map ? map->Copy(zone) : map; 704 map_ = copy_map ? map->Copy(zone) : map;
678 dominated_index_ = -1; 705 dominated_index_ = -1;
679 length_ = block->dominated_blocks()->length(); 706 length_ = block->dominated_blocks()->length();
680 if (dominators != NULL) { 707 if (dominators != NULL) {
681 dominators_ = *dominators; 708 dominators_ = *dominators;
682 } 709 }
683 } 710 }
684 bool is_done() { return dominated_index_ >= length_; } 711 bool is_done() { return dominated_index_ >= length_; }
685 712
686 GvnBasicBlockState(GvnBasicBlockState* previous, 713 GvnBasicBlockState(GvnBasicBlockState* previous,
687 HBasicBlock* block, 714 HBasicBlock* block,
688 HValueMap* map, 715 HInstructionMap* map,
689 HSideEffectMap* dominators, 716 HSideEffectMap* dominators,
690 Zone* zone) 717 Zone* zone)
691 : previous_(previous), next_(NULL) { 718 : previous_(previous), next_(NULL) {
692 Initialize(block, map, dominators, true, zone); 719 Initialize(block, map, dominators, true, zone);
693 } 720 }
694 721
695 GvnBasicBlockState* next_dominated(Zone* zone) { 722 GvnBasicBlockState* next_dominated(Zone* zone) {
696 dominated_index_++; 723 dominated_index_++;
697 if (dominated_index_ == length_ - 1) { 724 if (dominated_index_ == length_ - 1) {
698 // No need to copy the map for the last child in the dominator tree. 725 // No need to copy the map for the last child in the dominator tree.
(...skipping 26 matching lines...) Expand all
725 block()->block_id(), 752 block()->block_id(),
726 previous_->block()->block_id()) 753 previous_->block()->block_id())
727 result = result->previous_; 754 result = result->previous_;
728 } 755 }
729 return result; 756 return result;
730 } 757 }
731 758
732 GvnBasicBlockState* previous_; 759 GvnBasicBlockState* previous_;
733 GvnBasicBlockState* next_; 760 GvnBasicBlockState* next_;
734 HBasicBlock* block_; 761 HBasicBlock* block_;
735 HValueMap* map_; 762 HInstructionMap* map_;
736 HSideEffectMap dominators_; 763 HSideEffectMap dominators_;
737 int dominated_index_; 764 int dominated_index_;
738 int length_; 765 int length_;
739 }; 766 };
740 767
741 768
742 // This is a recursive traversal of the dominator tree but it has been turned 769 // This is a recursive traversal of the dominator tree but it has been turned
743 // into a loop to avoid stack overflows. 770 // into a loop to avoid stack overflows.
744 // The logical "stack frames" of the recursion are kept in a list of 771 // The logical "stack frames" of the recursion are kept in a list of
745 // GvnBasicBlockState instances. 772 // GvnBasicBlockState instances.
746 void HGlobalValueNumberingPhase::AnalyzeGraph() { 773 void HGlobalValueNumberingPhase::AnalyzeGraph() {
747 HBasicBlock* entry_block = graph()->entry_block(); 774 HBasicBlock* entry_block = graph()->entry_block();
748 HValueMap* entry_map = new(zone()) HValueMap(zone()); 775 HInstructionMap* entry_map =
776 new(zone()) HInstructionMap(zone(), &side_effects_tracker_);
749 GvnBasicBlockState* current = 777 GvnBasicBlockState* current =
750 GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map); 778 GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map);
751 779
752 while (current != NULL) { 780 while (current != NULL) {
753 HBasicBlock* block = current->block(); 781 HBasicBlock* block = current->block();
754 HValueMap* map = current->map(); 782 HInstructionMap* map = current->map();
755 HSideEffectMap* dominators = current->dominators(); 783 HSideEffectMap* dominators = current->dominators();
756 784
757 TRACE_GVN_2("Analyzing block B%d%s\n", 785 TRACE_GVN_2("Analyzing block B%d%s\n",
758 block->block_id(), 786 block->block_id(),
759 block->IsLoopHeader() ? " (loop header)" : ""); 787 block->IsLoopHeader() ? " (loop header)" : "");
760 788
761 // If this is a loop header kill everything killed by the loop. 789 // If this is a loop header kill everything killed by the loop.
762 if (block->IsLoopHeader()) { 790 if (block->IsLoopHeader()) {
763 map->Kill(loop_side_effects_[block->block_id()]); 791 map->Kill(loop_side_effects_[block->block_id()]);
764 dominators->Kill(loop_side_effects_[block->block_id()]); 792 dominators->Kill(loop_side_effects_[block->block_id()]);
765 } 793 }
766 794
767 // Go through all instructions of the current block. 795 // Go through all instructions of the current block.
768 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { 796 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
769 HInstruction* instr = it.Current(); 797 HInstruction* instr = it.Current();
770 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { 798 if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) {
771 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { 799 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
772 HValue* other = dominators->at(i); 800 HValue* other = dominators->at(i);
773 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); 801 GVNFlag flag = GVNFlagFromInt(i);
774 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); 802 if (instr->DependsOnFlags().Contains(flag) && other != NULL) {
775 if (instr->DependsOnFlags().Contains(depends_on_flag) &&
776 (other != NULL)) {
777 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", 803 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n",
778 i, 804 i,
779 instr->id(), 805 instr->id(),
780 instr->Mnemonic(), 806 instr->Mnemonic(),
781 other->id(), 807 other->id(),
782 other->Mnemonic()); 808 other->Mnemonic());
783 if (instr->HandleSideEffectDominator(changes_flag, other)) { 809 if (instr->HandleSideEffectDominator(flag, other)) {
784 removed_side_effects_ = true; 810 removed_side_effects_ = true;
785 } 811 }
786 } 812 }
787 } 813 }
788 } 814 }
789 // Instruction was unlinked during graph traversal. 815 // Instruction was unlinked during graph traversal.
790 if (!instr->IsLinked()) continue; 816 if (!instr->IsLinked()) continue;
791 817
792 GVNFlagSet flags = instr->ChangesFlags(); 818 SideEffects changes = side_effects_tracker_.ComputeChanges(instr);
793 if (!flags.IsEmpty()) { 819 if (!changes.IsEmpty()) {
794 // Clear all instructions in the map that are affected by side effects. 820 // Clear all instructions in the map that are affected by side effects.
795 // Store instruction as the dominating one for tracked side effects. 821 // Store instruction as the dominating one for tracked side effects.
796 map->Kill(flags); 822 map->Kill(changes);
797 dominators->Store(flags, instr); 823 dominators->Store(changes, instr);
798 TRACE_GVN_2("Instruction %d %s\n", instr->id(), 824 if (FLAG_trace_gvn) {
799 GetGVNFlagsString(flags).get()); 825 HeapStringAllocator allocator;
826 StringStream stream(&allocator);
827 stream.Add("Instruction i%d changes ", instr->id());
828 side_effects_tracker_.PrintSideEffectsTo(&stream, changes);
829 stream.Add("\n");
830 stream.OutputToStdOut();
831 }
800 } 832 }
801 if (instr->CheckFlag(HValue::kUseGVN)) { 833 if (instr->CheckFlag(HValue::kUseGVN)) {
802 ASSERT(!instr->HasObservableSideEffects()); 834 ASSERT(!instr->HasObservableSideEffects());
803 HValue* other = map->Lookup(instr); 835 HInstruction* other = map->Lookup(instr);
804 if (other != NULL) { 836 if (other != NULL) {
805 ASSERT(instr->Equals(other) && other->Equals(instr)); 837 ASSERT(instr->Equals(other) && other->Equals(instr));
806 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", 838 TRACE_GVN_4("Replacing instruction i%d (%s) with i%d (%s)\n",
807 instr->id(), 839 instr->id(),
808 instr->Mnemonic(), 840 instr->Mnemonic(),
809 other->id(), 841 other->id(),
810 other->Mnemonic()); 842 other->Mnemonic());
811 if (instr->HasSideEffects()) removed_side_effects_ = true; 843 if (instr->HasSideEffects()) removed_side_effects_ = true;
812 instr->DeleteAndReplaceWith(other); 844 instr->DeleteAndReplaceWith(other);
813 } else { 845 } else {
814 map->Add(instr, zone()); 846 map->Add(instr, zone());
815 } 847 }
816 } 848 }
817 } 849 }
818 850
819 HBasicBlock* dominator_block; 851 HBasicBlock* dominator_block;
820 GvnBasicBlockState* next = 852 GvnBasicBlockState* next =
821 current->next_in_dominator_tree_traversal(zone(), 853 current->next_in_dominator_tree_traversal(zone(),
822 &dominator_block); 854 &dominator_block);
823 855
824 if (next != NULL) { 856 if (next != NULL) {
825 HBasicBlock* dominated = next->block(); 857 HBasicBlock* dominated = next->block();
826 HValueMap* successor_map = next->map(); 858 HInstructionMap* successor_map = next->map();
827 HSideEffectMap* successor_dominators = next->dominators(); 859 HSideEffectMap* successor_dominators = next->dominators();
828 860
829 // Kill everything killed on any path between this block and the 861 // Kill everything killed on any path between this block and the
830 // dominated block. We don't have to traverse these paths if the 862 // dominated block. We don't have to traverse these paths if the
831 // value map and the dominators list is already empty. If the range 863 // value map and the dominators list is already empty. If the range
832 // of block ids (block_id, dominated_id) is empty there are no such 864 // of block ids (block_id, dominated_id) is empty there are no such
833 // paths. 865 // paths.
834 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) && 866 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) &&
835 dominator_block->block_id() + 1 < dominated->block_id()) { 867 dominator_block->block_id() + 1 < dominated->block_id()) {
836 visited_on_paths_.Clear(); 868 visited_on_paths_.Clear();
837 GVNFlagSet side_effects_on_all_paths = 869 SideEffects side_effects_on_all_paths =
838 CollectSideEffectsOnPathsToDominatedBlock(dominator_block, 870 CollectSideEffectsOnPathsToDominatedBlock(dominator_block,
839 dominated); 871 dominated);
840 successor_map->Kill(side_effects_on_all_paths); 872 successor_map->Kill(side_effects_on_all_paths);
841 successor_dominators->Kill(side_effects_on_all_paths); 873 successor_dominators->Kill(side_effects_on_all_paths);
842 } 874 }
843 } 875 }
844 current = next; 876 current = next;
845 } 877 }
846 } 878 }
847 879
848 } } // namespace v8::internal 880 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-gvn.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698