OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
97 void HBasicBlock::AddPhi(HPhi* phi) { | 97 void HBasicBlock::AddPhi(HPhi* phi) { |
98 ASSERT(!IsStartBlock()); | 98 ASSERT(!IsStartBlock()); |
99 phis_.Add(phi, zone()); | 99 phis_.Add(phi, zone()); |
100 phi->SetBlock(this); | 100 phi->SetBlock(this); |
101 } | 101 } |
102 | 102 |
103 | 103 |
104 void HBasicBlock::RemovePhi(HPhi* phi) { | 104 void HBasicBlock::RemovePhi(HPhi* phi) { |
105 ASSERT(phi->block() == this); | 105 ASSERT(phi->block() == this); |
106 ASSERT(phis_.Contains(phi)); | 106 ASSERT(phis_.Contains(phi)); |
107 ASSERT(phi->HasNoUses() || !phi->is_live()); | |
108 phi->Kill(); | 107 phi->Kill(); |
109 phis_.RemoveElement(phi); | 108 phis_.RemoveElement(phi); |
110 phi->SetBlock(NULL); | 109 phi->SetBlock(NULL); |
111 } | 110 } |
112 | 111 |
113 | 112 |
114 void HBasicBlock::AddInstruction(HInstruction* instr) { | 113 void HBasicBlock::AddInstruction(HInstruction* instr) { |
115 ASSERT(!IsStartBlock() || !IsFinished()); | 114 ASSERT(!IsStartBlock() || !IsFinished()); |
116 ASSERT(!instr->IsLinked()); | 115 ASSERT(!instr->IsLinked()); |
117 ASSERT(!IsFinished()); | 116 ASSERT(!IsFinished()); |
(...skipping 2486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2604 // Make sure that we *really* removed all redundant phis. | 2603 // Make sure that we *really* removed all redundant phis. |
2605 for (int i = 0; i < blocks_.length(); ++i) { | 2604 for (int i = 0; i < blocks_.length(); ++i) { |
2606 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { | 2605 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { |
2607 ASSERT(blocks_[i]->phis()->at(j)->GetRedundantReplacement() == NULL); | 2606 ASSERT(blocks_[i]->phis()->at(j)->GetRedundantReplacement() == NULL); |
2608 } | 2607 } |
2609 } | 2608 } |
2610 #endif | 2609 #endif |
2611 } | 2610 } |
2612 | 2611 |
2613 | 2612 |
2614 void HGraph::EliminateUnreachablePhis() { | |
2615 HPhase phase("H_Unreachable phi elimination", this); | |
2616 | |
2617 // Initialize worklist. | |
2618 ZoneList<HPhi*> phi_list(blocks_.length(), zone()); | |
2619 ZoneList<HPhi*> worklist(blocks_.length(), zone()); | |
2620 for (int i = 0; i < blocks_.length(); ++i) { | |
2621 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { | |
2622 HPhi* phi = blocks_[i]->phis()->at(j); | |
2623 phi_list.Add(phi, zone()); | |
2624 // We can't eliminate phis in the receiver position in the environment | |
2625 // because in case of throwing an error we need this value to | |
2626 // construct a stack trace. | |
2627 if (phi->HasRealUses() || phi->IsReceiver()) { | |
2628 phi->set_is_live(true); | |
2629 worklist.Add(phi, zone()); | |
2630 } | |
2631 } | |
2632 } | |
2633 | |
2634 // Iteratively mark live phis. | |
2635 while (!worklist.is_empty()) { | |
2636 HPhi* phi = worklist.RemoveLast(); | |
2637 for (int i = 0; i < phi->OperandCount(); i++) { | |
2638 HValue* operand = phi->OperandAt(i); | |
2639 if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) { | |
2640 HPhi::cast(operand)->set_is_live(true); | |
2641 worklist.Add(HPhi::cast(operand), zone()); | |
2642 } | |
2643 } | |
2644 } | |
2645 | |
2646 // Remove unreachable phis. | |
2647 for (int i = 0; i < phi_list.length(); i++) { | |
2648 HPhi* phi = phi_list[i]; | |
2649 if (!phi->is_live()) { | |
2650 HBasicBlock* block = phi->block(); | |
2651 block->RemovePhi(phi); | |
2652 block->RecordDeletedPhi(phi->merged_index()); | |
2653 } | |
2654 } | |
2655 } | |
2656 | |
2657 | |
2658 bool HGraph::CheckArgumentsPhiUses() { | 2613 bool HGraph::CheckArgumentsPhiUses() { |
2659 int block_count = blocks_.length(); | 2614 int block_count = blocks_.length(); |
2660 for (int i = 0; i < block_count; ++i) { | 2615 for (int i = 0; i < block_count; ++i) { |
2661 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { | 2616 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { |
2662 HPhi* phi = blocks_[i]->phis()->at(j); | 2617 HPhi* phi = blocks_[i]->phis()->at(j); |
2663 // We don't support phi uses of arguments for now. | 2618 // We don't support phi uses of arguments for now. |
2664 if (phi->CheckFlag(HValue::kIsArguments)) return false; | 2619 if (phi->CheckFlag(HValue::kIsArguments)) return false; |
2665 } | 2620 } |
2666 } | 2621 } |
2667 return true; | 2622 return true; |
(...skipping 2240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4908 *bailout_reason = SmartArrayPointer<char>(StrDup( | 4863 *bailout_reason = SmartArrayPointer<char>(StrDup( |
4909 "Unsupported phi use of const variable")); | 4864 "Unsupported phi use of const variable")); |
4910 return false; | 4865 return false; |
4911 } | 4866 } |
4912 EliminateRedundantPhis(); | 4867 EliminateRedundantPhis(); |
4913 if (!CheckArgumentsPhiUses()) { | 4868 if (!CheckArgumentsPhiUses()) { |
4914 *bailout_reason = SmartArrayPointer<char>(StrDup( | 4869 *bailout_reason = SmartArrayPointer<char>(StrDup( |
4915 "Unsupported phi use of arguments")); | 4870 "Unsupported phi use of arguments")); |
4916 return false; | 4871 return false; |
4917 } | 4872 } |
4918 if (FLAG_eliminate_dead_phis) EliminateUnreachablePhis(); | 4873 |
4874 // Remove dead code and phis | |
4875 if (FLAG_dead_code_elimination) { | |
4876 DeadCodeElimination("H_Eliminate early dead code"); | |
4877 } | |
4919 CollectPhis(); | 4878 CollectPhis(); |
4920 | 4879 |
4921 if (has_osr_loop_entry()) { | 4880 if (has_osr_loop_entry()) { |
4922 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); | 4881 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); |
4923 for (int j = 0; j < phis->length(); j++) { | 4882 for (int j = 0; j < phis->length(); j++) { |
4924 HPhi* phi = phis->at(j); | 4883 HPhi* phi = phis->at(j); |
4925 osr_values()->at(phi->merged_index())->set_incoming_value(phi); | 4884 osr_values()->at(phi->merged_index())->set_incoming_value(phi); |
4926 } | 4885 } |
4927 } | 4886 } |
4928 | 4887 |
(...skipping 27 matching lines...) Expand all Loading... | |
4956 | 4915 |
4957 // Eliminate redundant stack checks on backwards branches. | 4916 // Eliminate redundant stack checks on backwards branches. |
4958 HStackCheckEliminator sce(this); | 4917 HStackCheckEliminator sce(this); |
4959 sce.Process(); | 4918 sce.Process(); |
4960 | 4919 |
4961 if (FLAG_idefs) SetupInformativeDefinitions(); | 4920 if (FLAG_idefs) SetupInformativeDefinitions(); |
4962 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { | 4921 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { |
4963 EliminateRedundantBoundsChecks(); | 4922 EliminateRedundantBoundsChecks(); |
4964 } | 4923 } |
4965 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); | 4924 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); |
4966 if (FLAG_dead_code_elimination) DeadCodeElimination(); | 4925 if (FLAG_dead_code_elimination) { |
4926 DeadCodeElimination("H_Eliminate late dead code"); | |
4927 } | |
4967 | 4928 |
4968 RestoreActualValues(); | 4929 RestoreActualValues(); |
4969 | 4930 |
4970 return true; | 4931 return true; |
4971 } | 4932 } |
4972 | 4933 |
4973 | 4934 |
4974 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { | 4935 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { |
4975 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { | 4936 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { |
4976 HPhi* phi = block->phis()->at(phi_index); | 4937 HPhi* phi = block->phis()->at(phi_index); |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5433 array_instruction = static_cast<ArrayInstructionInterface*>(op); | 5394 array_instruction = static_cast<ArrayInstructionInterface*>(op); |
5434 } else { | 5395 } else { |
5435 continue; | 5396 continue; |
5436 } | 5397 } |
5437 DehoistArrayIndex(array_instruction); | 5398 DehoistArrayIndex(array_instruction); |
5438 } | 5399 } |
5439 } | 5400 } |
5440 } | 5401 } |
5441 | 5402 |
5442 | 5403 |
5443 void HGraph::DeadCodeElimination() { | 5404 void HGraph::DeadCodeElimination(const char* phase_name) { |
5444 HPhase phase("H_Dead code elimination", this); | 5405 HPhase phase(phase_name, this); |
5445 ZoneList<HInstruction*> worklist(blocks_.length(), zone()); | 5406 MarkLiveInstructions(); |
5407 RemoveDeadInstructions(); | |
5408 } | |
5409 | |
5410 | |
5411 void HGraph::MarkLiveInstructions() { | |
5412 ZoneList<HValue*> worklist(blocks_.length(), zone()); | |
5413 | |
5414 // Mark initial root instructions for dead code elimination. | |
5446 for (int i = 0; i < blocks()->length(); ++i) { | 5415 for (int i = 0; i < blocks()->length(); ++i) { |
5447 for (HInstruction* instr = blocks()->at(i)->first(); | 5416 HBasicBlock* block = blocks()->at(i); |
5417 for (HInstruction* instr = block->first(); | |
5448 instr != NULL; | 5418 instr != NULL; |
5449 instr = instr->next()) { | 5419 instr = instr->next()) { |
5450 if (instr->IsDead()) worklist.Add(instr, zone()); | 5420 if (!instr->CanBeEliminated()) MarkLive(NULL, instr, &worklist); |
5421 } | |
5422 for (int j = 0; j < block->phis()->length(); j++) { | |
5423 HPhi* phi = block->phis()->at(j); | |
5424 // TODO(titzer): we can't eliminate the receiver for generating backtraces | |
5425 if (phi->IsReceiver()) MarkLive(NULL, phi, &worklist); | |
Sven Panne
2013/05/14 07:57:31
Can we move this check into HPhi::IsDeletable? Thi
| |
5451 } | 5426 } |
5452 } | 5427 } |
5453 | 5428 |
5429 // Transitively mark all inputs of live instructions live. | |
5454 while (!worklist.is_empty()) { | 5430 while (!worklist.is_empty()) { |
5455 HInstruction* instr = worklist.RemoveLast(); | 5431 HValue* instr = worklist.RemoveLast(); |
5456 // This happens when an instruction is used multiple times as operand. That | |
5457 // in turn could happen through GVN. | |
5458 if (!instr->IsLinked()) continue; | |
5459 if (FLAG_trace_dead_code_elimination) { | |
5460 HeapStringAllocator allocator; | |
5461 StringStream stream(&allocator); | |
5462 instr->PrintNameTo(&stream); | |
5463 stream.Add(" = "); | |
5464 instr->PrintTo(&stream); | |
5465 PrintF("[removing dead instruction %s]\n", *stream.ToCString()); | |
5466 } | |
5467 instr->DeleteAndReplaceWith(NULL); | |
5468 for (int i = 0; i < instr->OperandCount(); ++i) { | 5432 for (int i = 0; i < instr->OperandCount(); ++i) { |
5469 HValue* operand = instr->OperandAt(i); | 5433 MarkLive(instr, instr->OperandAt(i), &worklist); |
5470 if (operand->IsDead()) worklist.Add(HInstruction::cast(operand), zone()); | |
5471 } | 5434 } |
5472 } | 5435 } |
5473 } | 5436 } |
5474 | 5437 |
5438 | |
5439 void HGraph::MarkLive(HValue *ref, HValue* instr, | |
5440 ZoneList<HValue*>* worklist) { | |
5441 if (!instr->CheckFlag(HValue::kIsLive)) { | |
5442 instr->SetFlag(HValue::kIsLive); | |
5443 worklist->Add(instr, zone()); | |
5444 | |
5445 if (FLAG_trace_dead_code_elimination) { | |
5446 HeapStringAllocator allocator; | |
5447 StringStream stream(&allocator); | |
5448 if (ref != NULL) { | |
5449 ref->PrintTo(&stream); | |
5450 } else { | |
5451 stream.Add("root "); | |
5452 } | |
5453 stream.Add(" -> "); | |
5454 instr->PrintTo(&stream); | |
5455 PrintF("[MarkLive %s]\n", *stream.ToCString()); | |
5456 } | |
5457 } | |
5458 } | |
5459 | |
5460 | |
5461 void HGraph::RemoveDeadInstructions() { | |
5462 ZoneList<HPhi*> dead_phis(blocks_.length(), zone()); | |
5463 | |
5464 // Remove any instruction not marked kIsLive. | |
5465 for (int i = 0; i < blocks()->length(); ++i) { | |
5466 HBasicBlock* block = blocks()->at(i); | |
5467 for (HInstruction* instr = block->first(); | |
5468 instr != NULL; | |
5469 instr = instr->next()) { | |
5470 if (!instr->CheckFlag(HValue::kIsLive)) { | |
5471 // Instruction has not been marked live; assume it is dead and remove. | |
5472 // TODO(titzer): we don't remove constants because some special ones | |
5473 // might be used by later phases and are assumed to be in the graph | |
5474 if (instr->IsConstant()) instr->DeleteAndReplaceWith(NULL); | |
5475 } else { | |
5476 // Clear the liveness flag to leave the graph clean for the next DCE. | |
5477 instr->ClearFlag(HValue::kIsLive); | |
5478 } | |
5479 } | |
5480 // Collect phis that are dead and remove them in the next pass. | |
5481 for (int j = 0; j < block->phis()->length(); j++) { | |
5482 HPhi* phi = block->phis()->at(j); | |
5483 if (!phi->CheckFlag(HValue::kIsLive)) { | |
5484 dead_phis.Add(phi, zone()); | |
5485 } else { | |
5486 phi->ClearFlag(HValue::kIsLive); | |
5487 } | |
5488 } | |
5489 } | |
5490 | |
5491 // Process phis separately to avoid simultaneously mutating the phi list. | |
5492 while (!dead_phis.is_empty()) { | |
5493 HPhi* phi = dead_phis.RemoveLast(); | |
5494 HBasicBlock* block = phi->block(); | |
5495 phi->DeleteAndReplaceWith(NULL); | |
5496 block->RecordDeletedPhi(phi->merged_index()); | |
5497 } | |
5498 } | |
5499 | |
5475 | 5500 |
5476 void HGraph::RestoreActualValues() { | 5501 void HGraph::RestoreActualValues() { |
5477 HPhase phase("H_Restore actual values", this); | 5502 HPhase phase("H_Restore actual values", this); |
5478 | 5503 |
5479 for (int block_index = 0; block_index < blocks()->length(); block_index++) { | 5504 for (int block_index = 0; block_index < blocks()->length(); block_index++) { |
5480 HBasicBlock* block = blocks()->at(block_index); | 5505 HBasicBlock* block = blocks()->at(block_index); |
5481 | 5506 |
5482 #ifdef DEBUG | 5507 #ifdef DEBUG |
5483 for (int i = 0; i < block->phis()->length(); i++) { | 5508 for (int i = 0; i < block->phis()->length(); i++) { |
5484 HPhi* phi = block->phis()->at(i); | 5509 HPhi* phi = block->phis()->at(i); |
(...skipping 6933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12418 } | 12443 } |
12419 } | 12444 } |
12420 | 12445 |
12421 #ifdef DEBUG | 12446 #ifdef DEBUG |
12422 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12447 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
12423 if (allocator_ != NULL) allocator_->Verify(); | 12448 if (allocator_ != NULL) allocator_->Verify(); |
12424 #endif | 12449 #endif |
12425 } | 12450 } |
12426 | 12451 |
12427 } } // namespace v8::internal | 12452 } } // namespace v8::internal |
OLD | NEW |