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