OLD | NEW |
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 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | 354 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
355 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); | 355 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
356 if (flags.Contains(changes_flag)) { | 356 if (flags.Contains(changes_flag)) { |
357 if (data_[i] == NULL) count_++; | 357 if (data_[i] == NULL) count_++; |
358 data_[i] = instr; | 358 data_[i] = instr; |
359 } | 359 } |
360 } | 360 } |
361 } | 361 } |
362 | 362 |
363 | 363 |
364 HGlobalValueNumberer::HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) | 364 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph, |
365 : graph_(graph), | 365 Zone* zone) |
366 info_(info), | 366 : HPhase("H_Global value numbering", graph, zone), |
367 removed_side_effects_(false), | 367 removed_side_effects_(false), |
368 phase_zone_(info->phase_zone()), | 368 block_side_effects_(graph->blocks()->length(), zone), |
369 phase_zone_scope_(phase_zone_, DELETE_ON_EXIT), | 369 loop_side_effects_(graph->blocks()->length(), zone), |
370 block_side_effects_(graph->blocks()->length(), phase_zone_), | 370 visited_on_paths_(zone, graph->blocks()->length()) { |
371 loop_side_effects_(graph->blocks()->length(), phase_zone_), | |
372 visited_on_paths_(phase_zone_, graph->blocks()->length()) { | |
373 ASSERT(!AllowHandleAllocation::IsAllowed()); | 371 ASSERT(!AllowHandleAllocation::IsAllowed()); |
374 block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length(), | 372 block_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(), zone); |
375 phase_zone_); | 373 loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(), zone); |
376 loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length(), | |
377 phase_zone_); | |
378 } | 374 } |
379 | 375 |
380 bool HGlobalValueNumberer::Analyze() { | 376 bool HGlobalValueNumberingPhase::Analyze() { |
381 removed_side_effects_ = false; | 377 removed_side_effects_ = false; |
382 ComputeBlockSideEffects(); | 378 ComputeBlockSideEffects(); |
383 if (FLAG_loop_invariant_code_motion) { | 379 if (FLAG_loop_invariant_code_motion) { |
384 LoopInvariantCodeMotion(); | 380 LoopInvariantCodeMotion(); |
385 } | 381 } |
386 AnalyzeGraph(); | 382 AnalyzeGraph(); |
387 return removed_side_effects_; | 383 return removed_side_effects_; |
388 } | 384 } |
389 | 385 |
390 | 386 |
391 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 387 void HGlobalValueNumberingPhase::ComputeBlockSideEffects() { |
392 // The Analyze phase of GVN can be called multiple times. Clear loop side | 388 // The Analyze phase of GVN can be called multiple times. Clear loop side |
393 // effects before computing them to erase the contents from previous Analyze | 389 // effects before computing them to erase the contents from previous Analyze |
394 // passes. | 390 // passes. |
395 for (int i = 0; i < loop_side_effects_.length(); ++i) { | 391 for (int i = 0; i < loop_side_effects_.length(); ++i) { |
396 loop_side_effects_[i].RemoveAll(); | 392 loop_side_effects_[i].RemoveAll(); |
397 } | 393 } |
398 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 394 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { |
399 // Compute side effects for the block. | 395 // Compute side effects for the block. |
400 HBasicBlock* block = graph_->blocks()->at(i); | 396 HBasicBlock* block = graph()->blocks()->at(i); |
401 HInstruction* instr = block->first(); | 397 HInstruction* instr = block->first(); |
402 int id = block->block_id(); | 398 int id = block->block_id(); |
403 GVNFlagSet side_effects; | 399 GVNFlagSet side_effects; |
404 while (instr != NULL) { | 400 while (instr != NULL) { |
405 side_effects.Add(instr->ChangesFlags()); | 401 side_effects.Add(instr->ChangesFlags()); |
406 if (instr->IsSoftDeoptimize()) { | 402 if (instr->IsSoftDeoptimize()) { |
407 block_side_effects_[id].RemoveAll(); | 403 block_side_effects_[id].RemoveAll(); |
408 side_effects.RemoveAll(); | 404 side_effects.RemoveAll(); |
409 break; | 405 break; |
410 } | 406 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 OS::SNPrintF(buffer, "0x%08X", flags.ToIntegral()); | 503 OS::SNPrintF(buffer, "0x%08X", flags.ToIntegral()); |
508 #endif | 504 #endif |
509 size_t string_len = strlen(underlying_buffer) + 1; | 505 size_t string_len = strlen(underlying_buffer) + 1; |
510 ASSERT(string_len <= sizeof(underlying_buffer)); | 506 ASSERT(string_len <= sizeof(underlying_buffer)); |
511 char* result = new char[strlen(underlying_buffer) + 1]; | 507 char* result = new char[strlen(underlying_buffer) + 1]; |
512 OS::MemCopy(result, underlying_buffer, string_len); | 508 OS::MemCopy(result, underlying_buffer, string_len); |
513 return SmartArrayPointer<char>(result); | 509 return SmartArrayPointer<char>(result); |
514 } | 510 } |
515 | 511 |
516 | 512 |
517 void HGlobalValueNumberer::LoopInvariantCodeMotion() { | 513 void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() { |
518 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", | 514 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", |
519 graph_->use_optimistic_licm() ? "yes" : "no"); | 515 graph()->use_optimistic_licm() ? "yes" : "no"); |
520 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 516 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { |
521 HBasicBlock* block = graph_->blocks()->at(i); | 517 HBasicBlock* block = graph()->blocks()->at(i); |
522 if (block->IsLoopHeader()) { | 518 if (block->IsLoopHeader()) { |
523 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; | 519 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; |
524 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", | 520 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", |
525 block->block_id(), | 521 block->block_id(), |
526 *GetGVNFlagsString(side_effects)); | 522 *GetGVNFlagsString(side_effects)); |
527 | 523 |
528 GVNFlagSet accumulated_first_time_depends; | 524 GVNFlagSet accumulated_first_time_depends; |
529 GVNFlagSet accumulated_first_time_changes; | 525 GVNFlagSet accumulated_first_time_changes; |
530 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); | 526 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); |
531 for (int j = block->block_id(); j <= last->block_id(); ++j) { | 527 for (int j = block->block_id(); j <= last->block_id(); ++j) { |
532 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, | 528 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects, |
533 &accumulated_first_time_depends, | 529 &accumulated_first_time_depends, |
534 &accumulated_first_time_changes); | 530 &accumulated_first_time_changes); |
535 } | 531 } |
536 } | 532 } |
537 } | 533 } |
538 } | 534 } |
539 | 535 |
540 | 536 |
541 void HGlobalValueNumberer::ProcessLoopBlock( | 537 void HGlobalValueNumberingPhase::ProcessLoopBlock( |
542 HBasicBlock* block, | 538 HBasicBlock* block, |
543 HBasicBlock* loop_header, | 539 HBasicBlock* loop_header, |
544 GVNFlagSet loop_kills, | 540 GVNFlagSet loop_kills, |
545 GVNFlagSet* first_time_depends, | 541 GVNFlagSet* first_time_depends, |
546 GVNFlagSet* first_time_changes) { | 542 GVNFlagSet* first_time_changes) { |
547 HBasicBlock* pre_header = loop_header->predecessors()->at(0); | 543 HBasicBlock* pre_header = loop_header->predecessors()->at(0); |
548 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); | 544 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); |
549 TRACE_GVN_2("Loop invariant motion for B%d %s\n", | 545 TRACE_GVN_2("Loop invariant motion for B%d %s\n", |
550 block->block_id(), | 546 block->block_id(), |
551 *GetGVNFlagsString(depends_flags)); | 547 *GetGVNFlagsString(depends_flags)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 if (!(previous_changes == *first_time_changes)) { | 592 if (!(previous_changes == *first_time_changes)) { |
597 TRACE_GVN_1("Updated first-time accumulated %s\n", | 593 TRACE_GVN_1("Updated first-time accumulated %s\n", |
598 *GetGVNFlagsString(*first_time_changes)); | 594 *GetGVNFlagsString(*first_time_changes)); |
599 } | 595 } |
600 } | 596 } |
601 instr = next; | 597 instr = next; |
602 } | 598 } |
603 } | 599 } |
604 | 600 |
605 | 601 |
606 bool HGlobalValueNumberer::AllowCodeMotion() { | 602 bool HGlobalValueNumberingPhase::AllowCodeMotion() { |
607 return info()->IsStub() || info()->opt_count() + 1 < FLAG_max_opt_count; | 603 return info()->IsStub() || info()->opt_count() + 1 < FLAG_max_opt_count; |
608 } | 604 } |
609 | 605 |
610 | 606 |
611 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, | 607 bool HGlobalValueNumberingPhase::ShouldMove(HInstruction* instr, |
612 HBasicBlock* loop_header) { | 608 HBasicBlock* loop_header) { |
613 // If we've disabled code motion or we're in a block that unconditionally | 609 // If we've disabled code motion or we're in a block that unconditionally |
614 // deoptimizes, don't move any instructions. | 610 // deoptimizes, don't move any instructions. |
615 return AllowCodeMotion() && !instr->block()->IsDeoptimizing(); | 611 return AllowCodeMotion() && !instr->block()->IsDeoptimizing(); |
616 } | 612 } |
617 | 613 |
618 | 614 |
619 GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( | 615 GVNFlagSet HGlobalValueNumberingPhase::CollectSideEffectsOnPathsToDominatedBlock |
620 HBasicBlock* dominator, HBasicBlock* dominated) { | 616 (HBasicBlock* dominator, HBasicBlock* dominated) { |
621 GVNFlagSet side_effects; | 617 GVNFlagSet side_effects; |
622 for (int i = 0; i < dominated->predecessors()->length(); ++i) { | 618 for (int i = 0; i < dominated->predecessors()->length(); ++i) { |
623 HBasicBlock* block = dominated->predecessors()->at(i); | 619 HBasicBlock* block = dominated->predecessors()->at(i); |
624 if (dominator->block_id() < block->block_id() && | 620 if (dominator->block_id() < block->block_id() && |
625 block->block_id() < dominated->block_id() && | 621 block->block_id() < dominated->block_id() && |
626 visited_on_paths_.Add(block->block_id())) { | 622 visited_on_paths_.Add(block->block_id())) { |
627 side_effects.Add(block_side_effects_[block->block_id()]); | 623 side_effects.Add(block_side_effects_[block->block_id()]); |
628 if (block->IsLoopHeader()) { | 624 if (block->IsLoopHeader()) { |
629 side_effects.Add(loop_side_effects_[block->block_id()]); | 625 side_effects.Add(loop_side_effects_[block->block_id()]); |
630 } | 626 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 HValueMap* map_; | 745 HValueMap* map_; |
750 HSideEffectMap dominators_; | 746 HSideEffectMap dominators_; |
751 int dominated_index_; | 747 int dominated_index_; |
752 int length_; | 748 int length_; |
753 }; | 749 }; |
754 | 750 |
755 // This is a recursive traversal of the dominator tree but it has been turned | 751 // This is a recursive traversal of the dominator tree but it has been turned |
756 // into a loop to avoid stack overflows. | 752 // into a loop to avoid stack overflows. |
757 // The logical "stack frames" of the recursion are kept in a list of | 753 // The logical "stack frames" of the recursion are kept in a list of |
758 // GvnBasicBlockState instances. | 754 // GvnBasicBlockState instances. |
759 void HGlobalValueNumberer::AnalyzeGraph() { | 755 void HGlobalValueNumberingPhase::AnalyzeGraph() { |
760 HBasicBlock* entry_block = graph_->entry_block(); | 756 HBasicBlock* entry_block = graph()->entry_block(); |
761 HValueMap* entry_map = new(phase_zone()) HValueMap(phase_zone()); | 757 HValueMap* entry_map = new(zone()) HValueMap(zone()); |
762 GvnBasicBlockState* current = | 758 GvnBasicBlockState* current = |
763 GvnBasicBlockState::CreateEntry(phase_zone(), entry_block, entry_map); | 759 GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map); |
764 | 760 |
765 while (current != NULL) { | 761 while (current != NULL) { |
766 HBasicBlock* block = current->block(); | 762 HBasicBlock* block = current->block(); |
767 HValueMap* map = current->map(); | 763 HValueMap* map = current->map(); |
768 HSideEffectMap* dominators = current->dominators(); | 764 HSideEffectMap* dominators = current->dominators(); |
769 | 765 |
770 TRACE_GVN_2("Analyzing block B%d%s\n", | 766 TRACE_GVN_2("Analyzing block B%d%s\n", |
771 block->block_id(), | 767 block->block_id(), |
772 block->IsLoopHeader() ? " (loop header)" : ""); | 768 block->IsLoopHeader() ? " (loop header)" : ""); |
773 | 769 |
(...skipping 21 matching lines...) Expand all Loading... |
795 if (other != NULL) { | 791 if (other != NULL) { |
796 ASSERT(instr->Equals(other) && other->Equals(instr)); | 792 ASSERT(instr->Equals(other) && other->Equals(instr)); |
797 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", | 793 TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", |
798 instr->id(), | 794 instr->id(), |
799 instr->Mnemonic(), | 795 instr->Mnemonic(), |
800 other->id(), | 796 other->id(), |
801 other->Mnemonic()); | 797 other->Mnemonic()); |
802 if (instr->HasSideEffects()) removed_side_effects_ = true; | 798 if (instr->HasSideEffects()) removed_side_effects_ = true; |
803 instr->DeleteAndReplaceWith(other); | 799 instr->DeleteAndReplaceWith(other); |
804 } else { | 800 } else { |
805 map->Add(instr, phase_zone()); | 801 map->Add(instr, zone()); |
806 } | 802 } |
807 } | 803 } |
808 if (instr->IsLinked() && | 804 if (instr->IsLinked() && |
809 instr->CheckFlag(HValue::kTrackSideEffectDominators)) { | 805 instr->CheckFlag(HValue::kTrackSideEffectDominators)) { |
810 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { | 806 for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
811 HValue* other = dominators->at(i); | 807 HValue* other = dominators->at(i); |
812 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); | 808 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
813 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); | 809 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); |
814 if (instr->DependsOnFlags().Contains(depends_on_flag) && | 810 if (instr->DependsOnFlags().Contains(depends_on_flag) && |
815 (other != NULL)) { | 811 (other != NULL)) { |
816 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", | 812 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", |
817 i, | 813 i, |
818 instr->id(), | 814 instr->id(), |
819 instr->Mnemonic(), | 815 instr->Mnemonic(), |
820 other->id(), | 816 other->id(), |
821 other->Mnemonic()); | 817 other->Mnemonic()); |
822 instr->SetSideEffectDominator(changes_flag, other); | 818 instr->SetSideEffectDominator(changes_flag, other); |
823 } | 819 } |
824 } | 820 } |
825 } | 821 } |
826 instr = next; | 822 instr = next; |
827 } | 823 } |
828 | 824 |
829 HBasicBlock* dominator_block; | 825 HBasicBlock* dominator_block; |
830 GvnBasicBlockState* next = | 826 GvnBasicBlockState* next = |
831 current->next_in_dominator_tree_traversal(phase_zone(), | 827 current->next_in_dominator_tree_traversal(zone(), |
832 &dominator_block); | 828 &dominator_block); |
833 | 829 |
834 if (next != NULL) { | 830 if (next != NULL) { |
835 HBasicBlock* dominated = next->block(); | 831 HBasicBlock* dominated = next->block(); |
836 HValueMap* successor_map = next->map(); | 832 HValueMap* successor_map = next->map(); |
837 HSideEffectMap* successor_dominators = next->dominators(); | 833 HSideEffectMap* successor_dominators = next->dominators(); |
838 | 834 |
839 // Kill everything killed on any path between this block and the | 835 // Kill everything killed on any path between this block and the |
840 // dominated block. We don't have to traverse these paths if the | 836 // dominated block. We don't have to traverse these paths if the |
841 // value map and the dominators list is already empty. If the range | 837 // value map and the dominators list is already empty. If the range |
842 // of block ids (block_id, dominated_id) is empty there are no such | 838 // of block ids (block_id, dominated_id) is empty there are no such |
843 // paths. | 839 // paths. |
844 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) && | 840 if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) && |
845 dominator_block->block_id() + 1 < dominated->block_id()) { | 841 dominator_block->block_id() + 1 < dominated->block_id()) { |
846 visited_on_paths_.Clear(); | 842 visited_on_paths_.Clear(); |
847 GVNFlagSet side_effects_on_all_paths = | 843 GVNFlagSet side_effects_on_all_paths = |
848 CollectSideEffectsOnPathsToDominatedBlock(dominator_block, | 844 CollectSideEffectsOnPathsToDominatedBlock(dominator_block, |
849 dominated); | 845 dominated); |
850 successor_map->Kill(side_effects_on_all_paths); | 846 successor_map->Kill(side_effects_on_all_paths); |
851 successor_dominators->Kill(side_effects_on_all_paths); | 847 successor_dominators->Kill(side_effects_on_all_paths); |
852 } | 848 } |
853 } | 849 } |
854 current = next; | 850 current = next; |
855 } | 851 } |
856 } | 852 } |
857 | 853 |
858 } } // namespace v8::internal | 854 } } // namespace v8::internal |
OLD | NEW |