| Index: runtime/vm/flow_graph_optimizer.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_optimizer.cc (revision 23072)
|
| +++ runtime/vm/flow_graph_optimizer.cc (working copy)
|
| @@ -3415,8 +3415,6 @@
|
| void LICM::Hoist(ForwardInstructionIterator* it,
|
| BlockEntryInstr* pre_header,
|
| Instruction* current) {
|
| - // TODO(fschneider): Avoid repeated deoptimization when
|
| - // speculatively hoisting checks.
|
| if (FLAG_trace_optimization) {
|
| OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n",
|
| current->DebugName(),
|
| @@ -3472,7 +3470,7 @@
|
| }
|
|
|
| // Host CheckSmi instruction and make this phi smi one.
|
| - Hoist(it, pre_header, current);
|
| + if (MayHoist(current, pre_header)) Hoist(it, pre_header, current);
|
|
|
| // Replace value we are checking with phi's input.
|
| current->value()->BindTo(phi->InputAt(non_smi_input)->definition());
|
| @@ -3491,6 +3489,31 @@
|
| }
|
|
|
|
|
| +bool LICM::MayHoist(Instruction* instr, BlockEntryInstr* pre_header) {
|
| + // TODO(fschneider): Enable hoisting of Assert-instructions
|
| + // if it safe to do.
|
| + if (instr->IsAssertAssignable()) return false;
|
| + if (instr->IsAssertBoolean()) return false;
|
| +
|
| + if (instr->CanDeoptimize()) {
|
| + intptr_t target_deopt_id =
|
| + pre_header->last_instruction()->AsGoto()->GetDeoptId();
|
| + const Function& function = flow_graph_->parsed_function().function();
|
| + const Array& deopt_history = Array::Handle(function.deopt_history());
|
| + if (deopt_history.IsNull()) return true;
|
| +
|
| + Smi& deopt_id = Smi::Handle();
|
| + for (intptr_t i = 0; i < deopt_history.Length(); ++i) {
|
| + deopt_id ^= deopt_history.At(i);
|
| + if (!deopt_id.IsNull() && (deopt_id.Value() == target_deopt_id)) {
|
| + return false;
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| void LICM::Optimize() {
|
| const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
|
| flow_graph()->loop_headers();
|
| @@ -3525,11 +3548,7 @@
|
| break;
|
| }
|
| }
|
| - if (inputs_loop_invariant &&
|
| - !current->IsAssertAssignable() &&
|
| - !current->IsAssertBoolean()) {
|
| - // TODO(fschneider): Enable hoisting of Assert-instructions
|
| - // if it safe to do.
|
| + if (inputs_loop_invariant && MayHoist(current, pre_header)) {
|
| Hoist(&it, pre_header, current);
|
| } else if (current->IsCheckSmi() &&
|
| current->InputAt(0)->definition()->IsPhi()) {
|
|
|