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