| 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 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1823 ReplaceCall(call, bool_const); | 1823 ReplaceCall(call, bool_const); |
| 1824 return; | 1824 return; |
| 1825 } | 1825 } |
| 1826 } | 1826 } |
| 1827 InstanceOfInstr* instance_of = | 1827 InstanceOfInstr* instance_of = |
| 1828 new InstanceOfInstr(call->token_pos(), | 1828 new InstanceOfInstr(call->token_pos(), |
| 1829 new Value(left), | 1829 new Value(left), |
| 1830 new Value(instantiator), | 1830 new Value(instantiator), |
| 1831 new Value(type_args), | 1831 new Value(type_args), |
| 1832 type, | 1832 type, |
| 1833 negate); | 1833 negate, |
| 1834 call->deopt_id()); |
| 1834 ReplaceCall(call, instance_of); | 1835 ReplaceCall(call, instance_of); |
| 1835 } | 1836 } |
| 1836 | 1837 |
| 1837 | 1838 |
| 1838 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { | 1839 void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
| 1839 ASSERT(Token::IsTypeCastOperator(call->token_kind())); | 1840 ASSERT(Token::IsTypeCastOperator(call->token_kind())); |
| 1840 Definition* left = call->ArgumentAt(0); | 1841 Definition* left = call->ArgumentAt(0); |
| 1841 Definition* instantiator = call->ArgumentAt(1); | 1842 Definition* instantiator = call->ArgumentAt(1); |
| 1842 Definition* type_args = call->ArgumentAt(2); | 1843 Definition* type_args = call->ArgumentAt(2); |
| 1843 const AbstractType& type = | 1844 const AbstractType& type = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1863 } | 1864 } |
| 1864 const String& dst_name = String::ZoneHandle( | 1865 const String& dst_name = String::ZoneHandle( |
| 1865 Symbols::New(Exceptions::kCastErrorDstName)); | 1866 Symbols::New(Exceptions::kCastErrorDstName)); |
| 1866 AssertAssignableInstr* assert_as = | 1867 AssertAssignableInstr* assert_as = |
| 1867 new AssertAssignableInstr(call->token_pos(), | 1868 new AssertAssignableInstr(call->token_pos(), |
| 1868 new Value(left), | 1869 new Value(left), |
| 1869 new Value(instantiator), | 1870 new Value(instantiator), |
| 1870 new Value(type_args), | 1871 new Value(type_args), |
| 1871 type, | 1872 type, |
| 1872 dst_name); | 1873 dst_name); |
| 1874 // Newly inserted instructions that can deoptimize or throw an exception |
| 1875 // must have a deoptimization id that is valid for lookup in the unoptimized |
| 1876 // code. |
| 1877 assert_as->deopt_id_ = call->deopt_id(); |
| 1873 ReplaceCall(call, assert_as); | 1878 ReplaceCall(call, assert_as); |
| 1874 } | 1879 } |
| 1875 | 1880 |
| 1876 | 1881 |
| 1877 // Tries to optimize instance call by replacing it with a faster instruction | 1882 // Tries to optimize instance call by replacing it with a faster instruction |
| 1878 // (e.g, binary op, field load, ..). | 1883 // (e.g, binary op, field load, ..). |
| 1879 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 1884 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 1880 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { | 1885 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { |
| 1881 return; | 1886 return; |
| 1882 } | 1887 } |
| (...skipping 2475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4358 if (!reachable_->Contains(block->preorder_number())) { | 4363 if (!reachable_->Contains(block->preorder_number())) { |
| 4359 if (FLAG_trace_constant_propagation) { | 4364 if (FLAG_trace_constant_propagation) { |
| 4360 OS::Print("Unreachable B%"Pd"\n", block->block_id()); | 4365 OS::Print("Unreachable B%"Pd"\n", block->block_id()); |
| 4361 } | 4366 } |
| 4362 // Remove all uses in unreachable blocks. | 4367 // Remove all uses in unreachable blocks. |
| 4363 if (join != NULL) { | 4368 if (join != NULL) { |
| 4364 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 4369 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
| 4365 it.Current()->UnuseAllInputs(); | 4370 it.Current()->UnuseAllInputs(); |
| 4366 } | 4371 } |
| 4367 } | 4372 } |
| 4373 block->UnuseAllInputs(); |
| 4368 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 4374 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 4369 it.Current()->UnuseAllInputs(); | 4375 it.Current()->UnuseAllInputs(); |
| 4370 } | 4376 } |
| 4371 continue; | 4377 continue; |
| 4372 } | 4378 } |
| 4373 | 4379 |
| 4374 if (join != NULL) { | 4380 if (join != NULL) { |
| 4375 // Remove phi inputs corresponding to unreachable predecessor blocks. | 4381 // Remove phi inputs corresponding to unreachable predecessor blocks. |
| 4376 // Predecessors will be recomputed (in block id order) after removing | 4382 // Predecessors will be recomputed (in block id order) after removing |
| 4377 // unreachable code so we merely have to keep the phi inputs in order. | 4383 // unreachable code so we merely have to keep the phi inputs in order. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4450 TargetEntryInstr* if_true = branch->true_successor(); | 4456 TargetEntryInstr* if_true = branch->true_successor(); |
| 4451 TargetEntryInstr* if_false = branch->false_successor(); | 4457 TargetEntryInstr* if_false = branch->false_successor(); |
| 4452 JoinEntryInstr* join = NULL; | 4458 JoinEntryInstr* join = NULL; |
| 4453 Instruction* next = NULL; | 4459 Instruction* next = NULL; |
| 4454 | 4460 |
| 4455 if (!reachable_->Contains(if_true->preorder_number())) { | 4461 if (!reachable_->Contains(if_true->preorder_number())) { |
| 4456 ASSERT(reachable_->Contains(if_false->preorder_number())); | 4462 ASSERT(reachable_->Contains(if_false->preorder_number())); |
| 4457 ASSERT(if_false->parallel_move() == NULL); | 4463 ASSERT(if_false->parallel_move() == NULL); |
| 4458 ASSERT(if_false->loop_info() == NULL); | 4464 ASSERT(if_false->loop_info() == NULL); |
| 4459 join = new JoinEntryInstr(if_false->block_id(), if_false->try_index()); | 4465 join = new JoinEntryInstr(if_false->block_id(), if_false->try_index()); |
| 4466 join->InheritDeoptTarget(if_false); |
| 4467 if_false->UnuseAllInputs(); |
| 4460 next = if_false->next(); | 4468 next = if_false->next(); |
| 4461 } else if (!reachable_->Contains(if_false->preorder_number())) { | 4469 } else if (!reachable_->Contains(if_false->preorder_number())) { |
| 4462 ASSERT(if_true->parallel_move() == NULL); | 4470 ASSERT(if_true->parallel_move() == NULL); |
| 4463 ASSERT(if_true->loop_info() == NULL); | 4471 ASSERT(if_true->loop_info() == NULL); |
| 4464 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); | 4472 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); |
| 4473 join->InheritDeoptTarget(if_true); |
| 4474 if_true->UnuseAllInputs(); |
| 4465 next = if_true->next(); | 4475 next = if_true->next(); |
| 4466 } | 4476 } |
| 4467 | 4477 |
| 4468 if (join != NULL) { | 4478 if (join != NULL) { |
| 4469 // Replace the branch with a jump to the reachable successor. | 4479 // Replace the branch with a jump to the reachable successor. |
| 4470 // Drop the comparison, which does not have side effects as long | 4480 // Drop the comparison, which does not have side effects as long |
| 4471 // as it is a strict compare (the only one we can determine is | 4481 // as it is a strict compare (the only one we can determine is |
| 4472 // constant with the current analysis). | 4482 // constant with the current analysis). |
| 4473 GotoInstr* jump = new GotoInstr(join); | 4483 GotoInstr* jump = new GotoInstr(join); |
| 4484 jump->InheritDeoptTarget(branch); |
| 4485 |
| 4474 Instruction* previous = branch->previous(); | 4486 Instruction* previous = branch->previous(); |
| 4475 branch->set_previous(NULL); | 4487 branch->set_previous(NULL); |
| 4476 previous->LinkTo(jump); | 4488 previous->LinkTo(jump); |
| 4489 |
| 4477 // Replace the false target entry with the new join entry. We will | 4490 // Replace the false target entry with the new join entry. We will |
| 4478 // recompute the dominators after this pass. | 4491 // recompute the dominators after this pass. |
| 4479 join->LinkTo(next); | 4492 join->LinkTo(next); |
| 4480 branch->UnuseAllInputs(); | 4493 branch->UnuseAllInputs(); |
| 4481 } | 4494 } |
| 4482 } | 4495 } |
| 4483 } | 4496 } |
| 4484 | 4497 |
| 4485 graph_->DiscoverBlocks(); | 4498 graph_->DiscoverBlocks(); |
| 4486 GrowableArray<BitVector*> dominance_frontier; | 4499 GrowableArray<BitVector*> dominance_frontier; |
| 4487 graph_->ComputeDominators(&dominance_frontier); | 4500 graph_->ComputeDominators(&dominance_frontier); |
| 4488 | 4501 |
| 4489 if (FLAG_trace_constant_propagation) { | 4502 if (FLAG_trace_constant_propagation) { |
| 4490 OS::Print("\n==== After constant propagation ====\n"); | 4503 OS::Print("\n==== After constant propagation ====\n"); |
| 4491 FlowGraphPrinter printer(*graph_); | 4504 FlowGraphPrinter printer(*graph_); |
| 4492 printer.PrintBlocks(); | 4505 printer.PrintBlocks(); |
| 4493 } | 4506 } |
| 4494 } | 4507 } |
| 4495 | 4508 |
| 4496 | 4509 |
| 4510 // Returns true if the given phi has a single input use and |
| 4511 // is used in the environments either at the corresponding block entry or |
| 4512 // at the same instruction where input use is. |
| 4513 static bool PhiHasSingleUse(PhiInstr* phi, Value* use) { |
| 4514 if ((use->next_use() != NULL) || (phi->input_use_list() != use)) { |
| 4515 return false; |
| 4516 } |
| 4517 |
| 4518 BlockEntryInstr* block = phi->block(); |
| 4519 for (Value* env_use = phi->env_use_list(); |
| 4520 env_use != NULL; |
| 4521 env_use = env_use->next_use()) { |
| 4522 if ((env_use->instruction() != block) && |
| 4523 (env_use->instruction() != use->instruction())) { |
| 4524 return false; |
| 4525 } |
| 4526 } |
| 4527 |
| 4528 return true; |
| 4529 } |
| 4530 |
| 4531 |
| 4497 bool BranchSimplifier::Match(JoinEntryInstr* block) { | 4532 bool BranchSimplifier::Match(JoinEntryInstr* block) { |
| 4498 // Match the pattern of a branch on a comparison whose left operand is a | 4533 // Match the pattern of a branch on a comparison whose left operand is a |
| 4499 // phi from the same block, and whose right operand is a constant. | 4534 // phi from the same block, and whose right operand is a constant. |
| 4500 // | 4535 // |
| 4501 // Branch(Comparison(kind, Phi, Constant)) | 4536 // Branch(Comparison(kind, Phi, Constant)) |
| 4502 // | 4537 // |
| 4503 // These are the branches produced by inlining in a test context. Also, | 4538 // These are the branches produced by inlining in a test context. Also, |
| 4504 // the phi and the constant have no other uses so they can simply be | 4539 // the phi and the constant have no other uses so they can simply be |
| 4505 // eliminated. The block has no other phis and no instructions | 4540 // eliminated. The block has no other phis and no instructions |
| 4506 // intervening between the phi, constant, and branch so the block can | 4541 // intervening between the phi, constant, and branch so the block can |
| 4507 // simply be eliminated. | 4542 // simply be eliminated. |
| 4508 BranchInstr* branch = block->last_instruction()->AsBranch(); | 4543 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 4509 ASSERT(branch != NULL); | 4544 ASSERT(branch != NULL); |
| 4510 ComparisonInstr* comparison = branch->comparison(); | 4545 ComparisonInstr* comparison = branch->comparison(); |
| 4511 Value* left = comparison->left(); | 4546 Value* left = comparison->left(); |
| 4512 PhiInstr* phi = left->definition()->AsPhi(); | 4547 PhiInstr* phi = left->definition()->AsPhi(); |
| 4513 Value* right = comparison->right(); | 4548 Value* right = comparison->right(); |
| 4514 ConstantInstr* constant = right->definition()->AsConstant(); | 4549 ConstantInstr* constant = right->definition()->AsConstant(); |
| 4515 return (phi != NULL) && | 4550 return (phi != NULL) && |
| 4516 (constant != NULL) && | 4551 (constant != NULL) && |
| 4517 (phi->GetBlock() == block) && | 4552 (phi->GetBlock() == block) && |
| 4518 phi->HasOnlyUse(left) && | 4553 PhiHasSingleUse(phi, left) && |
| 4519 constant->HasOnlyUse(right) && | 4554 constant->HasOnlyUse(right) && |
| 4520 (block->next() == constant) && | 4555 (block->next() == constant) && |
| 4521 (constant->next() == branch) && | 4556 (constant->next() == branch) && |
| 4522 (block->phis()->length() == 1); | 4557 (block->phis()->length() == 1); |
| 4523 } | 4558 } |
| 4524 | 4559 |
| 4525 | 4560 |
| 4526 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) { | 4561 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) { |
| 4527 // Convert a target block into a join block. Branches will be duplicated | 4562 // Convert a target block into a join block. Branches will be duplicated |
| 4528 // so the former true and false targets become joins of the control flows | 4563 // so the former true and false targets become joins of the control flows |
| 4529 // from all the duplicated branches. | 4564 // from all the duplicated branches. |
| 4530 JoinEntryInstr* join = | 4565 JoinEntryInstr* join = |
| 4531 new JoinEntryInstr(target->block_id(), target->try_index()); | 4566 new JoinEntryInstr(target->block_id(), target->try_index()); |
| 4567 join->InheritDeoptTarget(target); |
| 4532 join->LinkTo(target->next()); | 4568 join->LinkTo(target->next()); |
| 4533 join->set_last_instruction(target->last_instruction()); | 4569 join->set_last_instruction(target->last_instruction()); |
| 4570 target->UnuseAllInputs(); |
| 4534 return join; | 4571 return join; |
| 4535 } | 4572 } |
| 4536 | 4573 |
| 4537 | 4574 |
| 4538 ConstantInstr* BranchSimplifier::CloneConstant(FlowGraph* flow_graph, | 4575 ConstantInstr* BranchSimplifier::CloneConstant(FlowGraph* flow_graph, |
| 4539 ConstantInstr* constant) { | 4576 ConstantInstr* constant) { |
| 4540 ConstantInstr* new_constant = new ConstantInstr(constant->value()); | 4577 ConstantInstr* new_constant = new ConstantInstr(constant->value()); |
| 4541 new_constant->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); | 4578 new_constant->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index()); |
| 4542 return new_constant; | 4579 return new_constant; |
| 4543 } | 4580 } |
| 4544 | 4581 |
| 4545 | 4582 |
| 4546 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, | 4583 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, |
| 4547 Value* left, | 4584 Value* left, |
| 4548 Value* right) { | 4585 Value* right) { |
| 4549 ComparisonInstr* comparison = branch->comparison(); | 4586 ComparisonInstr* comparison = branch->comparison(); |
| 4550 ComparisonInstr* new_comparison = NULL; | 4587 ComparisonInstr* new_comparison = NULL; |
| 4551 if (comparison->IsStrictCompare()) { | 4588 if (comparison->IsStrictCompare()) { |
| 4552 new_comparison = new StrictCompareInstr(comparison->kind(), left, right); | 4589 new_comparison = new StrictCompareInstr(comparison->kind(), left, right); |
| 4553 } else if (comparison->IsEqualityCompare()) { | 4590 } else if (comparison->IsEqualityCompare()) { |
| 4554 new_comparison = | 4591 EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare(); |
| 4555 new EqualityCompareInstr(comparison->AsEqualityCompare()->token_pos(), | 4592 EqualityCompareInstr* new_equality_compare = |
| 4593 new EqualityCompareInstr(equality_compare->token_pos(), |
| 4556 comparison->kind(), | 4594 comparison->kind(), |
| 4557 left, | 4595 left, |
| 4558 right); | 4596 right); |
| 4597 new_equality_compare->set_ic_data(equality_compare->ic_data()); |
| 4598 new_comparison = new_equality_compare; |
| 4559 } else { | 4599 } else { |
| 4560 ASSERT(comparison->IsRelationalOp()); | 4600 ASSERT(comparison->IsRelationalOp()); |
| 4561 new_comparison = | 4601 RelationalOpInstr* relational_op = comparison->AsRelationalOp(); |
| 4562 new RelationalOpInstr(comparison->AsRelationalOp()->token_pos(), | 4602 RelationalOpInstr* new_relational_op = |
| 4603 new RelationalOpInstr(relational_op->token_pos(), |
| 4563 comparison->kind(), | 4604 comparison->kind(), |
| 4564 left, | 4605 left, |
| 4565 right); | 4606 right); |
| 4607 new_relational_op->set_ic_data(relational_op->ic_data()); |
| 4608 new_comparison = new_relational_op; |
| 4566 } | 4609 } |
| 4567 return new BranchInstr(new_comparison, branch->is_checked()); | 4610 return new BranchInstr(new_comparison, branch->is_checked()); |
| 4568 } | 4611 } |
| 4569 | 4612 |
| 4570 | 4613 |
| 4571 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { | 4614 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
| 4572 // Optimize some branches that test the value of a phi. When it is safe | 4615 // Optimize some branches that test the value of a phi. When it is safe |
| 4573 // to do so, push the branch to each of the predecessor blocks. This is | 4616 // to do so, push the branch to each of the predecessor blocks. This is |
| 4574 // an optimization when (a) it can avoid materializing a boolean object at | 4617 // an optimization when (a) it can avoid materializing a boolean object at |
| 4575 // the phi only to test its value, and (b) it can expose opportunities for | 4618 // the phi only to test its value, and (b) it can expose opportunities for |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4624 | 4667 |
| 4625 // Insert a copy of the constant in all the predecessors. | 4668 // Insert a copy of the constant in all the predecessors. |
| 4626 ConstantInstr* new_constant = CloneConstant(flow_graph, constant); | 4669 ConstantInstr* new_constant = CloneConstant(flow_graph, constant); |
| 4627 new_constant->InsertBefore(old_goto); | 4670 new_constant->InsertBefore(old_goto); |
| 4628 | 4671 |
| 4629 // Replace the goto in each predecessor with a rewritten branch, | 4672 // Replace the goto in each predecessor with a rewritten branch, |
| 4630 // rewritten to use the corresponding phi input instead of the phi. | 4673 // rewritten to use the corresponding phi input instead of the phi. |
| 4631 Value* new_left = phi->InputAt(i)->Copy(); | 4674 Value* new_left = phi->InputAt(i)->Copy(); |
| 4632 Value* new_right = new Value(new_constant); | 4675 Value* new_right = new Value(new_constant); |
| 4633 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); | 4676 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); |
| 4677 new_branch->InheritDeoptTarget(old_goto); |
| 4634 new_branch->InsertBefore(old_goto); | 4678 new_branch->InsertBefore(old_goto); |
| 4635 new_branch->set_next(NULL); // Detaching the goto from the graph. | 4679 new_branch->set_next(NULL); // Detaching the goto from the graph. |
| 4636 old_goto->UnuseAllInputs(); | 4680 old_goto->UnuseAllInputs(); |
| 4637 | 4681 |
| 4638 // Update the predecessor block. We may have created another | 4682 // Update the predecessor block. We may have created another |
| 4639 // instance of the pattern so add it to the worklist if necessary. | 4683 // instance of the pattern so add it to the worklist if necessary. |
| 4640 BlockEntryInstr* branch_block = new_branch->GetBlock(); | 4684 BlockEntryInstr* branch_block = new_branch->GetBlock(); |
| 4641 branch_block->set_last_instruction(new_branch); | 4685 branch_block->set_last_instruction(new_branch); |
| 4642 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); | 4686 if (branch_block->IsJoinEntry()) worklist.Add(branch_block); |
| 4643 | 4687 |
| 4644 // Connect the branch to the true and false joins, via empty target | 4688 // Connect the branch to the true and false joins, via empty target |
| 4645 // blocks. | 4689 // blocks. |
| 4646 TargetEntryInstr* true_target = | 4690 TargetEntryInstr* true_target = |
| 4647 new TargetEntryInstr(flow_graph->max_block_id() + 1, | 4691 new TargetEntryInstr(flow_graph->max_block_id() + 1, |
| 4648 block->try_index()); | 4692 block->try_index()); |
| 4693 true_target->InheritDeoptTarget(join_true); |
| 4649 TargetEntryInstr* false_target = | 4694 TargetEntryInstr* false_target = |
| 4650 new TargetEntryInstr(flow_graph->max_block_id() + 2, | 4695 new TargetEntryInstr(flow_graph->max_block_id() + 2, |
| 4651 block->try_index()); | 4696 block->try_index()); |
| 4697 false_target->InheritDeoptTarget(join_false); |
| 4652 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); | 4698 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); |
| 4653 *new_branch->true_successor_address() = true_target; | 4699 *new_branch->true_successor_address() = true_target; |
| 4654 *new_branch->false_successor_address() = false_target; | 4700 *new_branch->false_successor_address() = false_target; |
| 4655 GotoInstr* goto_true = new GotoInstr(join_true); | 4701 GotoInstr* goto_true = new GotoInstr(join_true); |
| 4702 goto_true->InheritDeoptTarget(join_true); |
| 4656 true_target->LinkTo(goto_true); | 4703 true_target->LinkTo(goto_true); |
| 4657 true_target->set_last_instruction(goto_true); | 4704 true_target->set_last_instruction(goto_true); |
| 4658 GotoInstr* goto_false = new GotoInstr(join_false); | 4705 GotoInstr* goto_false = new GotoInstr(join_false); |
| 4706 goto_false->InheritDeoptTarget(join_false); |
| 4659 false_target->LinkTo(goto_false); | 4707 false_target->LinkTo(goto_false); |
| 4660 false_target->set_last_instruction(goto_false); | 4708 false_target->set_last_instruction(goto_false); |
| 4661 } | 4709 } |
| 4662 // When all predecessors have been rewritten, the original block is | 4710 // When all predecessors have been rewritten, the original block is |
| 4663 // unreachable from the graph. | 4711 // unreachable from the graph. |
| 4664 phi->UnuseAllInputs(); | 4712 phi->UnuseAllInputs(); |
| 4665 branch->UnuseAllInputs(); | 4713 branch->UnuseAllInputs(); |
| 4714 block->UnuseAllInputs(); |
| 4666 } | 4715 } |
| 4667 } | 4716 } |
| 4668 | 4717 |
| 4669 if (changed) { | 4718 if (changed) { |
| 4670 // We may have changed the block order and the dominator tree. | 4719 // We may have changed the block order and the dominator tree. |
| 4671 flow_graph->DiscoverBlocks(); | 4720 flow_graph->DiscoverBlocks(); |
| 4672 GrowableArray<BitVector*> dominance_frontier; | 4721 GrowableArray<BitVector*> dominance_frontier; |
| 4673 flow_graph->ComputeDominators(&dominance_frontier); | 4722 flow_graph->ComputeDominators(&dominance_frontier); |
| 4674 } | 4723 } |
| 4675 } | 4724 } |
| 4676 | 4725 |
| 4677 | 4726 |
| 4678 } // namespace dart | 4727 } // namespace dart |
| OLD | NEW |