| OLD | NEW |
| 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_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 2221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 for (Value* use = def->input_use_list(); | 2232 for (Value* use = def->input_use_list(); |
| 2233 use != NULL; | 2233 use != NULL; |
| 2234 use = next_use) { | 2234 use = next_use) { |
| 2235 next_use = use->next_use(); | 2235 next_use = use->next_use(); |
| 2236 | 2236 |
| 2237 // Skip dead phis. | 2237 // Skip dead phis. |
| 2238 PhiInstr* phi = use->instruction()->AsPhi(); | 2238 PhiInstr* phi = use->instruction()->AsPhi(); |
| 2239 if ((phi != NULL) && !phi->is_alive()) continue; | 2239 if ((phi != NULL) && !phi->is_alive()) continue; |
| 2240 | 2240 |
| 2241 if (IsDominatedUse(dom, use)) { | 2241 if (IsDominatedUse(dom, use)) { |
| 2242 use->RemoveFromInputUseList(); | 2242 use->definition()->RemoveInputUse(use); |
| 2243 use->set_definition(other); | 2243 use->set_definition(other); |
| 2244 use->AddToInputUseList(); | 2244 other->AddInputUse(use); |
| 2245 } | 2245 } |
| 2246 } | 2246 } |
| 2247 } | 2247 } |
| 2248 | 2248 |
| 2249 | 2249 |
| 2250 // For a comparison operation return an operation for the equivalent flipped | 2250 // For a comparison operation return an operation for the equivalent flipped |
| 2251 // comparison: a (op) b === b (op') a. | 2251 // comparison: a (op) b === b (op') a. |
| 2252 static Token::Kind FlipComparison(Token::Kind op) { | 2252 static Token::Kind FlipComparison(Token::Kind op) { |
| 2253 switch (op) { | 2253 switch (op) { |
| 2254 case Token::kEQ: return Token::kEQ; | 2254 case Token::kEQ: return Token::kEQ; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2310 } | 2310 } |
| 2311 } | 2311 } |
| 2312 | 2312 |
| 2313 | 2313 |
| 2314 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, | 2314 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn, |
| 2315 Range* constraint_range, | 2315 Range* constraint_range, |
| 2316 Instruction* after) { | 2316 Instruction* after) { |
| 2317 // No need to constrain constants. | 2317 // No need to constrain constants. |
| 2318 if (defn->IsConstant()) return NULL; | 2318 if (defn->IsConstant()) return NULL; |
| 2319 | 2319 |
| 2320 ConstraintInstr* constraint = | 2320 Value* value = new Value(defn); |
| 2321 new ConstraintInstr(new Value(defn), constraint_range); | 2321 ConstraintInstr* constraint = new ConstraintInstr(value, constraint_range); |
| 2322 constraint->InsertAfter(after); | 2322 constraint->InsertAfter(after); |
| 2323 constraint->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | 2323 constraint->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
| 2324 RenameDominatedUses(defn, after, constraint); | 2324 RenameDominatedUses(defn, after, constraint); |
| 2325 constraints_.Add(constraint); | 2325 constraints_.Add(constraint); |
| 2326 constraint->value()->set_instruction(constraint); | 2326 value->set_instruction(constraint); |
| 2327 constraint->value()->set_use_index(0); | 2327 value->set_use_index(0); |
| 2328 constraint->value()->AddToInputUseList(); | 2328 defn->AddInputUse(value); |
| 2329 return constraint; | 2329 return constraint; |
| 2330 } | 2330 } |
| 2331 | 2331 |
| 2332 | 2332 |
| 2333 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { | 2333 void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) { |
| 2334 BranchInstr* branch = use->instruction()->AsBranch(); | 2334 BranchInstr* branch = use->instruction()->AsBranch(); |
| 2335 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); | 2335 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); |
| 2336 if ((rel_op != NULL) && (rel_op->operands_class_id() == kSmiCid)) { | 2336 if ((rel_op != NULL) && (rel_op->operands_class_id() == kSmiCid)) { |
| 2337 // Found comparison of two smis. Constrain defn at true and false | 2337 // Found comparison of two smis. Constrain defn at true and false |
| 2338 // successors using the other operand as a boundary. | 2338 // successors using the other operand as a boundary. |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2962 ASSERT(last->env() != NULL); | 2962 ASSERT(last->env() != NULL); |
| 2963 last->env()->DeepCopyTo(current); | 2963 last->env()->DeepCopyTo(current); |
| 2964 current->deopt_id_ = last->GetDeoptId(); | 2964 current->deopt_id_ = last->GetDeoptId(); |
| 2965 } | 2965 } |
| 2966 | 2966 |
| 2967 | 2967 |
| 2968 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, | 2968 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, |
| 2969 BlockEntryInstr* header, | 2969 BlockEntryInstr* header, |
| 2970 BlockEntryInstr* pre_header, | 2970 BlockEntryInstr* pre_header, |
| 2971 CheckSmiInstr* current) { | 2971 CheckSmiInstr* current) { |
| 2972 PhiInstr* phi = current->InputAt(0)->definition()->AsPhi(); | 2972 PhiInstr* phi = current->value()->definition()->AsPhi(); |
| 2973 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { | 2973 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { |
| 2974 return; | 2974 return; |
| 2975 } | 2975 } |
| 2976 | 2976 |
| 2977 if (phi->GetPropagatedCid() == kSmiCid) { | 2977 if (phi->GetPropagatedCid() == kSmiCid) { |
| 2978 it->RemoveCurrentFromGraph(); | 2978 it->RemoveCurrentFromGraph(); |
| 2979 return; | 2979 return; |
| 2980 } | 2980 } |
| 2981 | 2981 |
| 2982 // Check if there is only a single kDynamicCid input to the phi that | 2982 // Check if there is only a single kDynamicCid input to the phi that |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2999 if ((non_smi_input == kNotFound) || | 2999 if ((non_smi_input == kNotFound) || |
| 3000 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { | 3000 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { |
| 3001 return; | 3001 return; |
| 3002 } | 3002 } |
| 3003 | 3003 |
| 3004 // Host CheckSmi instruction and make this phi smi one. | 3004 // Host CheckSmi instruction and make this phi smi one. |
| 3005 Hoist(it, pre_header, current); | 3005 Hoist(it, pre_header, current); |
| 3006 | 3006 |
| 3007 // Replace value we are checking with phi's input. Maintain use lists. | 3007 // Replace value we are checking with phi's input. Maintain use lists. |
| 3008 Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition(); | 3008 Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition(); |
| 3009 current->value()->RemoveFromInputUseList(); | 3009 phi->RemoveInputUse(current->value()); |
| 3010 current->value()->set_definition(non_smi_input_defn); | 3010 current->value()->set_definition(non_smi_input_defn); |
| 3011 current->value()->AddToInputUseList(); | 3011 non_smi_input_defn->AddInputUse(current->value()); |
| 3012 | 3012 |
| 3013 phi->SetPropagatedCid(kSmiCid); | 3013 phi->SetPropagatedCid(kSmiCid); |
| 3014 } | 3014 } |
| 3015 | 3015 |
| 3016 | 3016 |
| 3017 void LICM::Optimize(FlowGraph* flow_graph) { | 3017 void LICM::Optimize(FlowGraph* flow_graph) { |
| 3018 GrowableArray<BlockEntryInstr*> loop_headers; | 3018 GrowableArray<BlockEntryInstr*> loop_headers; |
| 3019 flow_graph->ComputeLoops(&loop_headers); | 3019 flow_graph->ComputeLoops(&loop_headers); |
| 3020 | 3020 |
| 3021 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 3021 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3534 BlockEntryInstr* pred = block->PredecessorAt(i); | 3534 BlockEntryInstr* pred = block->PredecessorAt(i); |
| 3535 ZoneGrowableArray<Definition*>* pred_out_values = | 3535 ZoneGrowableArray<Definition*>* pred_out_values = |
| 3536 out_values_[pred->preorder_number()]; | 3536 out_values_[pred->preorder_number()]; |
| 3537 ASSERT((*pred_out_values)[expr_id] != NULL); | 3537 ASSERT((*pred_out_values)[expr_id] != NULL); |
| 3538 | 3538 |
| 3539 // Sets of outgoing values are not linked into use lists so | 3539 // Sets of outgoing values are not linked into use lists so |
| 3540 // they might contain values that were replaced and removed | 3540 // they might contain values that were replaced and removed |
| 3541 // from the graph by this iteration. | 3541 // from the graph by this iteration. |
| 3542 // To prevent using them we additionally mark definitions themselves | 3542 // To prevent using them we additionally mark definitions themselves |
| 3543 // as replaced and store a pointer to the replacement. | 3543 // as replaced and store a pointer to the replacement. |
| 3544 Value* input = new Value((*pred_out_values)[expr_id]->Replacement()); | 3544 Definition* replacement = (*pred_out_values)[expr_id]->Replacement(); |
| 3545 Value* input = new Value(replacement); |
| 3545 phi->SetInputAt(i, input); | 3546 phi->SetInputAt(i, input); |
| 3546 | 3547 |
| 3547 // TODO(vegorov): add a helper function to handle input insertion. | 3548 // TODO(vegorov): add a helper function to handle input insertion. |
| 3548 input->set_instruction(phi); | 3549 input->set_instruction(phi); |
| 3549 input->set_use_index(i); | 3550 input->set_use_index(i); |
| 3550 input->AddToInputUseList(); | 3551 replacement->AddInputUse(input); |
| 3551 } | 3552 } |
| 3552 | 3553 |
| 3553 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); | 3554 phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index()); |
| 3554 phis_.Add(phi); // Postpone phi insertion until after load forwarding. | 3555 phis_.Add(phi); // Postpone phi insertion until after load forwarding. |
| 3555 | 3556 |
| 3556 return phi; | 3557 return phi; |
| 3557 } | 3558 } |
| 3558 | 3559 |
| 3559 // Iterate over basic blocks and replace exposed loads with incoming | 3560 // Iterate over basic blocks and replace exposed loads with incoming |
| 3560 // values. | 3561 // values. |
| (...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4605 | 4606 |
| 4606 if (FLAG_trace_constant_propagation) { | 4607 if (FLAG_trace_constant_propagation) { |
| 4607 OS::Print("\n==== After constant propagation ====\n"); | 4608 OS::Print("\n==== After constant propagation ====\n"); |
| 4608 FlowGraphPrinter printer(*graph_); | 4609 FlowGraphPrinter printer(*graph_); |
| 4609 printer.PrintBlocks(); | 4610 printer.PrintBlocks(); |
| 4610 } | 4611 } |
| 4611 } | 4612 } |
| 4612 | 4613 |
| 4613 | 4614 |
| 4614 } // namespace dart | 4615 } // namespace dart |
| OLD | NEW |