| 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 3397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3408 | 3408 |
| 3409 | 3409 |
| 3410 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { | 3410 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) { |
| 3411 ASSERT(flow_graph->is_licm_allowed()); | 3411 ASSERT(flow_graph->is_licm_allowed()); |
| 3412 } | 3412 } |
| 3413 | 3413 |
| 3414 | 3414 |
| 3415 void LICM::Hoist(ForwardInstructionIterator* it, | 3415 void LICM::Hoist(ForwardInstructionIterator* it, |
| 3416 BlockEntryInstr* pre_header, | 3416 BlockEntryInstr* pre_header, |
| 3417 Instruction* current) { | 3417 Instruction* current) { |
| 3418 // TODO(fschneider): Avoid repeated deoptimization when | |
| 3419 // speculatively hoisting checks. | |
| 3420 if (FLAG_trace_optimization) { | 3418 if (FLAG_trace_optimization) { |
| 3421 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", | 3419 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", |
| 3422 current->DebugName(), | 3420 current->DebugName(), |
| 3423 current->GetDeoptId(), | 3421 current->GetDeoptId(), |
| 3424 current->GetBlock()->block_id(), | 3422 current->GetBlock()->block_id(), |
| 3425 pre_header->block_id()); | 3423 pre_header->block_id()); |
| 3426 } | 3424 } |
| 3427 // Move the instruction out of the loop. | 3425 // Move the instruction out of the loop. |
| 3428 current->RemoveEnvironment(); | 3426 current->RemoveEnvironment(); |
| 3429 it->RemoveCurrentFromGraph(); | 3427 it->RemoveCurrentFromGraph(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3465 } | 3463 } |
| 3466 } | 3464 } |
| 3467 } | 3465 } |
| 3468 | 3466 |
| 3469 if ((non_smi_input == kNotFound) || | 3467 if ((non_smi_input == kNotFound) || |
| 3470 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { | 3468 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { |
| 3471 return; | 3469 return; |
| 3472 } | 3470 } |
| 3473 | 3471 |
| 3474 // Host CheckSmi instruction and make this phi smi one. | 3472 // Host CheckSmi instruction and make this phi smi one. |
| 3475 Hoist(it, pre_header, current); | 3473 if (MayHoist(current, pre_header)) Hoist(it, pre_header, current); |
| 3476 | 3474 |
| 3477 // Replace value we are checking with phi's input. | 3475 // Replace value we are checking with phi's input. |
| 3478 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); | 3476 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); |
| 3479 | 3477 |
| 3480 phi->UpdateType(CompileType::FromCid(kSmiCid)); | 3478 phi->UpdateType(CompileType::FromCid(kSmiCid)); |
| 3481 } | 3479 } |
| 3482 | 3480 |
| 3483 | 3481 |
| 3484 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, | 3482 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, |
| 3485 intptr_t loop_header_index, | 3483 intptr_t loop_header_index, |
| 3486 Instruction* instr) { | 3484 Instruction* instr) { |
| 3487 return (sets != NULL) && | 3485 return (sets != NULL) && |
| 3488 instr->HasExprId() && | 3486 instr->HasExprId() && |
| 3489 ((*sets)[loop_header_index] != NULL) && | 3487 ((*sets)[loop_header_index] != NULL) && |
| 3490 (*sets)[loop_header_index]->Contains(instr->expr_id()); | 3488 (*sets)[loop_header_index]->Contains(instr->expr_id()); |
| 3491 } | 3489 } |
| 3492 | 3490 |
| 3493 | 3491 |
| 3492 bool LICM::MayHoist(Instruction* instr, BlockEntryInstr* pre_header) { |
| 3493 // TODO(fschneider): Enable hoisting of Assert-instructions |
| 3494 // if it safe to do. |
| 3495 if (instr->IsAssertAssignable()) return false; |
| 3496 if (instr->IsAssertBoolean()) return false; |
| 3497 |
| 3498 if (instr->CanDeoptimize()) { |
| 3499 intptr_t target_deopt_id = |
| 3500 pre_header->last_instruction()->AsGoto()->GetDeoptId(); |
| 3501 const Function& function = flow_graph_->parsed_function().function(); |
| 3502 const Array& deopt_history = Array::Handle(function.deopt_history()); |
| 3503 if (deopt_history.IsNull()) return true; |
| 3504 |
| 3505 Smi& deopt_id = Smi::Handle(); |
| 3506 for (intptr_t i = 0; i < deopt_history.Length(); ++i) { |
| 3507 deopt_id ^= deopt_history.At(i); |
| 3508 if (!deopt_id.IsNull() && (deopt_id.Value() == target_deopt_id)) { |
| 3509 return false; |
| 3510 } |
| 3511 } |
| 3512 } |
| 3513 return true; |
| 3514 } |
| 3515 |
| 3516 |
| 3494 void LICM::Optimize() { | 3517 void LICM::Optimize() { |
| 3495 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = | 3518 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers = |
| 3496 flow_graph()->loop_headers(); | 3519 flow_graph()->loop_headers(); |
| 3497 | 3520 |
| 3498 ZoneGrowableArray<BitVector*>* loop_invariant_loads = | 3521 ZoneGrowableArray<BitVector*>* loop_invariant_loads = |
| 3499 flow_graph()->loop_invariant_loads(); | 3522 flow_graph()->loop_invariant_loads(); |
| 3500 | 3523 |
| 3501 BlockEffects* block_effects = flow_graph()->block_effects(); | 3524 BlockEffects* block_effects = flow_graph()->block_effects(); |
| 3502 | 3525 |
| 3503 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 3526 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3518 block_effects->CanBeMovedTo(current, pre_header)) || | 3541 block_effects->CanBeMovedTo(current, pre_header)) || |
| 3519 IsLoopInvariantLoad(loop_invariant_loads, i, current)) { | 3542 IsLoopInvariantLoad(loop_invariant_loads, i, current)) { |
| 3520 bool inputs_loop_invariant = true; | 3543 bool inputs_loop_invariant = true; |
| 3521 for (int i = 0; i < current->InputCount(); ++i) { | 3544 for (int i = 0; i < current->InputCount(); ++i) { |
| 3522 Definition* input_def = current->InputAt(i)->definition(); | 3545 Definition* input_def = current->InputAt(i)->definition(); |
| 3523 if (!input_def->GetBlock()->Dominates(pre_header)) { | 3546 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 3524 inputs_loop_invariant = false; | 3547 inputs_loop_invariant = false; |
| 3525 break; | 3548 break; |
| 3526 } | 3549 } |
| 3527 } | 3550 } |
| 3528 if (inputs_loop_invariant && | 3551 if (inputs_loop_invariant && MayHoist(current, pre_header)) { |
| 3529 !current->IsAssertAssignable() && | |
| 3530 !current->IsAssertBoolean()) { | |
| 3531 // TODO(fschneider): Enable hoisting of Assert-instructions | |
| 3532 // if it safe to do. | |
| 3533 Hoist(&it, pre_header, current); | 3552 Hoist(&it, pre_header, current); |
| 3534 } else if (current->IsCheckSmi() && | 3553 } else if (current->IsCheckSmi() && |
| 3535 current->InputAt(0)->definition()->IsPhi()) { | 3554 current->InputAt(0)->definition()->IsPhi()) { |
| 3536 TryHoistCheckSmiThroughPhi( | 3555 TryHoistCheckSmiThroughPhi( |
| 3537 &it, header, pre_header, current->AsCheckSmi()); | 3556 &it, header, pre_header, current->AsCheckSmi()); |
| 3538 } | 3557 } |
| 3539 } | 3558 } |
| 3540 } | 3559 } |
| 3541 } | 3560 } |
| 3542 } | 3561 } |
| (...skipping 2968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6511 | 6530 |
| 6512 // Insert materializations at environment uses. | 6531 // Insert materializations at environment uses. |
| 6513 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 6532 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
| 6514 for (intptr_t i = 0; i < exits.length(); i++) { | 6533 for (intptr_t i = 0; i < exits.length(); i++) { |
| 6515 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 6534 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
| 6516 } | 6535 } |
| 6517 } | 6536 } |
| 6518 | 6537 |
| 6519 | 6538 |
| 6520 } // namespace dart | 6539 } // namespace dart |
| OLD | NEW |