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 for (intptr_t i = 0; i < deopt_history.Length(); ++i) { | |
3506 const Object& obj = Object::Handle(deopt_history.At(i)); | |
3507 if (obj.IsNull()) continue; | |
Kevin Millikin (Google)
2013/05/24 11:39:21
If you just delete this line, I think the result i
Florian Schneider
2013/05/24 11:53:02
Done.
| |
3508 if (obj.IsSmi() && Smi::Cast(obj).Value() == target_deopt_id) { | |
Kevin Millikin (Google)
2013/05/24 11:39:21
Can it be non-smi (other than null)? The Smi::Cas
Florian Schneider
2013/05/24 11:53:02
Done.
| |
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 |