Chromium Code Reviews| 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 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 | 443 |
| 444 if (unboxed != current) { | 444 if (unboxed != current) { |
| 445 phi->set_representation(unboxed); | 445 phi->set_representation(unboxed); |
| 446 return true; | 446 return true; |
| 447 } | 447 } |
| 448 | 448 |
| 449 return false; | 449 return false; |
| 450 } | 450 } |
| 451 | 451 |
| 452 | 452 |
| 453 void FlowGraphOptimizer::UnboxPhis() { | |
| 454 GrowableArray<PhiInstr*> worklist(5); | |
| 455 | |
| 456 // Convervatively unbox all phis that were proven to be of Double, | |
| 457 // Float32x4, or Uint32x4 type. | |
| 458 for (intptr_t i = 0; i < block_order_.length(); ++i) { | |
| 459 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); | |
| 460 if (join_entry != NULL) { | |
| 461 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { | |
| 462 PhiInstr* phi = it.Current(); | |
| 463 if (UnboxPhi(phi)) { | |
| 464 worklist.Add(phi); | |
| 465 } | |
| 466 } | |
| 467 } | |
| 468 } | |
| 469 | |
| 470 while (!worklist.is_empty()) { | |
| 471 PhiInstr* phi = worklist.RemoveLast(); | |
| 472 InsertConversionsFor(phi); | |
| 473 | |
| 474 for (intptr_t i = 0; i < phi->InputCount(); i++) { | |
| 475 ConvertUse(phi->InputAt(i), | |
| 476 phi->InputAt(i)->definition()->representation()); | |
| 477 } | |
| 478 } | |
| 479 } | |
| 480 | |
| 481 | |
| 482 void FlowGraphOptimizer::SelectRepresentations() { | 453 void FlowGraphOptimizer::SelectRepresentations() { |
| 483 // Convervatively unbox all phis that were proven to be of Double, | 454 // Convervatively unbox all phis that were proven to be of Double, |
| 484 // Float32x4, or Uint32x4 type. | 455 // Float32x4, or Uint32x4 type. |
| 485 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 456 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 486 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); | 457 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
| 487 if (join_entry != NULL) { | 458 if (join_entry != NULL) { |
| 488 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { | 459 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
| 489 PhiInstr* phi = it.Current(); | 460 PhiInstr* phi = it.Current(); |
| 490 UnboxPhi(phi); | 461 UnboxPhi(phi); |
| 491 } | 462 } |
| (...skipping 4323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4815 GrowableArray<BlockEntryInstr*> ignored; | 4786 GrowableArray<BlockEntryInstr*> ignored; |
| 4816 ConstantPropagator cp(graph, ignored); | 4787 ConstantPropagator cp(graph, ignored); |
| 4817 cp.Analyze(); | 4788 cp.Analyze(); |
| 4818 cp.Transform(); | 4789 cp.Transform(); |
| 4819 } | 4790 } |
| 4820 | 4791 |
| 4821 | 4792 |
| 4822 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { | 4793 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { |
| 4823 GrowableArray<BlockEntryInstr*> ignored; | 4794 GrowableArray<BlockEntryInstr*> ignored; |
| 4824 ConstantPropagator cp(graph, ignored); | 4795 ConstantPropagator cp(graph, ignored); |
| 4796 cp.Analyze(); | |
| 4825 cp.VisitBranches(); | 4797 cp.VisitBranches(); |
| 4826 cp.Transform(); | 4798 cp.Transform(); |
| 4827 } | 4799 } |
| 4828 | 4800 |
| 4829 | 4801 |
| 4830 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { | 4802 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { |
| 4831 if (!reachable_->Contains(block->preorder_number())) { | 4803 if (!reachable_->Contains(block->preorder_number())) { |
| 4832 reachable_->Add(block->preorder_number()); | 4804 reachable_->Add(block->preorder_number()); |
| 4833 block_worklist_.Add(block); | 4805 block_worklist_.Add(block); |
| 4834 } | 4806 } |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5153 SetValue(instr, Smi::Handle( | 5125 SetValue(instr, Smi::Handle( |
| 5154 Smi::New(result ? instr->if_true() : instr->if_false()))); | 5126 Smi::New(result ? instr->if_true() : instr->if_false()))); |
| 5155 } | 5127 } |
| 5156 } | 5128 } |
| 5157 | 5129 |
| 5158 | 5130 |
| 5159 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 5131 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
| 5160 const Object& left = instr->left()->definition()->constant_value(); | 5132 const Object& left = instr->left()->definition()->constant_value(); |
| 5161 const Object& right = instr->right()->definition()->constant_value(); | 5133 const Object& right = instr->right()->definition()->constant_value(); |
| 5162 | 5134 |
| 5135 if (instr->left()->definition() == instr->right()->definition()) { | |
|
srdjan
2013/06/12 16:37:51
Yes, thanks to the spec that now says identical(NA
| |
| 5136 // Fold x === x, and x !== x to true/false. | |
| 5137 SetValue(instr, | |
| 5138 (instr->kind() == Token::kEQ_STRICT) | |
| 5139 ? Bool::True() | |
| 5140 : Bool::False()); | |
| 5141 return; | |
| 5142 } | |
| 5143 | |
| 5163 if (IsNonConstant(left) || IsNonConstant(right)) { | 5144 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 5164 // TODO(vegorov): incorporate nullability information into the lattice. | 5145 // TODO(vegorov): incorporate nullability information into the lattice. |
| 5165 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || | 5146 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || |
| 5166 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { | 5147 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { |
| 5167 bool result = left.IsNull() ? instr->right()->Type()->IsNull() | 5148 bool result = left.IsNull() ? instr->right()->Type()->IsNull() |
| 5168 : instr->left()->Type()->IsNull(); | 5149 : instr->left()->Type()->IsNull(); |
| 5169 if (instr->kind() == Token::kNE_STRICT) result = !result; | 5150 if (instr->kind() == Token::kNE_STRICT) result = !result; |
| 5170 SetValue(instr, result ? Bool::True() : Bool::False()); | 5151 SetValue(instr, result ? Bool::True() : Bool::False()); |
| 5171 } else { | 5152 } else { |
| 5172 SetValue(instr, non_constant_); | 5153 SetValue(instr, non_constant_); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 5193 default: | 5174 default: |
| 5194 UNREACHABLE(); | 5175 UNREACHABLE(); |
| 5195 return false; | 5176 return false; |
| 5196 } | 5177 } |
| 5197 } | 5178 } |
| 5198 | 5179 |
| 5199 | 5180 |
| 5200 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { | 5181 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 5201 const Object& left = instr->left()->definition()->constant_value(); | 5182 const Object& left = instr->left()->definition()->constant_value(); |
| 5202 const Object& right = instr->right()->definition()->constant_value(); | 5183 const Object& right = instr->right()->definition()->constant_value(); |
| 5184 | |
| 5185 if (instr->left()->definition() == instr->right()->definition()) { | |
| 5186 // Fold x == x, and x != x to true/false for numbers and checked strict | |
| 5187 // comparisons. | |
| 5188 if (instr->is_checked_strict_equal() || | |
| 5189 RawObject::IsNumberClassId(instr->receiver_class_id())) { | |
|
srdjan
2013/06/12 16:37:51
This is wrong for identical(NAN, NAN), which retur
Florian Schneider
2013/06/13 08:15:43
Done.
Lasse Reichstein Nielsen
2013/06/13 08:21:25
Is this correct? I.e. if
var NAN = 0.0/0.0;
pr
| |
| 5190 return SetValue(instr, | |
| 5191 (instr->kind() == Token::kEQ) | |
| 5192 ? Bool::True() | |
| 5193 : Bool::False()); | |
| 5194 } | |
| 5195 } | |
| 5196 | |
| 5203 if (IsNonConstant(left) || IsNonConstant(right)) { | 5197 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 5204 SetValue(instr, non_constant_); | 5198 SetValue(instr, non_constant_); |
| 5205 } else if (IsConstant(left) && IsConstant(right)) { | 5199 } else if (IsConstant(left) && IsConstant(right)) { |
| 5206 if (left.IsInteger() && right.IsInteger()) { | 5200 if (left.IsInteger() && right.IsInteger()) { |
| 5207 const bool result = CompareIntegers(instr->kind(), | 5201 const bool result = CompareIntegers(instr->kind(), |
| 5208 Integer::Cast(left), | 5202 Integer::Cast(left), |
| 5209 Integer::Cast(right)); | 5203 Integer::Cast(right)); |
| 5210 SetValue(instr, result ? Bool::True() : Bool::False()); | 5204 SetValue(instr, result ? Bool::True() : Bool::False()); |
| 5211 } else { | 5205 } else { |
| 5212 SetValue(instr, non_constant_); | 5206 SetValue(instr, non_constant_); |
| (...skipping 1379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6592 | 6586 |
| 6593 // Insert materializations at environment uses. | 6587 // Insert materializations at environment uses. |
| 6594 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 6588 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
| 6595 for (intptr_t i = 0; i < exits.length(); i++) { | 6589 for (intptr_t i = 0; i < exits.length(); i++) { |
| 6596 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 6590 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
| 6597 } | 6591 } |
| 6598 } | 6592 } |
| 6599 | 6593 |
| 6600 | 6594 |
| 6601 } // namespace dart | 6595 } // namespace dart |
| OLD | NEW |