Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 12340108: Remove dead phis as soon as they are discovered. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_allocator.h" 5 #include "vm/flow_graph_allocator.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 } 84 }
85 blocked_cpu_registers_[SPREG] = true; 85 blocked_cpu_registers_[SPREG] = true;
86 blocked_cpu_registers_[FPREG] = true; 86 blocked_cpu_registers_[FPREG] = true;
87 87
88 // FpuTMP is used as scratch by optimized code and parallel move resolver. 88 // FpuTMP is used as scratch by optimized code and parallel move resolver.
89 blocked_fpu_registers_[FpuTMP] = true; 89 blocked_fpu_registers_[FpuTMP] = true;
90 } 90 }
91 91
92 92
93 // Remove environments from the instructions which can't deoptimize. 93 // Remove environments from the instructions which can't deoptimize.
94 // Replace dead phis uses with null values in environments. 94 void FlowGraphAllocator::EliminateEnvironments() {
95 void FlowGraphAllocator::EliminateEnvironmentUses() {
96 ConstantInstr* constant_null =
97 postorder_.Last()->AsGraphEntry()->constant_null();
98 for (intptr_t i = 0; i < block_order_.length(); ++i) { 95 for (intptr_t i = 0; i < block_order_.length(); ++i) {
99 BlockEntryInstr* block = block_order_[i]; 96 BlockEntryInstr* block = block_order_[i];
100 if (block->IsJoinEntry()) block->AsJoinEntry()->RemoveDeadPhis();
101 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 97 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
102 Instruction* current = it.Current(); 98 Instruction* current = it.Current();
103 if (current->CanDeoptimize()) { 99 if (!current->CanDeoptimize()) current->RemoveEnvironment();
104 ASSERT(current->env() != NULL);
105 for (Environment::DeepIterator it(current->env());
106 !it.Done();
107 it.Advance()) {
108 Value* use = it.CurrentValue();
109 Definition* def = use->definition();
110 PushArgumentInstr* push_argument = def->AsPushArgument();
111 if ((push_argument != NULL) && push_argument->WasEliminated()) {
112 it.SetCurrentValue(push_argument->value()->Copy());
Vyacheslav Egorov (Google) 2013/02/27 21:53:02 What happened to this special PushArgument handlin
Kevin Millikin (Google) 2013/02/28 08:12:02 It was already obsolete after a previous change, w
113 continue;
114 }
115
116 PhiInstr* phi = def->AsPhi();
117 if ((phi != NULL) && !phi->is_alive()) {
118 it.SetCurrentValue(new Value(constant_null));
119 continue;
120 }
121 }
122 } else {
123 current->RemoveEnvironment();
124 }
125 } 100 }
126 } 101 }
127 } 102 }
128 103
129 104
130 void FlowGraphAllocator::ComputeInitialSets() { 105 void FlowGraphAllocator::ComputeInitialSets() {
131 const intptr_t block_count = postorder_.length(); 106 const intptr_t block_count = postorder_.length();
132 for (intptr_t i = 0; i < block_count; i++) { 107 for (intptr_t i = 0; i < block_count; i++) {
133 BlockEntryInstr* block = postorder_[i]; 108 BlockEntryInstr* block = postorder_[i];
134 109
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 !value->BindsToConstant()) { 145 !value->BindsToConstant()) {
171 live_in->Add(value->definition()->ssa_temp_index()); 146 live_in->Add(value->definition()->ssa_temp_index());
172 } 147 }
173 } 148 }
174 } 149 }
175 } 150 }
176 151
177 // Handle phis. 152 // Handle phis.
178 if (block->IsJoinEntry()) { 153 if (block->IsJoinEntry()) {
179 JoinEntryInstr* join = block->AsJoinEntry(); 154 JoinEntryInstr* join = block->AsJoinEntry();
180 if (join->phis() != NULL) { 155 for (PhiIterator it(join); !it.Done(); it.Advance()) {
181 for (intptr_t j = 0; j < join->phis()->length(); j++) { 156 PhiInstr* phi = it.Current();
182 PhiInstr* phi = (*join->phis())[j]; 157 ASSERT(phi != NULL);
183 if (phi == NULL) continue; 158 kill->Add(phi->ssa_temp_index());
159 live_in->Remove(phi->ssa_temp_index());
184 160
185 kill->Add(phi->ssa_temp_index()); 161 // If a phi input is not defined by the corresponding predecessor it
186 live_in->Remove(phi->ssa_temp_index()); 162 // must be marked live-in for that predecessor.
163 for (intptr_t k = 0; k < phi->InputCount(); k++) {
164 Value* val = phi->InputAt(k);
165 if (val->BindsToConstant()) continue;
187 166
188 // If phi-operand is not defined by a predecessor it must be marked 167 BlockEntryInstr* pred = block->PredecessorAt(k);
189 // live-in for a predecessor. 168 const intptr_t use = val->definition()->ssa_temp_index();
190 for (intptr_t k = 0; k < phi->InputCount(); k++) { 169 if (!kill_[pred->postorder_number()]->Contains(use)) {
191 Value* val = phi->InputAt(k); 170 live_in_[pred->postorder_number()]->Add(use);
192 if (val->BindsToConstant()) continue;
193
194 BlockEntryInstr* pred = block->PredecessorAt(k);
195 const intptr_t use = val->definition()->ssa_temp_index();
196 if (!kill_[pred->postorder_number()]->Contains(use)) {
197 live_in_[pred->postorder_number()]->Add(use);
198 }
199 } 171 }
200 } 172 }
201 } 173 }
202 } 174 }
203 } 175 }
204 176
205 // Process initial definitions, ie, constants and incoming parameters. 177 // Process initial definitions, ie, constants and incoming parameters.
206 GraphEntryInstr* graph_entry = flow_graph_.graph_entry(); 178 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
207 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 179 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
208 intptr_t vreg = (*graph_entry->initial_definitions())[i]->ssa_temp_index(); 180 intptr_t vreg = (*graph_entry->initial_definitions())[i]->ssa_temp_index();
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 const intptr_t pos = goto_instr->lifetime_position(); 661 const intptr_t pos = goto_instr->lifetime_position();
690 662
691 JoinEntryInstr* join = goto_instr->successor(); 663 JoinEntryInstr* join = goto_instr->successor();
692 ASSERT(join != NULL); 664 ASSERT(join != NULL);
693 665
694 // Search for the index of the current block in the predecessors of 666 // Search for the index of the current block in the predecessors of
695 // the join. 667 // the join.
696 const intptr_t pred_idx = join->IndexOfPredecessor(block); 668 const intptr_t pred_idx = join->IndexOfPredecessor(block);
697 669
698 // Record the corresponding phi input use for each phi. 670 // Record the corresponding phi input use for each phi.
699 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
700 intptr_t move_idx = 0; 671 intptr_t move_idx = 0;
701 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) { 672 for (PhiIterator it(join); !it.Done(); it.Advance()) {
702 PhiInstr* phi = (*phis)[phi_idx]; 673 PhiInstr* phi = it.Current();
703 if (phi == NULL) continue;
704
705 Value* val = phi->InputAt(pred_idx); 674 Value* val = phi->InputAt(pred_idx);
706 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx); 675 MoveOperands* move = parallel_move->MoveOperandsAt(move_idx);
707 676
708 ConstantInstr* constant = val->definition()->AsConstant(); 677 ConstantInstr* constant = val->definition()->AsConstant();
709 if (constant != NULL) { 678 if (constant != NULL) {
710 move->set_src(Location::Constant(constant->value())); 679 move->set_src(Location::Constant(constant->value()));
711 move_idx++; 680 move_idx++;
712 continue; 681 continue;
713 } 682 }
714 683
(...skipping 22 matching lines...) Expand all
737 706
738 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) { 707 void FlowGraphAllocator::ConnectIncomingPhiMoves(BlockEntryInstr* block) {
739 // If this block is a join we need to add destinations of phi 708 // If this block is a join we need to add destinations of phi
740 // resolution moves to phi's live range so that register allocator will 709 // resolution moves to phi's live range so that register allocator will
741 // fill them with moves. 710 // fill them with moves.
742 JoinEntryInstr* join = block->AsJoinEntry(); 711 JoinEntryInstr* join = block->AsJoinEntry();
743 if (join == NULL) return; 712 if (join == NULL) return;
744 713
745 // All uses are recorded at the start position in the block. 714 // All uses are recorded at the start position in the block.
746 const intptr_t pos = join->start_pos(); 715 const intptr_t pos = join->start_pos();
747
748 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
749 if (phis == NULL) return;
750
751 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header(); 716 const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
752
753 intptr_t move_idx = 0; 717 intptr_t move_idx = 0;
754 for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) { 718 for (PhiIterator it(join); !it.Done(); it.Advance()) {
755 PhiInstr* phi = (*phis)[phi_idx]; 719 PhiInstr* phi = it.Current();
756 if (phi == NULL) continue; 720 ASSERT(phi != NULL);
757
758 const intptr_t vreg = phi->ssa_temp_index(); 721 const intptr_t vreg = phi->ssa_temp_index();
759 ASSERT(vreg != -1); 722 ASSERT(vreg >= 0);
760 723
761 // Expected shape of live range: 724 // Expected shape of live range:
762 // 725 //
763 // B 726 // B
764 // phi [-------- 727 // phi [--------
765 // 728 //
766 LiveRange* range = GetLiveRange(vreg); 729 LiveRange* range = GetLiveRange(vreg);
767 range->DefineAt(pos); // Shorten live range. 730 range->DefineAt(pos); // Shorten live range.
768 731
769 if (is_loop_header) range->mark_loop_phi(); 732 if (is_loop_header) range->mark_loop_phi();
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 } 1139 }
1177 1140
1178 // Create parallel moves in join predecessors. This must be done after 1141 // Create parallel moves in join predecessors. This must be done after
1179 // all instructions are numbered. 1142 // all instructions are numbered.
1180 for (intptr_t i = block_count - 1; i >= 0; i--) { 1143 for (intptr_t i = block_count - 1; i >= 0; i--) {
1181 BlockEntryInstr* block = postorder_[i]; 1144 BlockEntryInstr* block = postorder_[i];
1182 1145
1183 // For join entry predecessors create phi resolution moves if 1146 // For join entry predecessors create phi resolution moves if
1184 // necessary. They will be populated by the register allocator. 1147 // necessary. They will be populated by the register allocator.
1185 JoinEntryInstr* join = block->AsJoinEntry(); 1148 JoinEntryInstr* join = block->AsJoinEntry();
1186 if ((join != NULL) && (join->phi_count() > 0)) { 1149 if ((join != NULL) &&
1187 const intptr_t phi_count = join->phi_count(); 1150 (join->phis() != NULL) &&
1151 !join->phis()->is_empty()) {
1152 const intptr_t phi_count = join->phis()->length();
1188 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 1153 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
1189 // Insert the move between the last two instructions of the 1154 // Insert the move between the last two instructions of the
1190 // predecessor block (all such blocks have at least two instructions: 1155 // predecessor block (all such blocks have at least two instructions:
1191 // the block entry and goto instructions.) 1156 // the block entry and goto instructions.)
1192 Instruction* last = block->PredecessorAt(i)->last_instruction(); 1157 Instruction* last = block->PredecessorAt(i)->last_instruction();
1193 ASSERT(last->IsGoto()); 1158 ASSERT(last->IsGoto());
1194 1159
1195 ParallelMoveInstr* move = last->AsGoto()->GetParallelMove(); 1160 ParallelMoveInstr* move = last->AsGoto()->GetParallelMove();
1196 1161
1197 // Populate the ParallelMove with empty moves. 1162 // Populate the ParallelMove with empty moves.
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 (free_until >= loop_header->last_block()->end_pos()) && 1714 (free_until >= loop_header->last_block()->end_pos()) &&
1750 loop_header->backedge_interference()->Contains(unallocated->vreg())) { 1715 loop_header->backedge_interference()->Contains(unallocated->vreg())) {
1751 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <= 1716 ASSERT(static_cast<intptr_t>(kNumberOfFpuRegisters) <=
1752 kNumberOfCpuRegisters); 1717 kNumberOfCpuRegisters);
1753 bool used_on_backedge[kNumberOfCpuRegisters] = { false }; 1718 bool used_on_backedge[kNumberOfCpuRegisters] = { false };
1754 1719
1755 for (PhiIterator it(loop_header->entry()->AsJoinEntry()); 1720 for (PhiIterator it(loop_header->entry()->AsJoinEntry());
1756 !it.Done(); 1721 !it.Done();
1757 it.Advance()) { 1722 it.Advance()) {
1758 PhiInstr* phi = it.Current(); 1723 PhiInstr* phi = it.Current();
1759 if (phi->is_alive()) { 1724 ASSERT(phi->is_alive());
1760 const intptr_t phi_vreg = phi->ssa_temp_index(); 1725 const intptr_t phi_vreg = phi->ssa_temp_index();
1761 LiveRange* range = GetLiveRange(phi_vreg); 1726 LiveRange* range = GetLiveRange(phi_vreg);
1762 if (range->assigned_location().kind() == register_kind_) { 1727 if (range->assigned_location().kind() == register_kind_) {
1763 const intptr_t reg = range->assigned_location().register_code(); 1728 const intptr_t reg = range->assigned_location().register_code();
1764 1729
1765 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { 1730 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
1766 used_on_backedge[reg] = true; 1731 used_on_backedge[reg] = true;
1767 }
1768 } 1732 }
1769 } 1733 }
1770 } 1734 }
1771 1735
1772 if (used_on_backedge[candidate]) { 1736 if (used_on_backedge[candidate]) {
1773 TRACE_ALLOC(OS::Print( 1737 TRACE_ALLOC(OS::Print(
1774 "considering %s for v%"Pd": has interference on the back edge" 1738 "considering %s for v%"Pd": has interference on the back edge"
1775 " {loop [%"Pd", %"Pd")}\n", 1739 " {loop [%"Pd", %"Pd")}\n",
1776 MakeRegisterLocation(candidate, Location::kDouble).Name(), 1740 MakeRegisterLocation(candidate, Location::kDouble).Name(),
1777 unallocated->vreg(), 1741 unallocated->vreg(),
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after
2439 mint_values_->Add(defn->ssa_temp_index()); 2403 mint_values_->Add(defn->ssa_temp_index());
2440 } 2404 }
2441 } 2405 }
2442 } 2406 }
2443 } 2407 }
2444 2408
2445 2409
2446 void FlowGraphAllocator::AllocateRegisters() { 2410 void FlowGraphAllocator::AllocateRegisters() {
2447 CollectRepresentations(); 2411 CollectRepresentations();
2448 2412
2449 EliminateEnvironmentUses(); 2413 EliminateEnvironments();
2450 2414
2451 AnalyzeLiveness(); 2415 AnalyzeLiveness();
2452 2416
2453 NumberInstructions(); 2417 NumberInstructions();
2454 2418
2455 DiscoverLoops(); 2419 DiscoverLoops();
2456 2420
2457 BuildLiveRanges(); 2421 BuildLiveRanges();
2458 2422
2459 if (FLAG_print_ssa_liveness) { 2423 if (FLAG_print_ssa_liveness) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2511 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2475 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2512 function.ToFullyQualifiedCString()); 2476 function.ToFullyQualifiedCString());
2513 FlowGraphPrinter printer(flow_graph_, true); 2477 FlowGraphPrinter printer(flow_graph_, true);
2514 printer.PrintBlocks(); 2478 printer.PrintBlocks();
2515 OS::Print("----------------------------------------------\n"); 2479 OS::Print("----------------------------------------------\n");
2516 } 2480 }
2517 } 2481 }
2518 2482
2519 2483
2520 } // namespace dart 2484 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698