| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.h" | 5 #include "vm/flow_graph.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 ASSERT(use->definition() != NULL); | 138 ASSERT(use->definition() != NULL); |
| 139 ASSERT((use->definition() != instr) || use->definition()->IsPhi()); | 139 ASSERT((use->definition() != instr) || use->definition()->IsPhi()); |
| 140 ASSERT(use->instruction() == instr); | 140 ASSERT(use->instruction() == instr); |
| 141 ASSERT(use->use_index() == use_index++); | 141 ASSERT(use->use_index() == use_index++); |
| 142 ASSERT(!FLAG_verify_compiler || | 142 ASSERT(!FLAG_verify_compiler || |
| 143 (1 == MembershipCount(use, use->definition()->env_use_list()))); | 143 (1 == MembershipCount(use, use->definition()->env_use_list()))); |
| 144 } | 144 } |
| 145 } | 145 } |
| 146 Definition* defn = instr->AsDefinition(); | 146 Definition* defn = instr->AsDefinition(); |
| 147 if (defn != NULL) { | 147 if (defn != NULL) { |
| 148 // Used definitions must have an SSA name. We use the name to index |
| 149 // into bit vectors during analyses. Some definitions without SSA names |
| 150 // (e.g., PushArgument) have environment uses. |
| 151 ASSERT((defn->input_use_list() == NULL) || defn->HasSSATemp()); |
| 148 Value* prev = NULL; | 152 Value* prev = NULL; |
| 149 Value* curr = defn->input_use_list(); | 153 Value* curr = defn->input_use_list(); |
| 150 while (curr != NULL) { | 154 while (curr != NULL) { |
| 151 ASSERT(prev == curr->previous_use()); | 155 ASSERT(prev == curr->previous_use()); |
| 152 ASSERT(defn == curr->definition()); | 156 ASSERT(defn == curr->definition()); |
| 153 Instruction* instr = curr->instruction(); | 157 Instruction* instr = curr->instruction(); |
| 154 // The instruction should not be removed from the graph. Removed | 158 // The instruction should not be removed from the graph. |
| 155 // instructions have a NULL previous link. Phis are not removed until | 159 ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) || |
| 156 // register allocation. Comparisons used only in a branch will have a | |
| 157 // NULL previous link though they are still in the graph. | |
| 158 ASSERT(instr->IsPhi() || | |
| 159 (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) || | |
| 160 (instr->previous() != NULL)); | 160 (instr->previous() != NULL)); |
| 161 ASSERT(curr == instr->InputAt(curr->use_index())); | 161 ASSERT(curr == instr->InputAt(curr->use_index())); |
| 162 prev = curr; | 162 prev = curr; |
| 163 curr = curr->next_use(); | 163 curr = curr->next_use(); |
| 164 } | 164 } |
| 165 | 165 |
| 166 prev = NULL; | 166 prev = NULL; |
| 167 curr = defn->env_use_list(); | 167 curr = defn->env_use_list(); |
| 168 while (curr != NULL) { | 168 while (curr != NULL) { |
| 169 ASSERT(prev == curr->previous_use()); | 169 ASSERT(prev == curr->previous_use()); |
| 170 ASSERT(defn == curr->definition()); | 170 ASSERT(defn == curr->definition()); |
| 171 Instruction* instr = curr->instruction(); | 171 Instruction* instr = curr->instruction(); |
| 172 ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index())); | 172 ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index())); |
| 173 ASSERT(instr->IsPhi() || | 173 ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) || |
| 174 (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) || | |
| 175 (instr->previous() != NULL)); | 174 (instr->previous() != NULL)); |
| 176 prev = curr; | 175 prev = curr; |
| 177 curr = curr->next_use(); | 176 curr = curr->next_use(); |
| 178 } | 177 } |
| 179 } | 178 } |
| 180 } | 179 } |
| 181 | 180 |
| 182 | 181 |
| 183 bool FlowGraph::VerifyUseLists() { | 182 bool FlowGraph::VerifyUseLists() { |
| 184 // Verify the initial definitions. | 183 // Verify the initial definitions. |
| 185 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { | 184 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { |
| 186 VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]); | 185 VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]); |
| 187 } | 186 } |
| 188 | 187 |
| 189 // Verify phis in join entries and the instructions in each block. | 188 // Verify phis in join entries and the instructions in each block. |
| 190 for (intptr_t i = 0; i < preorder_.length(); ++i) { | 189 for (intptr_t i = 0; i < preorder_.length(); ++i) { |
| 191 BlockEntryInstr* entry = preorder_[i]; | 190 BlockEntryInstr* entry = preorder_[i]; |
| 192 JoinEntryInstr* join = entry->AsJoinEntry(); | 191 JoinEntryInstr* join = entry->AsJoinEntry(); |
| 193 if (join != NULL && join->phis() != NULL) { | 192 if (join != NULL) { |
| 194 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 193 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
| 195 PhiInstr* phi = (*join->phis())[i]; | 194 PhiInstr* phi = it.Current(); |
| 196 if (phi != NULL) VerifyUseListsInInstruction(phi); | 195 ASSERT(phi != NULL); |
| 196 VerifyUseListsInInstruction(phi); |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 199 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 200 VerifyUseListsInInstruction(it.Current()); | 200 VerifyUseListsInInstruction(it.Current()); |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 return true; // Return true so we can ASSERT validation. | 203 return true; // Return true so we can ASSERT validation. |
| 204 } | 204 } |
| 205 #endif // DEBUG | 205 #endif // DEBUG |
| 206 | 206 |
| 207 | 207 |
| 208 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, | 208 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, |
| 209 GrowableArray<Definition*>* inlining_parameters) { | 209 GrowableArray<Definition*>* inlining_parameters) { |
| 210 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); | 210 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); |
| 211 current_ssa_temp_index_ = next_virtual_register_number; | 211 current_ssa_temp_index_ = next_virtual_register_number; |
| 212 GrowableArray<BitVector*> dominance_frontier; | 212 GrowableArray<BitVector*> dominance_frontier; |
| 213 ComputeDominators(&dominance_frontier); | 213 ComputeDominators(&dominance_frontier); |
| 214 InsertPhis(preorder_, assigned_vars_, dominance_frontier); | 214 InsertPhis(preorder_, assigned_vars_, dominance_frontier); |
| 215 GrowableArray<PhiInstr*> live_phis; | 215 GrowableArray<PhiInstr*> live_phis; |
| 216 // Rename uses to reference inserted phis where appropriate. | 216 // Rename uses to reference inserted phis where appropriate. |
| 217 // Collect phis that reach a non-environment use. | 217 // Collect phis that reach a non-environment use. |
| 218 Rename(&live_phis, inlining_parameters); | 218 Rename(&live_phis, inlining_parameters); |
| 219 // Propagate alive mark transitively from alive phis. | 219 // Propagate alive mark transitively from alive phis and then remove |
| 220 MarkLivePhis(&live_phis); | 220 // non-live ones. |
| 221 RemoveDeadPhis(&live_phis); |
| 221 } | 222 } |
| 222 | 223 |
| 223 | 224 |
| 224 // Compute immediate dominators and the dominance frontier for each basic | 225 // Compute immediate dominators and the dominance frontier for each basic |
| 225 // block. As a side effect of the algorithm, sets the immediate dominator | 226 // block. As a side effect of the algorithm, sets the immediate dominator |
| 226 // of each basic block. | 227 // of each basic block. |
| 227 // | 228 // |
| 228 // dominance_frontier: an output parameter encoding the dominance frontier. | 229 // dominance_frontier: an output parameter encoding the dominance frontier. |
| 229 // The array maps the preorder block number of a block to the set of | 230 // The array maps the preorder block number of a block to the set of |
| 230 // (preorder block numbers of) blocks in the dominance frontier. | 231 // (preorder block numbers of) blocks in the dominance frontier. |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); | 572 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); |
| 572 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); | 573 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); |
| 573 ASSERT(pred_index >= 0); | 574 ASSERT(pred_index >= 0); |
| 574 if (successor->phis() != NULL) { | 575 if (successor->phis() != NULL) { |
| 575 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { | 576 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { |
| 576 PhiInstr* phi = (*successor->phis())[i]; | 577 PhiInstr* phi = (*successor->phis())[i]; |
| 577 if (phi != NULL) { | 578 if (phi != NULL) { |
| 578 // Rename input operand. | 579 // Rename input operand. |
| 579 Value* use = new Value((*env)[i]); | 580 Value* use = new Value((*env)[i]); |
| 580 phi->SetInputAt(pred_index, use); | 581 phi->SetInputAt(pred_index, use); |
| 581 use->definition()->AddInputUse(use); | |
| 582 } | 582 } |
| 583 } | 583 } |
| 584 } | 584 } |
| 585 } | 585 } |
| 586 } | 586 } |
| 587 | 587 |
| 588 | 588 |
| 589 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) { | 589 void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) { |
| 590 while (!live_phis->is_empty()) { | 590 while (!live_phis->is_empty()) { |
| 591 PhiInstr* phi = live_phis->RemoveLast(); | 591 PhiInstr* phi = live_phis->RemoveLast(); |
| 592 for (intptr_t i = 0; i < phi->InputCount(); i++) { | 592 for (intptr_t i = 0; i < phi->InputCount(); i++) { |
| 593 Value* val = phi->InputAt(i); | 593 Value* val = phi->InputAt(i); |
| 594 PhiInstr* used_phi = val->definition()->AsPhi(); | 594 PhiInstr* used_phi = val->definition()->AsPhi(); |
| 595 if ((used_phi != NULL) && !used_phi->is_alive()) { | 595 if ((used_phi != NULL) && !used_phi->is_alive()) { |
| 596 used_phi->mark_alive(); | 596 used_phi->mark_alive(); |
| 597 live_phis->Add(used_phi); | 597 live_phis->Add(used_phi); |
| 598 } | 598 } |
| 599 } | 599 } |
| 600 } | 600 } |
| 601 |
| 602 for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) { |
| 603 JoinEntryInstr* join = it.Current()->AsJoinEntry(); |
| 604 if (join != NULL) join->RemoveDeadPhis(constant_null()); |
| 605 } |
| 601 } | 606 } |
| 602 | 607 |
| 603 | 608 |
| 604 // Find the natural loop for the back edge m->n and attach loop information | 609 // Find the natural loop for the back edge m->n and attach loop information |
| 605 // to block n (loop header). The algorithm is described in "Advanced Compiler | 610 // to block n (loop header). The algorithm is described in "Advanced Compiler |
| 606 // Design & Implementation" (Muchnick) p192. | 611 // Design & Implementation" (Muchnick) p192. |
| 607 static void FindLoop(BlockEntryInstr* m, | 612 static void FindLoop(BlockEntryInstr* m, |
| 608 BlockEntryInstr* n, | 613 BlockEntryInstr* n, |
| 609 intptr_t num_blocks) { | 614 intptr_t num_blocks) { |
| 610 GrowableArray<BlockEntryInstr*> stack; | 615 GrowableArray<BlockEntryInstr*> stack; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 !it.Done(); | 690 !it.Done(); |
| 686 it.Advance()) { | 691 it.Advance()) { |
| 687 ++size; | 692 ++size; |
| 688 } | 693 } |
| 689 } | 694 } |
| 690 return size; | 695 return size; |
| 691 } | 696 } |
| 692 | 697 |
| 693 | 698 |
| 694 } // namespace dart | 699 } // namespace dart |
| OLD | NEW |