| 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 3414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3425 | 3425 |
| 3426 | 3426 |
| 3427 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { | 3427 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { |
| 3428 ASSERT(flow_graph->is_licm_allowed()); | 3428 ASSERT(flow_graph->is_licm_allowed()); |
| 3429 } | 3429 } |
| 3430 | 3430 |
| 3431 | 3431 |
| 3432 void LICM::Hoist(ForwardInstructionIterator* it, | 3432 void LICM::Hoist(ForwardInstructionIterator* it, |
| 3433 BlockEntryInstr* pre_header, | 3433 BlockEntryInstr* pre_header, |
| 3434 Instruction* current) { | 3434 Instruction* current) { |
| 3435 // TODO(fschneider): Avoid repeated deoptimization when |
| 3436 // speculatively hoisting checks. |
| 3435 if (FLAG_trace_optimization) { | 3437 if (FLAG_trace_optimization) { |
| 3436 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", | 3438 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", |
| 3437 current->DebugName(), | 3439 current->DebugName(), |
| 3438 current->GetDeoptId(), | 3440 current->GetDeoptId(), |
| 3439 current->GetBlock()->block_id(), | 3441 current->GetBlock()->block_id(), |
| 3440 pre_header->block_id()); | 3442 pre_header->block_id()); |
| 3441 } | 3443 } |
| 3442 // Move the instruction out of the loop. | 3444 // Move the instruction out of the loop. |
| 3443 current->RemoveEnvironment(); | 3445 current->RemoveEnvironment(); |
| 3444 it->RemoveCurrentFromGraph(); | 3446 it->RemoveCurrentFromGraph(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3480 } | 3482 } |
| 3481 } | 3483 } |
| 3482 } | 3484 } |
| 3483 | 3485 |
| 3484 if ((non_smi_input == kNotFound) || | 3486 if ((non_smi_input == kNotFound) || |
| 3485 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { | 3487 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { |
| 3486 return; | 3488 return; |
| 3487 } | 3489 } |
| 3488 | 3490 |
| 3489 // Host CheckSmi instruction and make this phi smi one. | 3491 // Host CheckSmi instruction and make this phi smi one. |
| 3490 if (MayHoist(current, pre_header)) Hoist(it, pre_header, current); | 3492 Hoist(it, pre_header, current); |
| 3491 | 3493 |
| 3492 // Replace value we are checking with phi's input. | 3494 // Replace value we are checking with phi's input. |
| 3493 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); | 3495 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); |
| 3494 | 3496 |
| 3495 phi->UpdateType(CompileType::FromCid(kSmiCid)); | 3497 phi->UpdateType(CompileType::FromCid(kSmiCid)); |
| 3496 } | 3498 } |
| 3497 | 3499 |
| 3498 | 3500 |
| 3499 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, | 3501 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, |
| 3500 intptr_t loop_header_index, | 3502 intptr_t loop_header_index, |
| 3501 Instruction* instr) { | 3503 Instruction* instr) { |
| 3502 return (sets != NULL) && | 3504 return (sets != NULL) && |
| 3503 instr->HasExprId() && | 3505 instr->HasExprId() && |
| 3504 ((*sets)[loop_header_index] != NULL) && | 3506 ((*sets)[loop_header_index] != NULL) && |
| 3505 (*sets)[loop_header_index]->Contains(instr->expr_id()); | 3507 (*sets)[loop_header_index]->Contains(instr->expr_id()); |
| 3506 } | 3508 } |
| 3507 | 3509 |
| 3508 | 3510 |
| 3509 bool LICM::MayHoist(Instruction* instr, BlockEntryInstr* pre_header) { | |
| 3510 // TODO(fschneider): Enable hoisting of Assert-instructions | |
| 3511 // if it safe to do. | |
| 3512 if (instr->IsAssertAssignable()) return false; | |
| 3513 if (instr->IsAssertBoolean()) return false; | |
| 3514 | |
| 3515 if (instr->CanDeoptimize()) { | |
| 3516 intptr_t target_deopt_id = | |
| 3517 pre_header->last_instruction()->AsGoto()->GetDeoptId(); | |
| 3518 const Function& function = flow_graph_->parsed_function().function(); | |
| 3519 const Array& deopt_history = Array::Handle(function.deopt_history()); | |
| 3520 if (deopt_history.IsNull()) return true; | |
| 3521 | |
| 3522 Smi& deopt_id = Smi::Handle(); | |
| 3523 for (intptr_t i = 0; i < deopt_history.Length(); ++i) { | |
| 3524 deopt_id ^= deopt_history.At(i); | |
| 3525 if (!deopt_id.IsNull() && (deopt_id.Value() == target_deopt_id)) { | |
| 3526 return false; | |
| 3527 } | |
| 3528 } | |
| 3529 } | |
| 3530 return true; | |
| 3531 } | |
| 3532 | |
| 3533 | |
| 3534 void LICM::Optimize() { | 3511 void LICM::Optimize() { |
| 3535 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 3512 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 3536 flow_graph()->loop_headers(); | 3513 flow_graph()->loop_headers(); |
| 3537 | 3514 |
| 3538 ZoneGrowableArray<BitVector*>* loop_invariant_loads = | 3515 ZoneGrowableArray<BitVector*>* loop_invariant_loads = |
| 3539 flow_graph()->loop_invariant_loads(); | 3516 flow_graph()->loop_invariant_loads(); |
| 3540 | 3517 |
| 3541 BlockEffects* block_effects = flow_graph()->block_effects(); | 3518 BlockEffects* block_effects = flow_graph()->block_effects(); |
| 3542 | 3519 |
| 3543 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 3520 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3558 block_effects->CanBeMovedTo(current, pre_header)) || | 3535 block_effects->CanBeMovedTo(current, pre_header)) || |
| 3559 IsLoopInvariantLoad(loop_invariant_loads, i, current)) { | 3536 IsLoopInvariantLoad(loop_invariant_loads, i, current)) { |
| 3560 bool inputs_loop_invariant = true; | 3537 bool inputs_loop_invariant = true; |
| 3561 for (int i = 0; i < current->InputCount(); ++i) { | 3538 for (int i = 0; i < current->InputCount(); ++i) { |
| 3562 Definition* input_def = current->InputAt(i)->definition(); | 3539 Definition* input_def = current->InputAt(i)->definition(); |
| 3563 if (!input_def->GetBlock()->Dominates(pre_header)) { | 3540 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 3564 inputs_loop_invariant = false; | 3541 inputs_loop_invariant = false; |
| 3565 break; | 3542 break; |
| 3566 } | 3543 } |
| 3567 } | 3544 } |
| 3568 if (inputs_loop_invariant && MayHoist(current, pre_header)) { | 3545 if (inputs_loop_invariant && |
| 3546 !current->IsAssertAssignable() && |
| 3547 !current->IsAssertBoolean()) { |
| 3548 // TODO(fschneider): Enable hoisting of Assert-instructions |
| 3549 // if it safe to do. |
| 3569 Hoist(&it, pre_header, current); | 3550 Hoist(&it, pre_header, current); |
| 3570 } else if (current->IsCheckSmi() && | 3551 } else if (current->IsCheckSmi() && |
| 3571 current->InputAt(0)->definition()->IsPhi()) { | 3552 current->InputAt(0)->definition()->IsPhi()) { |
| 3572 TryHoistCheckSmiThroughPhi( | 3553 TryHoistCheckSmiThroughPhi( |
| 3573 &it, header, pre_header, current->AsCheckSmi()); | 3554 &it, header, pre_header, current->AsCheckSmi()); |
| 3574 } | 3555 } |
| 3575 } | 3556 } |
| 3576 } | 3557 } |
| 3577 } | 3558 } |
| 3578 } | 3559 } |
| (...skipping 3010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6589 | 6570 |
| 6590 // Insert materializations at environment uses. | 6571 // Insert materializations at environment uses. |
| 6591 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 6572 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
| 6592 for (intptr_t i = 0; i < exits.length(); i++) { | 6573 for (intptr_t i = 0; i < exits.length(); i++) { |
| 6593 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 6574 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
| 6594 } | 6575 } |
| 6595 } | 6576 } |
| 6596 | 6577 |
| 6597 | 6578 |
| 6598 } // namespace dart | 6579 } // namespace dart |
| OLD | NEW |