OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 #include "src/hydrogen-gvn.h" | 6 #include "src/hydrogen-gvn.h" |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 } else { | 393 } else { |
394 for (index = 0; index < kNumberOfInobjectFields; ++index) { | 394 for (index = 0; index < kNumberOfInobjectFields; ++index) { |
395 result.AddSpecial(InobjectField(index)); | 395 result.AddSpecial(InobjectField(index)); |
396 } | 396 } |
397 } | 397 } |
398 } | 398 } |
399 return result; | 399 return result; |
400 } | 400 } |
401 | 401 |
402 | 402 |
403 void SideEffectsTracker::PrintSideEffectsTo(StringStream* stream, | 403 OStream& operator<<(OStream& os, const TrackedEffects& te) { |
404 SideEffects side_effects) const { | 404 SideEffectsTracker* t = te.tracker; |
405 const char* separator = ""; | 405 const char* separator = ""; |
406 stream->Add("["); | 406 os << "["; |
407 for (int bit = 0; bit < kNumberOfFlags; ++bit) { | 407 for (int bit = 0; bit < kNumberOfFlags; ++bit) { |
408 GVNFlag flag = GVNFlagFromInt(bit); | 408 GVNFlag flag = GVNFlagFromInt(bit); |
409 if (side_effects.ContainsFlag(flag)) { | 409 if (te.effects.ContainsFlag(flag)) { |
410 stream->Add(separator); | 410 os << separator; |
411 separator = ", "; | 411 separator = ", "; |
412 switch (flag) { | 412 switch (flag) { |
413 #define DECLARE_FLAG(Type) \ | 413 #define DECLARE_FLAG(Type) \ |
414 case k##Type: \ | 414 case k##Type: \ |
415 stream->Add(#Type); \ | 415 os << #Type; \ |
416 break; | 416 break; |
417 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) | 417 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) |
418 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) | 418 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) |
419 #undef DECLARE_FLAG | 419 #undef DECLARE_FLAG |
420 default: | 420 default: |
421 break; | 421 break; |
422 } | 422 } |
423 } | 423 } |
424 } | 424 } |
425 for (int index = 0; index < num_global_vars_; ++index) { | 425 for (int index = 0; index < t->num_global_vars_; ++index) { |
426 if (side_effects.ContainsSpecial(GlobalVar(index))) { | 426 if (te.effects.ContainsSpecial(t->GlobalVar(index))) { |
427 stream->Add(separator); | 427 os << separator << "[" << *t->global_vars_[index].handle() << "]"; |
428 separator = ", "; | 428 separator = ", "; |
429 stream->Add("[%p]", *global_vars_[index].handle()); | |
430 } | 429 } |
431 } | 430 } |
432 for (int index = 0; index < num_inobject_fields_; ++index) { | 431 for (int index = 0; index < t->num_inobject_fields_; ++index) { |
433 if (side_effects.ContainsSpecial(InobjectField(index))) { | 432 if (te.effects.ContainsSpecial(t->InobjectField(index))) { |
434 stream->Add(separator); | 433 os << separator << t->inobject_fields_[index]; |
435 separator = ", "; | 434 separator = ", "; |
436 inobject_fields_[index].PrintTo(stream); | |
437 } | 435 } |
438 } | 436 } |
439 stream->Add("]"); | 437 os << "]"; |
| 438 return os; |
440 } | 439 } |
441 | 440 |
442 | 441 |
443 bool SideEffectsTracker::ComputeGlobalVar(Unique<Cell> cell, int* index) { | 442 bool SideEffectsTracker::ComputeGlobalVar(Unique<Cell> cell, int* index) { |
444 for (int i = 0; i < num_global_vars_; ++i) { | 443 for (int i = 0; i < num_global_vars_; ++i) { |
445 if (cell == global_vars_[i]) { | 444 if (cell == global_vars_[i]) { |
446 *index = i; | 445 *index = i; |
447 return true; | 446 return true; |
448 } | 447 } |
449 } | 448 } |
(...skipping 14 matching lines...) Expand all Loading... |
464 bool SideEffectsTracker::ComputeInobjectField(HObjectAccess access, | 463 bool SideEffectsTracker::ComputeInobjectField(HObjectAccess access, |
465 int* index) { | 464 int* index) { |
466 for (int i = 0; i < num_inobject_fields_; ++i) { | 465 for (int i = 0; i < num_inobject_fields_; ++i) { |
467 if (access.Equals(inobject_fields_[i])) { | 466 if (access.Equals(inobject_fields_[i])) { |
468 *index = i; | 467 *index = i; |
469 return true; | 468 return true; |
470 } | 469 } |
471 } | 470 } |
472 if (num_inobject_fields_ < kNumberOfInobjectFields) { | 471 if (num_inobject_fields_ < kNumberOfInobjectFields) { |
473 if (FLAG_trace_gvn) { | 472 if (FLAG_trace_gvn) { |
474 HeapStringAllocator allocator; | 473 OFStream os(stdout); |
475 StringStream stream(&allocator); | 474 os << "Tracking inobject field access " << access << " (mapped to index " |
476 stream.Add("Tracking inobject field access "); | 475 << num_inobject_fields_ << ")" << endl; |
477 access.PrintTo(&stream); | |
478 stream.Add(" (mapped to index %d)\n", num_inobject_fields_); | |
479 stream.OutputToStdOut(); | |
480 } | 476 } |
481 *index = num_inobject_fields_; | 477 *index = num_inobject_fields_; |
482 inobject_fields_[num_inobject_fields_++] = access; | 478 inobject_fields_[num_inobject_fields_++] = access; |
483 return true; | 479 return true; |
484 } | 480 } |
485 return false; | 481 return false; |
486 } | 482 } |
487 | 483 |
488 | 484 |
489 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph) | 485 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph) |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 | 558 |
563 | 559 |
564 void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() { | 560 void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() { |
565 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", | 561 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", |
566 graph()->use_optimistic_licm() ? "yes" : "no"); | 562 graph()->use_optimistic_licm() ? "yes" : "no"); |
567 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { | 563 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { |
568 HBasicBlock* block = graph()->blocks()->at(i); | 564 HBasicBlock* block = graph()->blocks()->at(i); |
569 if (block->IsLoopHeader()) { | 565 if (block->IsLoopHeader()) { |
570 SideEffects side_effects = loop_side_effects_[block->block_id()]; | 566 SideEffects side_effects = loop_side_effects_[block->block_id()]; |
571 if (FLAG_trace_gvn) { | 567 if (FLAG_trace_gvn) { |
572 HeapStringAllocator allocator; | 568 OFStream os(stdout); |
573 StringStream stream(&allocator); | 569 os << "Try loop invariant motion for " << *block << " changes " |
574 stream.Add("Try loop invariant motion for block B%d changes ", | 570 << Print(side_effects) << endl; |
575 block->block_id()); | |
576 side_effects_tracker_.PrintSideEffectsTo(&stream, side_effects); | |
577 stream.Add("\n"); | |
578 stream.OutputToStdOut(); | |
579 } | 571 } |
580 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); | 572 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); |
581 for (int j = block->block_id(); j <= last->block_id(); ++j) { | 573 for (int j = block->block_id(); j <= last->block_id(); ++j) { |
582 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects); | 574 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects); |
583 } | 575 } |
584 } | 576 } |
585 } | 577 } |
586 } | 578 } |
587 | 579 |
588 | 580 |
589 void HGlobalValueNumberingPhase::ProcessLoopBlock( | 581 void HGlobalValueNumberingPhase::ProcessLoopBlock( |
590 HBasicBlock* block, | 582 HBasicBlock* block, |
591 HBasicBlock* loop_header, | 583 HBasicBlock* loop_header, |
592 SideEffects loop_kills) { | 584 SideEffects loop_kills) { |
593 HBasicBlock* pre_header = loop_header->predecessors()->at(0); | 585 HBasicBlock* pre_header = loop_header->predecessors()->at(0); |
594 if (FLAG_trace_gvn) { | 586 if (FLAG_trace_gvn) { |
595 HeapStringAllocator allocator; | 587 OFStream os(stdout); |
596 StringStream stream(&allocator); | 588 os << "Loop invariant code motion for " << *block << " depends on " |
597 stream.Add("Loop invariant code motion for B%d depends on ", | 589 << Print(loop_kills) << endl; |
598 block->block_id()); | |
599 side_effects_tracker_.PrintSideEffectsTo(&stream, loop_kills); | |
600 stream.Add("\n"); | |
601 stream.OutputToStdOut(); | |
602 } | 590 } |
603 HInstruction* instr = block->first(); | 591 HInstruction* instr = block->first(); |
604 while (instr != NULL) { | 592 while (instr != NULL) { |
605 HInstruction* next = instr->next(); | 593 HInstruction* next = instr->next(); |
606 if (instr->CheckFlag(HValue::kUseGVN)) { | 594 if (instr->CheckFlag(HValue::kUseGVN)) { |
607 SideEffects changes = side_effects_tracker_.ComputeChanges(instr); | 595 SideEffects changes = side_effects_tracker_.ComputeChanges(instr); |
608 SideEffects depends_on = side_effects_tracker_.ComputeDependsOn(instr); | 596 SideEffects depends_on = side_effects_tracker_.ComputeDependsOn(instr); |
609 if (FLAG_trace_gvn) { | 597 if (FLAG_trace_gvn) { |
610 HeapStringAllocator allocator; | 598 OFStream os(stdout); |
611 StringStream stream(&allocator); | 599 os << "Checking instruction i" << instr->id() << " (" |
612 stream.Add("Checking instruction i%d (%s) changes ", | 600 << instr->Mnemonic() << ") changes " << Print(changes) |
613 instr->id(), instr->Mnemonic()); | 601 << ", depends on " << Print(depends_on) << ". Loop changes " |
614 side_effects_tracker_.PrintSideEffectsTo(&stream, changes); | 602 << Print(loop_kills) << endl; |
615 stream.Add(", depends on "); | |
616 side_effects_tracker_.PrintSideEffectsTo(&stream, depends_on); | |
617 stream.Add(". Loop changes "); | |
618 side_effects_tracker_.PrintSideEffectsTo(&stream, loop_kills); | |
619 stream.Add("\n"); | |
620 stream.OutputToStdOut(); | |
621 } | 603 } |
622 bool can_hoist = !depends_on.ContainsAnyOf(loop_kills); | 604 bool can_hoist = !depends_on.ContainsAnyOf(loop_kills); |
623 if (can_hoist && !graph()->use_optimistic_licm()) { | 605 if (can_hoist && !graph()->use_optimistic_licm()) { |
624 can_hoist = block->IsLoopSuccessorDominator(); | 606 can_hoist = block->IsLoopSuccessorDominator(); |
625 } | 607 } |
626 | 608 |
627 if (can_hoist) { | 609 if (can_hoist) { |
628 bool inputs_loop_invariant = true; | 610 bool inputs_loop_invariant = true; |
629 for (int i = 0; i < instr->OperandCount(); ++i) { | 611 for (int i = 0; i < instr->OperandCount(); ++i) { |
630 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { | 612 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
845 // Instruction was unlinked during graph traversal. | 827 // Instruction was unlinked during graph traversal. |
846 if (!instr->IsLinked()) continue; | 828 if (!instr->IsLinked()) continue; |
847 | 829 |
848 SideEffects changes = side_effects_tracker_.ComputeChanges(instr); | 830 SideEffects changes = side_effects_tracker_.ComputeChanges(instr); |
849 if (!changes.IsEmpty()) { | 831 if (!changes.IsEmpty()) { |
850 // Clear all instructions in the map that are affected by side effects. | 832 // Clear all instructions in the map that are affected by side effects. |
851 // Store instruction as the dominating one for tracked side effects. | 833 // Store instruction as the dominating one for tracked side effects. |
852 map->Kill(changes); | 834 map->Kill(changes); |
853 dominators->Store(changes, instr); | 835 dominators->Store(changes, instr); |
854 if (FLAG_trace_gvn) { | 836 if (FLAG_trace_gvn) { |
855 HeapStringAllocator allocator; | 837 OFStream os(stdout); |
856 StringStream stream(&allocator); | 838 os << "Instruction i" << instr->id() << " changes " << Print(changes) |
857 stream.Add("Instruction i%d changes ", instr->id()); | 839 << endl; |
858 side_effects_tracker_.PrintSideEffectsTo(&stream, changes); | |
859 stream.Add("\n"); | |
860 stream.OutputToStdOut(); | |
861 } | 840 } |
862 } | 841 } |
863 if (instr->CheckFlag(HValue::kUseGVN) && | 842 if (instr->CheckFlag(HValue::kUseGVN) && |
864 !instr->CheckFlag(HValue::kCantBeReplaced)) { | 843 !instr->CheckFlag(HValue::kCantBeReplaced)) { |
865 ASSERT(!instr->HasObservableSideEffects()); | 844 ASSERT(!instr->HasObservableSideEffects()); |
866 HInstruction* other = map->Lookup(instr); | 845 HInstruction* other = map->Lookup(instr); |
867 if (other != NULL) { | 846 if (other != NULL) { |
868 ASSERT(instr->Equals(other) && other->Equals(instr)); | 847 ASSERT(instr->Equals(other) && other->Equals(instr)); |
869 TRACE_GVN_4("Replacing instruction i%d (%s) with i%d (%s)\n", | 848 TRACE_GVN_4("Replacing instruction i%d (%s) with i%d (%s)\n", |
870 instr->id(), | 849 instr->id(), |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 dominated); | 881 dominated); |
903 successor_map->Kill(side_effects_on_all_paths); | 882 successor_map->Kill(side_effects_on_all_paths); |
904 successor_dominators->Kill(side_effects_on_all_paths); | 883 successor_dominators->Kill(side_effects_on_all_paths); |
905 } | 884 } |
906 } | 885 } |
907 current = next; | 886 current = next; |
908 } | 887 } |
909 } | 888 } |
910 | 889 |
911 } } // namespace v8::internal | 890 } } // namespace v8::internal |
OLD | NEW |