Chromium Code Reviews| Index: runtime/vm/flow_graph_optimizer.cc |
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
| index 9cc2ec8ce37f5c90a741800473343e3307025d22..ca18612c032aec36b144f0616987ea8627e68525 100644 |
| --- a/runtime/vm/flow_graph_optimizer.cc |
| +++ b/runtime/vm/flow_graph_optimizer.cc |
| @@ -383,8 +383,7 @@ void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { |
| Instruction* deopt_target; |
| PhiInstr* phi = use->instruction()->AsPhi(); |
| if (phi != NULL) { |
| - if (!phi->is_alive()) continue; |
| - |
| + ASSERT(phi->is_alive()); |
| // For phis conversions have to be inserted in the predecessor. |
| insert_before = |
| phi->block()->PredecessorAt(use->use_index())->last_instruction(); |
| @@ -402,12 +401,10 @@ void FlowGraphOptimizer::SelectRepresentations() { |
| // Convervatively unbox all phis that were proven to be of type Double. |
| for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
| - if (join_entry == NULL) continue; |
| - |
| - if (join_entry->phis() != NULL) { |
| - for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| - PhiInstr* phi = (*join_entry->phis())[i]; |
| - if (phi == NULL) continue; |
| + if (join_entry != NULL) { |
| + for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
| + PhiInstr* phi = it.Current(); |
| + ASSERT(phi != NULL); |
| if (phi->Type()->ToCid() == kDoubleCid) { |
| phi->set_representation(kUnboxedDouble); |
| } |
| @@ -425,17 +422,15 @@ void FlowGraphOptimizer::SelectRepresentations() { |
| for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| BlockEntryInstr* entry = block_order_[i]; |
| - |
| JoinEntryInstr* join_entry = entry->AsJoinEntry(); |
| - if ((join_entry != NULL) && (join_entry->phis() != NULL)) { |
| - for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| - PhiInstr* phi = (*join_entry->phis())[i]; |
| - if ((phi != NULL) && (phi->is_alive())) { |
| - InsertConversionsFor(phi); |
| - } |
| + if (join_entry != NULL) { |
| + for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
| + PhiInstr* phi = it.Current(); |
| + ASSERT(phi != NULL); |
| + ASSERT(phi->is_alive()); |
| + InsertConversionsFor(phi); |
| } |
| } |
| - |
| for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| Definition* def = it.Current()->AsDefinition(); |
| if (def != NULL) { |
| @@ -2256,8 +2251,7 @@ void RangeAnalysis::RenameDominatedUses(Definition* def, |
| // Skip dead phis. |
| PhiInstr* phi = use->instruction()->AsPhi(); |
| - if ((phi != NULL) && !phi->is_alive()) continue; |
| - |
| + ASSERT((phi == NULL) || phi->is_alive()); |
| if (IsDominatedUse(dom, use)) { |
| use->BindTo(other); |
| } |
| @@ -3376,13 +3370,19 @@ class LoadOptimizer : public ValueObject { |
| return true; |
| } |
| - // Emit non-redundant phis created during ComputeOutValues and ForwardLoads. |
| + // Phis have not yet been inserted into the graph but they have uses of |
| + // their inputs. Insert the non-redundant ones and clear the input uses |
| + // of the redundant ones. |
| void EmitPhis() { |
| for (intptr_t i = 0; i < phis_.length(); i++) { |
| PhiInstr* phi = phis_[i]; |
| if ((phi->input_use_list() != NULL) && !EliminateRedundantPhi(phi)) { |
| phi->mark_alive(); |
| phi->block()->InsertPhi(phi); |
| + } else { |
| + for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) { |
| + phi->InputAt(j)->RemoveFromUseList(); |
| + } |
| } |
| } |
| } |
| @@ -4251,41 +4251,47 @@ void ConstantPropagator::Transform() { |
| // Predecessors will be recomputed (in block id order) after removing |
| // unreachable code so we merely have to keep the phi inputs in order. |
| ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
| - if (phis != NULL) { |
| + if ((phis != NULL) && !phis->is_empty()) { |
| intptr_t pred_count = join->PredecessorCount(); |
| intptr_t live_count = 0; |
| for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { |
| if (reachable_->Contains( |
| join->PredecessorAt(pred_idx)->preorder_number())) { |
| if (live_count < pred_idx) { |
| - for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { |
| - PhiInstr* phi = (*phis)[phi_idx]; |
| - if (phi == NULL) continue; |
| + for (PhiIterator it(join); !it.Done(); it.Advance()) { |
| + PhiInstr* phi = it.Current(); |
| + ASSERT(phi != NULL); |
| phi->SetInputAt(live_count, phi->InputAt(pred_idx)); |
| } |
| } |
| ++live_count; |
| } else { |
| - for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { |
| - PhiInstr* phi = (*phis)[phi_idx]; |
| - if (phi == NULL) continue; |
| + for (PhiIterator it(join); !it.Done(); it.Advance()) { |
| + PhiInstr* phi = it.Current(); |
| + ASSERT(phi != NULL); |
| phi->InputAt(pred_idx)->RemoveFromUseList(); |
| } |
| } |
| } |
| if (live_count < pred_count) { |
| - for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { |
| - PhiInstr* phi = (*phis)[phi_idx]; |
| - if (phi == NULL) continue; |
| + intptr_t to_idx = 0; |
| + for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) { |
| + PhiInstr* phi = (*phis)[from_idx]; |
| + ASSERT(phi != NULL); |
| if (FLAG_remove_redundant_phis && (live_count == 1)) { |
|
Vyacheslav Egorov (Google)
2013/02/27 21:53:02
Do we have any code that kills truly redundant phi
Kevin Millikin (Google)
2013/02/28 08:12:02
I don't think so. I wonder, do they arise?
|
| Value* input = phi->InputAt(0); |
| phi->ReplaceUsesWith(input->definition()); |
| input->RemoveFromUseList(); |
| - (*phis)[phi_idx] = NULL; |
| } else { |
| phi->inputs_.TruncateTo(live_count); |
| + (*phis)[to_idx++] = phi; |
| } |
| } |
| + if (to_idx == 0) { |
| + join->phis_ = NULL; |
| + } else { |
| + phis->TruncateTo(to_idx); |
| + } |
| } |
| } |
| } |