| 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 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 replacement_defn->ssa_temp_index()); | 283 replacement_defn->ssa_temp_index()); |
| 284 } | 284 } |
| 285 } else if (FLAG_trace_optimization) { | 285 } else if (FLAG_trace_optimization) { |
| 286 if (current_defn == NULL) { | 286 if (current_defn == NULL) { |
| 287 OS::Print("Removing %s\n", current->DebugName()); | 287 OS::Print("Removing %s\n", current->DebugName()); |
| 288 } else { | 288 } else { |
| 289 ASSERT(!current_defn->HasUses()); | 289 ASSERT(!current_defn->HasUses()); |
| 290 OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index()); | 290 OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index()); |
| 291 } | 291 } |
| 292 } | 292 } |
| 293 current->UnuseAllInputs(); | |
| 294 iterator->RemoveCurrentFromGraph(); | 293 iterator->RemoveCurrentFromGraph(); |
| 295 } | 294 } |
| 296 | 295 |
| 297 | 296 |
| 298 void FlowGraphOptimizer::Canonicalize() { | 297 void FlowGraphOptimizer::Canonicalize() { |
| 299 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 298 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 300 BlockEntryInstr* entry = block_order_[i]; | 299 BlockEntryInstr* entry = block_order_[i]; |
| 301 entry->Accept(this); | 300 entry->Accept(this); |
| 302 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 301 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 303 Instruction* current = it.Current(); | 302 Instruction* current = it.Current(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 326 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 325 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 327 converted = new UnboxIntegerInstr(use->CopyWithType(), deopt_id); | 326 converted = new UnboxIntegerInstr(use->CopyWithType(), deopt_id); |
| 328 | 327 |
| 329 } else if ((from == kUnboxedMint) && (to == kTagged)) { | 328 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
| 330 converted = new BoxIntegerInstr(use->CopyWithType()); | 329 converted = new BoxIntegerInstr(use->CopyWithType()); |
| 331 | 330 |
| 332 } else if (from == kUnboxedMint && to == kUnboxedDouble) { | 331 } else if (from == kUnboxedMint && to == kUnboxedDouble) { |
| 333 // Convert by boxing/unboxing. | 332 // Convert by boxing/unboxing. |
| 334 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. | 333 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. |
| 335 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType()); | 334 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType()); |
| 336 use->RemoveFromUseList(); | 335 use->BindTo(boxed); |
| 337 use->set_definition(boxed); | |
| 338 boxed->AddInputUse(use); | |
| 339 InsertBefore(insert_before, boxed, NULL, Definition::kValue); | 336 InsertBefore(insert_before, boxed, NULL, Definition::kValue); |
| 340 | 337 |
| 341 const intptr_t deopt_id = (deopt_target != NULL) ? | 338 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 342 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 339 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 343 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id); | 340 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id); |
| 344 | 341 |
| 345 } else if ((from == kUnboxedDouble) && (to == kTagged)) { | 342 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 346 converted = new BoxDoubleInstr(use->CopyWithType(), NULL); | 343 converted = new BoxDoubleInstr(use->CopyWithType(), NULL); |
| 347 | 344 |
| 348 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 345 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 349 ASSERT((deopt_target != NULL) || | 346 ASSERT((deopt_target != NULL) || |
| 350 (use->Type()->ToCid() == kDoubleCid)); | 347 (use->Type()->ToCid() == kDoubleCid)); |
| 351 const intptr_t deopt_id = (deopt_target != NULL) ? | 348 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 352 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 349 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 353 ConstantInstr* constant = use->definition()->AsConstant(); | 350 ConstantInstr* constant = use->definition()->AsConstant(); |
| 354 if ((constant != NULL) && constant->value().IsSmi()) { | 351 if ((constant != NULL) && constant->value().IsSmi()) { |
| 355 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); | 352 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); |
| 356 const Double& dbl_obj = | 353 const Double& dbl_obj = |
| 357 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld)); | 354 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld)); |
| 358 ConstantInstr* double_const = new ConstantInstr(dbl_obj); | 355 ConstantInstr* double_const = new ConstantInstr(dbl_obj); |
| 359 InsertBefore(insert_before, double_const, NULL, Definition::kValue); | 356 InsertBefore(insert_before, double_const, NULL, Definition::kValue); |
| 360 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id); | 357 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id); |
| 361 } else { | 358 } else { |
| 362 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); | 359 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); |
| 363 } | 360 } |
| 364 } | 361 } |
| 365 ASSERT(converted != NULL); | 362 ASSERT(converted != NULL); |
| 366 use->RemoveFromUseList(); | 363 use->BindTo(converted); |
| 367 use->set_definition(converted); | |
| 368 converted->AddInputUse(use); | |
| 369 InsertBefore(insert_before, converted, use->instruction()->env(), | 364 InsertBefore(insert_before, converted, use->instruction()->env(), |
| 370 Definition::kValue); | 365 Definition::kValue); |
| 371 } | 366 } |
| 372 | 367 |
| 373 | 368 |
| 374 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { | 369 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { |
| 375 const Representation from_rep = def->representation(); | 370 const Representation from_rep = def->representation(); |
| 376 | 371 |
| 377 for (Value::Iterator it(def->input_use_list()); | 372 for (Value::Iterator it(def->input_use_list()); |
| 378 !it.Done(); | 373 !it.Done(); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 553 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
| 559 } | 554 } |
| 560 | 555 |
| 561 | 556 |
| 562 void FlowGraphOptimizer::ReplaceCall(Definition* call, | 557 void FlowGraphOptimizer::ReplaceCall(Definition* call, |
| 563 Definition* replacement) { | 558 Definition* replacement) { |
| 564 // Remove the original push arguments. | 559 // Remove the original push arguments. |
| 565 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 560 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 566 PushArgumentInstr* push = call->PushArgumentAt(i); | 561 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 567 push->ReplaceUsesWith(push->value()->definition()); | 562 push->ReplaceUsesWith(push->value()->definition()); |
| 568 push->UnuseAllInputs(); | |
| 569 push->RemoveFromGraph(); | 563 push->RemoveFromGraph(); |
| 570 } | 564 } |
| 571 call->ReplaceWith(replacement, current_iterator()); | 565 call->ReplaceWith(replacement, current_iterator()); |
| 572 } | 566 } |
| 573 | 567 |
| 574 | 568 |
| 575 static intptr_t ReceiverClassId(InstanceCallInstr* call) { | 569 static intptr_t ReceiverClassId(InstanceCallInstr* call) { |
| 576 if (!call->HasICData()) return kIllegalCid; | 570 if (!call->HasICData()) return kIllegalCid; |
| 577 | 571 |
| 578 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); | 572 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 ASSERT(!field.IsNull()); | 1227 ASSERT(!field.IsNull()); |
| 1234 | 1228 |
| 1235 if (InstanceCallNeedsClassCheck(call)) { | 1229 if (InstanceCallNeedsClassCheck(call)) { |
| 1236 AddReceiverCheck(call); | 1230 AddReceiverCheck(call); |
| 1237 } | 1231 } |
| 1238 LoadFieldInstr* load = new LoadFieldInstr( | 1232 LoadFieldInstr* load = new LoadFieldInstr( |
| 1239 new Value(call->ArgumentAt(0)), | 1233 new Value(call->ArgumentAt(0)), |
| 1240 field.Offset(), | 1234 field.Offset(), |
| 1241 AbstractType::ZoneHandle(field.type()), | 1235 AbstractType::ZoneHandle(field.type()), |
| 1242 field.is_final()); | 1236 field.is_final()); |
| 1243 // Detach environment from the original instruction because it can't | 1237 // Discard the environment from the original instruction because the load |
| 1244 // deoptimize. | 1238 // can't deoptimize. |
| 1245 for (Environment::DeepIterator it(call->env()); !it.Done(); it.Advance()) { | 1239 call->RemoveEnvironment(); |
| 1246 it.CurrentValue()->RemoveFromUseList(); | |
| 1247 } | |
| 1248 call->set_env(NULL); | |
| 1249 ReplaceCall(call, load); | 1240 ReplaceCall(call, load); |
| 1250 } | 1241 } |
| 1251 | 1242 |
| 1252 | 1243 |
| 1253 void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, | 1244 void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, |
| 1254 intptr_t length_offset, | 1245 intptr_t length_offset, |
| 1255 bool is_immutable, | 1246 bool is_immutable, |
| 1256 MethodRecognizer::Kind kind) { | 1247 MethodRecognizer::Kind kind) { |
| 1257 AddReceiverCheck(call); | 1248 AddReceiverCheck(call); |
| 1258 | 1249 |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1913 instr->deopt_id()), | 1904 instr->deopt_id()), |
| 1914 instr->env(), | 1905 instr->env(), |
| 1915 Definition::kEffect); | 1906 Definition::kEffect); |
| 1916 needs_store_barrier = false; | 1907 needs_store_barrier = false; |
| 1917 } | 1908 } |
| 1918 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 1909 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 1919 field, | 1910 field, |
| 1920 new Value(instr->ArgumentAt(0)), | 1911 new Value(instr->ArgumentAt(0)), |
| 1921 new Value(instr->ArgumentAt(1)), | 1912 new Value(instr->ArgumentAt(1)), |
| 1922 needs_store_barrier); | 1913 needs_store_barrier); |
| 1923 // Detach environment from the original instruction because it can't | 1914 // Discard the environment from the original instruction because the store |
| 1924 // deoptimize. | 1915 // can't deoptimize. |
| 1925 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { | 1916 instr->RemoveEnvironment(); |
| 1926 it.CurrentValue()->RemoveFromUseList(); | |
| 1927 } | |
| 1928 instr->set_env(NULL); | |
| 1929 ReplaceCall(instr, store); | 1917 ReplaceCall(instr, store); |
| 1930 return true; | 1918 return true; |
| 1931 } | 1919 } |
| 1932 | 1920 |
| 1933 | 1921 |
| 1934 void FlowGraphOptimizer::HandleRelationalOp(RelationalOpInstr* comp) { | 1922 void FlowGraphOptimizer::HandleRelationalOp(RelationalOpInstr* comp) { |
| 1935 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { | 1923 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { |
| 1936 return; | 1924 return; |
| 1937 } | 1925 } |
| 1938 const ICData& ic_data = *comp->ic_data(); | 1926 const ICData& ic_data = *comp->ic_data(); |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2264 for (Value::Iterator it(def->input_use_list()); | 2252 for (Value::Iterator it(def->input_use_list()); |
| 2265 !it.Done(); | 2253 !it.Done(); |
| 2266 it.Advance()) { | 2254 it.Advance()) { |
| 2267 Value* use = it.Current(); | 2255 Value* use = it.Current(); |
| 2268 | 2256 |
| 2269 // Skip dead phis. | 2257 // Skip dead phis. |
| 2270 PhiInstr* phi = use->instruction()->AsPhi(); | 2258 PhiInstr* phi = use->instruction()->AsPhi(); |
| 2271 if ((phi != NULL) && !phi->is_alive()) continue; | 2259 if ((phi != NULL) && !phi->is_alive()) continue; |
| 2272 | 2260 |
| 2273 if (IsDominatedUse(dom, use)) { | 2261 if (IsDominatedUse(dom, use)) { |
| 2274 use->RemoveFromUseList(); | 2262 use->BindTo(other); |
| 2275 use->set_definition(other); | |
| 2276 other->AddInputUse(use); | |
| 2277 } | 2263 } |
| 2278 } | 2264 } |
| 2279 } | 2265 } |
| 2280 | 2266 |
| 2281 | 2267 |
| 2282 // For a comparison operation return an operation for the equivalent flipped | 2268 // For a comparison operation return an operation for the equivalent flipped |
| 2283 // comparison: a (op) b === b (op') a. | 2269 // comparison: a (op) b === b (op') a. |
| 2284 static Token::Kind FlipComparison(Token::Kind op) { | 2270 static Token::Kind FlipComparison(Token::Kind op) { |
| 2285 switch (op) { | 2271 switch (op) { |
| 2286 case Token::kEQ: return Token::kEQ; | 2272 case Token::kEQ: return Token::kEQ; |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2611 if ((defn != NULL) && | 2597 if ((defn != NULL) && |
| 2612 (defn->ssa_temp_index() != -1) && | 2598 (defn->ssa_temp_index() != -1) && |
| 2613 smi_definitions_->Contains(defn->ssa_temp_index())) { | 2599 smi_definitions_->Contains(defn->ssa_temp_index())) { |
| 2614 defn->InferRange(); | 2600 defn->InferRange(); |
| 2615 } else if (FLAG_array_bounds_check_elimination && | 2601 } else if (FLAG_array_bounds_check_elimination && |
| 2616 current->IsCheckArrayBound()) { | 2602 current->IsCheckArrayBound()) { |
| 2617 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); | 2603 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); |
| 2618 RangeBoundary array_length = | 2604 RangeBoundary array_length = |
| 2619 RangeBoundary::FromDefinition(check->length()->definition()); | 2605 RangeBoundary::FromDefinition(check->length()->definition()); |
| 2620 if (check->IsRedundant(array_length)) { | 2606 if (check->IsRedundant(array_length)) { |
| 2621 current->UnuseAllInputs(); | |
| 2622 it.RemoveCurrentFromGraph(); | 2607 it.RemoveCurrentFromGraph(); |
| 2623 } | 2608 } |
| 2624 } | 2609 } |
| 2625 } | 2610 } |
| 2626 | 2611 |
| 2627 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 2612 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
| 2628 InferRangesRecursive(block->dominated_blocks()[i]); | 2613 InferRangesRecursive(block->dominated_blocks()[i]); |
| 2629 } | 2614 } |
| 2630 } | 2615 } |
| 2631 | 2616 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2653 | 2638 |
| 2654 void RangeAnalysis::RemoveConstraints() { | 2639 void RangeAnalysis::RemoveConstraints() { |
| 2655 for (intptr_t i = 0; i < constraints_.length(); i++) { | 2640 for (intptr_t i = 0; i < constraints_.length(); i++) { |
| 2656 Definition* def = constraints_[i]->value()->definition(); | 2641 Definition* def = constraints_[i]->value()->definition(); |
| 2657 // Some constraints might be constraining constraints. Unwind the chain of | 2642 // Some constraints might be constraining constraints. Unwind the chain of |
| 2658 // constraints until we reach the actual definition. | 2643 // constraints until we reach the actual definition. |
| 2659 while (def->IsConstraint()) { | 2644 while (def->IsConstraint()) { |
| 2660 def = def->AsConstraint()->value()->definition(); | 2645 def = def->AsConstraint()->value()->definition(); |
| 2661 } | 2646 } |
| 2662 constraints_[i]->ReplaceUsesWith(def); | 2647 constraints_[i]->ReplaceUsesWith(def); |
| 2663 constraints_[i]->UnuseAllInputs(); | |
| 2664 constraints_[i]->RemoveFromGraph(); | 2648 constraints_[i]->RemoveFromGraph(); |
| 2665 } | 2649 } |
| 2666 } | 2650 } |
| 2667 | 2651 |
| 2668 | 2652 |
| 2669 void FlowGraphOptimizer::InferSmiRanges() { | 2653 void FlowGraphOptimizer::InferSmiRanges() { |
| 2670 RangeAnalysis range_analysis(flow_graph_); | 2654 RangeAnalysis range_analysis(flow_graph_); |
| 2671 range_analysis.Analyze(); | 2655 range_analysis.Analyze(); |
| 2672 } | 2656 } |
| 2673 | 2657 |
| 2674 | 2658 |
| 2675 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { | 2659 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { |
| 2676 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { | 2660 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { |
| 2677 BlockEntryInstr* candidate = header->PredecessorAt(j); | 2661 BlockEntryInstr* candidate = header->PredecessorAt(j); |
| 2678 if (header->dominator() == candidate) { | 2662 if (header->dominator() == candidate) { |
| 2679 return candidate; | 2663 return candidate; |
| 2680 } | 2664 } |
| 2681 } | 2665 } |
| 2682 return NULL; | 2666 return NULL; |
| 2683 } | 2667 } |
| 2684 | 2668 |
| 2685 | 2669 |
| 2670 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { |
| 2671 } |
| 2672 |
| 2673 |
| 2686 void LICM::Hoist(ForwardInstructionIterator* it, | 2674 void LICM::Hoist(ForwardInstructionIterator* it, |
| 2687 BlockEntryInstr* pre_header, | 2675 BlockEntryInstr* pre_header, |
| 2688 Instruction* current) { | 2676 Instruction* current) { |
| 2689 // TODO(fschneider): Avoid repeated deoptimization when | 2677 // TODO(fschneider): Avoid repeated deoptimization when |
| 2690 // speculatively hoisting checks. | 2678 // speculatively hoisting checks. |
| 2691 if (FLAG_trace_optimization) { | 2679 if (FLAG_trace_optimization) { |
| 2692 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", | 2680 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", |
| 2693 current->DebugName(), | 2681 current->DebugName(), |
| 2694 current->GetDeoptId(), | 2682 current->GetDeoptId(), |
| 2695 current->GetBlock()->block_id(), | 2683 current->GetBlock()->block_id(), |
| 2696 pre_header->block_id()); | 2684 pre_header->block_id()); |
| 2697 } | 2685 } |
| 2698 // Move the instruction out of the loop. | 2686 // Move the instruction out of the loop. |
| 2687 current->RemoveEnvironment(); |
| 2699 it->RemoveCurrentFromGraph(); | 2688 it->RemoveCurrentFromGraph(); |
| 2700 GotoInstr* last = pre_header->last_instruction()->AsGoto(); | 2689 GotoInstr* last = pre_header->last_instruction()->AsGoto(); |
| 2701 current->InsertBefore(last); | 2690 // Using kind kEffect will not assign a fresh ssa temporary index. |
| 2702 // Attach the environment of the Goto instruction to the hoisted | 2691 flow_graph()->InsertBefore(last, current, last->env(), Definition::kEffect); |
| 2703 // instruction and set the correct deopt_id. | |
| 2704 ASSERT(last->env() != NULL); | |
| 2705 last->env()->DeepCopyTo(current); | |
| 2706 current->deopt_id_ = last->GetDeoptId(); | 2692 current->deopt_id_ = last->GetDeoptId(); |
| 2707 } | 2693 } |
| 2708 | 2694 |
| 2709 | 2695 |
| 2710 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, | 2696 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, |
| 2711 BlockEntryInstr* header, | 2697 BlockEntryInstr* header, |
| 2712 BlockEntryInstr* pre_header, | 2698 BlockEntryInstr* pre_header, |
| 2713 CheckSmiInstr* current) { | 2699 CheckSmiInstr* current) { |
| 2714 PhiInstr* phi = current->value()->definition()->AsPhi(); | 2700 PhiInstr* phi = current->value()->definition()->AsPhi(); |
| 2715 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { | 2701 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { |
| 2716 return; | 2702 return; |
| 2717 } | 2703 } |
| 2718 | 2704 |
| 2719 if (phi->Type()->ToCid() == kSmiCid) { | 2705 if (phi->Type()->ToCid() == kSmiCid) { |
| 2720 current->UnuseAllInputs(); | |
| 2721 it->RemoveCurrentFromGraph(); | 2706 it->RemoveCurrentFromGraph(); |
| 2722 return; | 2707 return; |
| 2723 } | 2708 } |
| 2724 | 2709 |
| 2725 // Check if there is only a single kDynamicCid input to the phi that | 2710 // Check if there is only a single kDynamicCid input to the phi that |
| 2726 // comes from the pre-header. | 2711 // comes from the pre-header. |
| 2727 const intptr_t kNotFound = -1; | 2712 const intptr_t kNotFound = -1; |
| 2728 intptr_t non_smi_input = kNotFound; | 2713 intptr_t non_smi_input = kNotFound; |
| 2729 for (intptr_t i = 0; i < phi->InputCount(); ++i) { | 2714 for (intptr_t i = 0; i < phi->InputCount(); ++i) { |
| 2730 Value* input = phi->InputAt(i); | 2715 Value* input = phi->InputAt(i); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2741 } | 2726 } |
| 2742 | 2727 |
| 2743 if ((non_smi_input == kNotFound) || | 2728 if ((non_smi_input == kNotFound) || |
| 2744 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { | 2729 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { |
| 2745 return; | 2730 return; |
| 2746 } | 2731 } |
| 2747 | 2732 |
| 2748 // Host CheckSmi instruction and make this phi smi one. | 2733 // Host CheckSmi instruction and make this phi smi one. |
| 2749 Hoist(it, pre_header, current); | 2734 Hoist(it, pre_header, current); |
| 2750 | 2735 |
| 2751 // Replace value we are checking with phi's input. Maintain use lists. | 2736 // Replace value we are checking with phi's input. |
| 2752 Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition(); | 2737 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); |
| 2753 current->value()->RemoveFromUseList(); | |
| 2754 current->value()->set_definition(non_smi_input_defn); | |
| 2755 non_smi_input_defn->AddInputUse(current->value()); | |
| 2756 | 2738 |
| 2757 phi->UpdateType(CompileType::FromCid(kSmiCid)); | 2739 phi->UpdateType(CompileType::FromCid(kSmiCid)); |
| 2758 } | 2740 } |
| 2759 | 2741 |
| 2760 | 2742 |
| 2761 void LICM::Optimize(FlowGraph* flow_graph) { | 2743 void LICM::Optimize() { |
| 2762 GrowableArray<BlockEntryInstr*> loop_headers; | 2744 GrowableArray<BlockEntryInstr*> loop_headers; |
| 2763 flow_graph->ComputeLoops(&loop_headers); | 2745 flow_graph()->ComputeLoops(&loop_headers); |
| 2764 | 2746 |
| 2765 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 2747 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| 2766 BlockEntryInstr* header = loop_headers[i]; | 2748 BlockEntryInstr* header = loop_headers[i]; |
| 2767 // Skip loop that don't have a pre-header block. | 2749 // Skip loop that don't have a pre-header block. |
| 2768 BlockEntryInstr* pre_header = FindPreHeader(header); | 2750 BlockEntryInstr* pre_header = FindPreHeader(header); |
| 2769 if (pre_header == NULL) continue; | 2751 if (pre_header == NULL) continue; |
| 2770 | 2752 |
| 2771 for (BitVector::Iterator loop_it(header->loop_info()); | 2753 for (BitVector::Iterator loop_it(header->loop_info()); |
| 2772 !loop_it.Done(); | 2754 !loop_it.Done(); |
| 2773 loop_it.Advance()) { | 2755 loop_it.Advance()) { |
| 2774 BlockEntryInstr* block = flow_graph->preorder()[loop_it.Current()]; | 2756 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()]; |
| 2775 for (ForwardInstructionIterator it(block); | 2757 for (ForwardInstructionIterator it(block); |
| 2776 !it.Done(); | 2758 !it.Done(); |
| 2777 it.Advance()) { | 2759 it.Advance()) { |
| 2778 Instruction* current = it.Current(); | 2760 Instruction* current = it.Current(); |
| 2779 if (!current->IsPushArgument() && !current->AffectedBySideEffect()) { | 2761 if (!current->IsPushArgument() && !current->AffectedBySideEffect()) { |
| 2780 bool inputs_loop_invariant = true; | 2762 bool inputs_loop_invariant = true; |
| 2781 for (int i = 0; i < current->InputCount(); ++i) { | 2763 for (int i = 0; i < current->InputCount(); ++i) { |
| 2782 Definition* input_def = current->InputAt(i)->definition(); | 2764 Definition* input_def = current->InputAt(i)->definition(); |
| 2783 if (!input_def->GetBlock()->Dominates(pre_header)) { | 2765 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 2784 inputs_loop_invariant = false; | 2766 inputs_loop_invariant = false; |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3120 | 3102 |
| 3121 Definition* replacement = (*out_values)[expr_id]; | 3103 Definition* replacement = (*out_values)[expr_id]; |
| 3122 EnsureSSATempIndex(graph_, defn, replacement); | 3104 EnsureSSATempIndex(graph_, defn, replacement); |
| 3123 if (FLAG_trace_optimization) { | 3105 if (FLAG_trace_optimization) { |
| 3124 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", | 3106 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", |
| 3125 defn->ssa_temp_index(), | 3107 defn->ssa_temp_index(), |
| 3126 replacement->ssa_temp_index()); | 3108 replacement->ssa_temp_index()); |
| 3127 } | 3109 } |
| 3128 | 3110 |
| 3129 defn->ReplaceUsesWith(replacement); | 3111 defn->ReplaceUsesWith(replacement); |
| 3130 defn->UnuseAllInputs(); | |
| 3131 instr_it.RemoveCurrentFromGraph(); | 3112 instr_it.RemoveCurrentFromGraph(); |
| 3132 continue; | 3113 continue; |
| 3133 } else if (!kill->Contains(expr_id)) { | 3114 } else if (!kill->Contains(expr_id)) { |
| 3134 // This is an exposed load: it is the first representative of a | 3115 // This is an exposed load: it is the first representative of a |
| 3135 // given expression id and it is not killed on the path from | 3116 // given expression id and it is not killed on the path from |
| 3136 // the block entry. | 3117 // the block entry. |
| 3137 if (exposed_values == NULL) { | 3118 if (exposed_values == NULL) { |
| 3138 static const intptr_t kMaxExposedValuesInitialSize = 5; | 3119 static const intptr_t kMaxExposedValuesInitialSize = 5; |
| 3139 exposed_values = new ZoneGrowableArray<Definition*>( | 3120 exposed_values = new ZoneGrowableArray<Definition*>( |
| 3140 Utils::Minimum(kMaxExposedValuesInitialSize, max_expr_id_)); | 3121 Utils::Minimum(kMaxExposedValuesInitialSize, max_expr_id_)); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3328 if (load != replacement) { | 3309 if (load != replacement) { |
| 3329 EnsureSSATempIndex(graph_, load, replacement); | 3310 EnsureSSATempIndex(graph_, load, replacement); |
| 3330 | 3311 |
| 3331 if (FLAG_trace_optimization) { | 3312 if (FLAG_trace_optimization) { |
| 3332 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", | 3313 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", |
| 3333 load->ssa_temp_index(), | 3314 load->ssa_temp_index(), |
| 3334 replacement->ssa_temp_index()); | 3315 replacement->ssa_temp_index()); |
| 3335 } | 3316 } |
| 3336 | 3317 |
| 3337 load->ReplaceUsesWith(replacement); | 3318 load->ReplaceUsesWith(replacement); |
| 3338 load->UnuseAllInputs(); | |
| 3339 load->RemoveFromGraph(); | 3319 load->RemoveFromGraph(); |
| 3340 load->SetReplacement(replacement); | 3320 load->SetReplacement(replacement); |
| 3341 } | 3321 } |
| 3342 } | 3322 } |
| 3343 } | 3323 } |
| 3344 } | 3324 } |
| 3345 | 3325 |
| 3346 // Check if the given phi take the same value on all code paths. | 3326 // Check if the given phi take the same value on all code paths. |
| 3347 // Eliminate it as redundant if this is the case. | 3327 // Eliminate it as redundant if this is the case. |
| 3348 // When analyzing phi operands assumes that only generated during | 3328 // When analyzing phi operands assumes that only generated during |
| (...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4377 | 4357 |
| 4378 if (FLAG_trace_constant_propagation) { | 4358 if (FLAG_trace_constant_propagation) { |
| 4379 OS::Print("\n==== After constant propagation ====\n"); | 4359 OS::Print("\n==== After constant propagation ====\n"); |
| 4380 FlowGraphPrinter printer(*graph_); | 4360 FlowGraphPrinter printer(*graph_); |
| 4381 printer.PrintBlocks(); | 4361 printer.PrintBlocks(); |
| 4382 } | 4362 } |
| 4383 } | 4363 } |
| 4384 | 4364 |
| 4385 | 4365 |
| 4386 } // namespace dart | 4366 } // namespace dart |
| OLD | NEW |