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/constant_propagator.h" | 5 #include "vm/constant_propagator.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
9 #include "vm/flow_graph_compiler.h" | 9 #include "vm/flow_graph_compiler.h" |
10 #include "vm/flow_graph_range_analysis.h" | 10 #include "vm/flow_graph_range_analysis.h" |
11 #include "vm/il_printer.h" | 11 #include "vm/il_printer.h" |
12 #include "vm/intermediate_language.h" | 12 #include "vm/intermediate_language.h" |
13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); | 18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); |
19 DEFINE_FLAG(bool, trace_constant_propagation, false, | 19 DEFINE_FLAG(bool, |
20 "Print constant propagation and useless code elimination."); | 20 trace_constant_propagation, |
| 21 false, |
| 22 "Print constant propagation and useless code elimination."); |
21 | 23 |
22 // Quick access to the current zone and isolate. | 24 // Quick access to the current zone and isolate. |
23 #define I (isolate()) | 25 #define I (isolate()) |
24 #define Z (graph_->zone()) | 26 #define Z (graph_->zone()) |
25 | 27 |
26 | 28 |
27 ConstantPropagator::ConstantPropagator( | 29 ConstantPropagator::ConstantPropagator( |
28 FlowGraph* graph, | 30 FlowGraph* graph, |
29 const GrowableArray<BlockEntryInstr*>& ignored) | 31 const GrowableArray<BlockEntryInstr*>& ignored) |
30 : FlowGraphVisitor(ignored), | 32 : FlowGraphVisitor(ignored), |
31 graph_(graph), | 33 graph_(graph), |
32 unknown_(Object::unknown_constant()), | 34 unknown_(Object::unknown_constant()), |
33 non_constant_(Object::non_constant()), | 35 non_constant_(Object::non_constant()), |
34 reachable_(new(Z) BitVector( | 36 reachable_(new (Z) BitVector(Z, graph->preorder().length())), |
35 Z, graph->preorder().length())), | 37 marked_phis_(new (Z) BitVector(Z, graph->max_virtual_register_number())), |
36 marked_phis_(new(Z) BitVector( | |
37 Z, graph->max_virtual_register_number())), | |
38 block_worklist_(), | 38 block_worklist_(), |
39 definition_worklist_(graph, 10) {} | 39 definition_worklist_(graph, 10) {} |
40 | 40 |
41 | 41 |
42 void ConstantPropagator::Optimize(FlowGraph* graph) { | 42 void ConstantPropagator::Optimize(FlowGraph* graph) { |
43 GrowableArray<BlockEntryInstr*> ignored; | 43 GrowableArray<BlockEntryInstr*> ignored; |
44 ConstantPropagator cp(graph, ignored); | 44 ConstantPropagator cp(graph, ignored); |
45 cp.Analyze(); | 45 cp.Analyze(); |
46 cp.Transform(); | 46 cp.Transform(); |
47 } | 47 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 228 } |
229 } | 229 } |
230 } | 230 } |
231 } | 231 } |
232 | 232 |
233 | 233 |
234 // -------------------------------------------------------------------------- | 234 // -------------------------------------------------------------------------- |
235 // Analysis of non-definition instructions. They do not have values so they | 235 // Analysis of non-definition instructions. They do not have values so they |
236 // cannot have constant values. | 236 // cannot have constant values. |
237 void ConstantPropagator::VisitCheckStackOverflow( | 237 void ConstantPropagator::VisitCheckStackOverflow( |
238 CheckStackOverflowInstr* instr) { } | 238 CheckStackOverflowInstr* instr) {} |
239 | 239 |
240 | 240 |
241 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } | 241 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {} |
242 | 242 |
243 | 243 |
244 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { } | 244 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {} |
245 | 245 |
246 | 246 |
247 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) { } | 247 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {} |
248 | 248 |
249 | 249 |
250 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) { } | 250 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {} |
251 | 251 |
252 | 252 |
253 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { } | 253 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {} |
254 | 254 |
255 | 255 |
256 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { | 256 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 void ConstantPropagator::VisitCheckEitherNonSmi( | 260 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { |
261 CheckEitherNonSmiInstr* instr) { } | 261 } |
262 | 262 |
263 | 263 |
264 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } | 264 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {} |
265 | 265 |
266 | 266 |
267 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { | 267 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { |
268 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. | 268 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. |
269 } | 269 } |
270 | 270 |
271 void ConstantPropagator::VisitGrowRegExpStack(GrowRegExpStackInstr* instr) { } | 271 void ConstantPropagator::VisitGrowRegExpStack(GrowRegExpStackInstr* instr) {} |
272 | 272 |
273 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { | 273 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { |
274 if (defn->IsPhi()) { | 274 if (defn->IsPhi()) { |
275 JoinEntryInstr* block = defn->AsPhi()->block(); | 275 JoinEntryInstr* block = defn->AsPhi()->block(); |
276 | 276 |
277 Definition* input = NULL; | 277 Definition* input = NULL; |
278 for (intptr_t i = 0; i < defn->InputCount(); ++i) { | 278 for (intptr_t i = 0; i < defn->InputCount(); ++i) { |
279 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { | 279 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { |
280 if (input == NULL) { | 280 if (input == NULL) { |
281 input = defn->InputAt(i)->definition(); | 281 input = defn->InputAt(i)->definition(); |
(...skipping 20 matching lines...) Expand all Loading... |
302 // Analysis of definitions. Compute the constant value. If it has changed | 302 // Analysis of definitions. Compute the constant value. If it has changed |
303 // and the definition has input uses, add the definition to the definition | 303 // and the definition has input uses, add the definition to the definition |
304 // worklist so that the used can be processed. | 304 // worklist so that the used can be processed. |
305 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 305 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
306 // Compute the join over all the reachable predecessor values. | 306 // Compute the join over all the reachable predecessor values. |
307 JoinEntryInstr* block = instr->block(); | 307 JoinEntryInstr* block = instr->block(); |
308 Object& value = Object::ZoneHandle(Z, Unknown()); | 308 Object& value = Object::ZoneHandle(Z, Unknown()); |
309 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 309 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
310 if (reachable_->Contains( | 310 if (reachable_->Contains( |
311 block->PredecessorAt(pred_idx)->preorder_number())) { | 311 block->PredecessorAt(pred_idx)->preorder_number())) { |
312 Join(&value, | 312 Join(&value, instr->InputAt(pred_idx)->definition()->constant_value()); |
313 instr->InputAt(pred_idx)->definition()->constant_value()); | |
314 } | 313 } |
315 } | 314 } |
316 if (!SetValue(instr, value) && | 315 if (!SetValue(instr, value) && |
317 marked_phis_->Contains(instr->ssa_temp_index())) { | 316 marked_phis_->Contains(instr->ssa_temp_index())) { |
318 marked_phis_->Remove(instr->ssa_temp_index()); | 317 marked_phis_->Remove(instr->ssa_temp_index()); |
319 definition_worklist_.Add(instr); | 318 definition_worklist_.Add(instr); |
320 } | 319 } |
321 } | 320 } |
322 | 321 |
323 | 322 |
324 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { | 323 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { |
325 // Ensure that we never remove redefinition of a constant unless we are also | 324 // Ensure that we never remove redefinition of a constant unless we are also |
326 // are guaranteed to fold away code paths that correspond to non-matching | 325 // are guaranteed to fold away code paths that correspond to non-matching |
327 // class ids. Otherwise LICM might potentially hoist incorrect code. | 326 // class ids. Otherwise LICM might potentially hoist incorrect code. |
328 const Object& value = instr->value()->definition()->constant_value(); | 327 const Object& value = instr->value()->definition()->constant_value(); |
329 if (IsConstant(value) && | 328 if (IsConstant(value) && !Field::IsExternalizableCid(value.GetClassId())) { |
330 !Field::IsExternalizableCid(value.GetClassId())) { | |
331 SetValue(instr, value); | 329 SetValue(instr, value); |
332 } else { | 330 } else { |
333 SetValue(instr, non_constant_); | 331 SetValue(instr, non_constant_); |
334 } | 332 } |
335 } | 333 } |
336 | 334 |
337 | 335 |
338 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { | 336 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { |
339 SetValue(instr, non_constant_); | 337 SetValue(instr, non_constant_); |
340 } | 338 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 | 419 |
422 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 420 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
423 instr->comparison()->Accept(this); | 421 instr->comparison()->Accept(this); |
424 const Object& value = instr->comparison()->constant_value(); | 422 const Object& value = instr->comparison()->constant_value(); |
425 if (IsNonConstant(value)) { | 423 if (IsNonConstant(value)) { |
426 SetValue(instr, non_constant_); | 424 SetValue(instr, non_constant_); |
427 } else if (IsConstant(value)) { | 425 } else if (IsConstant(value)) { |
428 ASSERT(!value.IsNull()); | 426 ASSERT(!value.IsNull()); |
429 ASSERT(value.IsBool()); | 427 ASSERT(value.IsBool()); |
430 bool result = Bool::Cast(value).value(); | 428 bool result = Bool::Cast(value).value(); |
431 SetValue(instr, | 429 SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true() |
432 Smi::Handle(Z, Smi::New( | 430 : instr->if_false()))); |
433 result ? instr->if_true() : instr->if_false()))); | |
434 } | 431 } |
435 } | 432 } |
436 | 433 |
437 | 434 |
438 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 435 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
439 Definition* left_defn = instr->left()->definition(); | 436 Definition* left_defn = instr->left()->definition(); |
440 Definition* right_defn = instr->right()->definition(); | 437 Definition* right_defn = instr->right()->definition(); |
441 | 438 |
442 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); | 439 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); |
443 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); | 440 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 SetValue(instr, Bool::Get(result)); | 483 SetValue(instr, Bool::Get(result)); |
487 } | 484 } |
488 } | 485 } |
489 | 486 |
490 | 487 |
491 static bool CompareIntegers(Token::Kind kind, | 488 static bool CompareIntegers(Token::Kind kind, |
492 const Integer& left, | 489 const Integer& left, |
493 const Integer& right) { | 490 const Integer& right) { |
494 const int result = left.CompareWith(right); | 491 const int result = left.CompareWith(right); |
495 switch (kind) { | 492 switch (kind) { |
496 case Token::kEQ: return (result == 0); | 493 case Token::kEQ: |
497 case Token::kNE: return (result != 0); | 494 return (result == 0); |
498 case Token::kLT: return (result < 0); | 495 case Token::kNE: |
499 case Token::kGT: return (result > 0); | 496 return (result != 0); |
500 case Token::kLTE: return (result <= 0); | 497 case Token::kLT: |
501 case Token::kGTE: return (result >= 0); | 498 return (result < 0); |
| 499 case Token::kGT: |
| 500 return (result > 0); |
| 501 case Token::kLTE: |
| 502 return (result <= 0); |
| 503 case Token::kGTE: |
| 504 return (result >= 0); |
502 default: | 505 default: |
503 UNREACHABLE(); | 506 UNREACHABLE(); |
504 return false; | 507 return false; |
505 } | 508 } |
506 } | 509 } |
507 | 510 |
508 | 511 |
509 // Comparison instruction that is equivalent to the (left & right) == 0 | 512 // Comparison instruction that is equivalent to the (left & right) == 0 |
510 // comparison pattern. | 513 // comparison pattern. |
511 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { | 514 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { |
512 const Object& left = instr->left()->definition()->constant_value(); | 515 const Object& left = instr->left()->definition()->constant_value(); |
513 const Object& right = instr->right()->definition()->constant_value(); | 516 const Object& right = instr->right()->definition()->constant_value(); |
514 if (IsNonConstant(left) || IsNonConstant(right)) { | 517 if (IsNonConstant(left) || IsNonConstant(right)) { |
515 SetValue(instr, non_constant_); | 518 SetValue(instr, non_constant_); |
516 } else if (IsConstant(left) && IsConstant(right)) { | 519 } else if (IsConstant(left) && IsConstant(right)) { |
517 // BitOp does not work on Bigints. | 520 // BitOp does not work on Bigints. |
518 if (left.IsInteger() && right.IsInteger() && | 521 if (left.IsInteger() && right.IsInteger() && !left.IsBigint() && |
519 !left.IsBigint() && !right.IsBigint()) { | 522 !right.IsBigint()) { |
520 const bool result = CompareIntegers( | 523 const bool result = CompareIntegers( |
521 instr->kind(), | 524 instr->kind(), |
522 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, | 525 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, |
523 Integer::Cast(right))), | 526 Integer::Cast(right))), |
524 Smi::Handle(Z, Smi::New(0))); | 527 Smi::Handle(Z, Smi::New(0))); |
525 SetValue(instr, result ? Bool::True() : Bool::False()); | 528 SetValue(instr, result ? Bool::True() : Bool::False()); |
526 } else { | 529 } else { |
527 SetValue(instr, non_constant_); | 530 SetValue(instr, non_constant_); |
528 } | 531 } |
529 } | 532 } |
(...skipping 26 matching lines...) Expand all Loading... |
556 return; | 559 return; |
557 } | 560 } |
558 } | 561 } |
559 | 562 |
560 const Object& left = left_defn->constant_value(); | 563 const Object& left = left_defn->constant_value(); |
561 const Object& right = right_defn->constant_value(); | 564 const Object& right = right_defn->constant_value(); |
562 if (IsNonConstant(left) || IsNonConstant(right)) { | 565 if (IsNonConstant(left) || IsNonConstant(right)) { |
563 SetValue(instr, non_constant_); | 566 SetValue(instr, non_constant_); |
564 } else if (IsConstant(left) && IsConstant(right)) { | 567 } else if (IsConstant(left) && IsConstant(right)) { |
565 if (left.IsInteger() && right.IsInteger()) { | 568 if (left.IsInteger() && right.IsInteger()) { |
566 const bool result = CompareIntegers(instr->kind(), | 569 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), |
567 Integer::Cast(left), | |
568 Integer::Cast(right)); | 570 Integer::Cast(right)); |
569 SetValue(instr, Bool::Get(result)); | 571 SetValue(instr, Bool::Get(result)); |
570 } else if (left.IsString() && right.IsString()) { | 572 } else if (left.IsString() && right.IsString()) { |
571 const bool result = String::Cast(left).Equals(String::Cast(right)); | 573 const bool result = String::Cast(left).Equals(String::Cast(right)); |
572 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); | 574 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); |
573 } else { | 575 } else { |
574 SetValue(instr, non_constant_); | 576 SetValue(instr, non_constant_); |
575 } | 577 } |
576 } | 578 } |
577 } | 579 } |
578 | 580 |
579 | 581 |
580 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { | 582 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { |
581 const Object& left = instr->left()->definition()->constant_value(); | 583 const Object& left = instr->left()->definition()->constant_value(); |
582 const Object& right = instr->right()->definition()->constant_value(); | 584 const Object& right = instr->right()->definition()->constant_value(); |
583 if (IsNonConstant(left) || IsNonConstant(right)) { | 585 if (IsNonConstant(left) || IsNonConstant(right)) { |
584 SetValue(instr, non_constant_); | 586 SetValue(instr, non_constant_); |
585 } else if (IsConstant(left) && IsConstant(right)) { | 587 } else if (IsConstant(left) && IsConstant(right)) { |
586 if (left.IsInteger() && right.IsInteger()) { | 588 if (left.IsInteger() && right.IsInteger()) { |
587 const bool result = CompareIntegers(instr->kind(), | 589 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), |
588 Integer::Cast(left), | |
589 Integer::Cast(right)); | 590 Integer::Cast(right)); |
590 SetValue(instr, Bool::Get(result)); | 591 SetValue(instr, Bool::Get(result)); |
591 } else if (left.IsDouble() && right.IsDouble()) { | 592 } else if (left.IsDouble() && right.IsDouble()) { |
592 // TODO(srdjan): Implement. | 593 // TODO(srdjan): Implement. |
593 SetValue(instr, non_constant_); | 594 SetValue(instr, non_constant_); |
594 } else { | 595 } else { |
595 SetValue(instr, non_constant_); | 596 SetValue(instr, non_constant_); |
596 } | 597 } |
597 } | 598 } |
598 } | 599 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 if (!index_obj.IsSmi()) { | 655 if (!index_obj.IsSmi()) { |
655 // Should not occur. | 656 // Should not occur. |
656 SetValue(instr, non_constant_); | 657 SetValue(instr, non_constant_); |
657 return; | 658 return; |
658 } | 659 } |
659 const intptr_t index = Smi::Cast(index_obj).Value(); | 660 const intptr_t index = Smi::Cast(index_obj).Value(); |
660 if (index >= 0) { | 661 if (index >= 0) { |
661 if (array_obj.IsString()) { | 662 if (array_obj.IsString()) { |
662 const String& str = String::Cast(array_obj); | 663 const String& str = String::Cast(array_obj); |
663 if (str.Length() > index) { | 664 if (str.Length() > index) { |
664 SetValue(instr, Smi::Handle(Z, | 665 SetValue(instr, |
665 Smi::New(static_cast<intptr_t>(str.CharAt(index))))); | 666 Smi::Handle( |
| 667 Z, Smi::New(static_cast<intptr_t>(str.CharAt(index))))); |
666 return; | 668 return; |
667 } | 669 } |
668 } else if (array_obj.IsArray()) { | 670 } else if (array_obj.IsArray()) { |
669 const Array& a = Array::Cast(array_obj); | 671 const Array& a = Array::Cast(array_obj); |
670 if ((a.Length() > index) && a.IsImmutable()) { | 672 if ((a.Length() > index) && a.IsImmutable()) { |
671 Instance& result = Instance::Handle(Z); | 673 Instance& result = Instance::Handle(Z); |
672 result ^= a.At(index); | 674 result ^= a.At(index); |
673 SetValue(instr, result); | 675 SetValue(instr, result); |
674 return; | 676 return; |
675 } | 677 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 } else { | 759 } else { |
758 SetValue(instr, non_constant_); | 760 SetValue(instr, non_constant_); |
759 } | 761 } |
760 } else if (IsConstant(value)) { | 762 } else if (IsConstant(value)) { |
761 if (value.IsInstance()) { | 763 if (value.IsInstance()) { |
762 const Instance& instance = Instance::Cast(value); | 764 const Instance& instance = Instance::Cast(value); |
763 const AbstractType& checked_type = instr->type(); | 765 const AbstractType& checked_type = instr->type(); |
764 if (instr->instantiator_type_arguments()->BindsToConstantNull()) { | 766 if (instr->instantiator_type_arguments()->BindsToConstantNull()) { |
765 const TypeArguments& checked_type_arguments = TypeArguments::Handle(); | 767 const TypeArguments& checked_type_arguments = TypeArguments::Handle(); |
766 Error& bound_error = Error::Handle(); | 768 Error& bound_error = Error::Handle(); |
767 bool is_instance = instance.IsInstanceOf(checked_type, | 769 bool is_instance = instance.IsInstanceOf( |
768 checked_type_arguments, | 770 checked_type, checked_type_arguments, &bound_error); |
769 &bound_error); | |
770 // Can only have bound error with generics. | 771 // Can only have bound error with generics. |
771 ASSERT(bound_error.IsNull()); | 772 ASSERT(bound_error.IsNull()); |
772 SetValue(instr, Bool::Get(instr->negate_result() | 773 SetValue(instr, Bool::Get(instr->negate_result() ? !is_instance |
773 ? !is_instance : is_instance)); | 774 : is_instance)); |
774 return; | 775 return; |
775 } | 776 } |
776 } | 777 } |
777 SetValue(instr, non_constant_); | 778 SetValue(instr, non_constant_); |
778 } | 779 } |
779 } | 780 } |
780 | 781 |
781 | 782 |
782 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { | 783 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { |
783 SetValue(instr, non_constant_); | 784 SetValue(instr, non_constant_); |
(...skipping 26 matching lines...) Expand all Loading... |
810 } | 811 } |
811 } | 812 } |
812 SetValue(instr, non_constant_); | 813 SetValue(instr, non_constant_); |
813 } | 814 } |
814 | 815 |
815 | 816 |
816 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 817 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
817 Value* instance = instr->instance(); | 818 Value* instance = instr->instance(); |
818 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 819 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
819 instance->definition()->OriginalDefinition()->IsCreateArray()) { | 820 instance->definition()->OriginalDefinition()->IsCreateArray()) { |
820 Value* num_elements = instance->definition()->OriginalDefinition() | 821 Value* num_elements = instance->definition() |
821 ->AsCreateArray()->num_elements(); | 822 ->OriginalDefinition() |
| 823 ->AsCreateArray() |
| 824 ->num_elements(); |
822 if (num_elements->BindsToConstant() && | 825 if (num_elements->BindsToConstant() && |
823 num_elements->BoundConstant().IsSmi()) { | 826 num_elements->BoundConstant().IsSmi()) { |
824 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 827 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
825 const Object& result = Smi::ZoneHandle(Z, Smi::New(length)); | 828 const Object& result = Smi::ZoneHandle(Z, Smi::New(length)); |
826 SetValue(instr, result); | 829 SetValue(instr, result); |
827 return; | 830 return; |
828 } | 831 } |
829 } | 832 } |
830 | 833 |
831 if (instr->IsImmutableLengthLoad()) { | 834 if (instr->IsImmutableLengthLoad()) { |
832 ConstantInstr* constant = | 835 ConstantInstr* constant = |
833 instance->definition()->OriginalDefinition()->AsConstant(); | 836 instance->definition()->OriginalDefinition()->AsConstant(); |
834 if (constant != NULL) { | 837 if (constant != NULL) { |
835 if (constant->value().IsString()) { | 838 if (constant->value().IsString()) { |
836 SetValue(instr, Smi::ZoneHandle(Z, | 839 SetValue(instr, |
837 Smi::New(String::Cast(constant->value()).Length()))); | 840 Smi::ZoneHandle( |
| 841 Z, Smi::New(String::Cast(constant->value()).Length()))); |
838 return; | 842 return; |
839 } | 843 } |
840 if (constant->value().IsArray()) { | 844 if (constant->value().IsArray()) { |
841 SetValue(instr, Smi::ZoneHandle(Z, | 845 SetValue(instr, |
842 Smi::New(Array::Cast(constant->value()).Length()))); | 846 Smi::ZoneHandle( |
| 847 Z, Smi::New(Array::Cast(constant->value()).Length()))); |
843 return; | 848 return; |
844 } | 849 } |
845 if (constant->value().IsTypedData()) { | 850 if (constant->value().IsTypedData()) { |
846 SetValue(instr, Smi::ZoneHandle(Z, | 851 SetValue(instr, |
847 Smi::New(TypedData::Cast(constant->value()).Length()))); | 852 Smi::ZoneHandle( |
| 853 Z, Smi::New(TypedData::Cast(constant->value()).Length()))); |
848 return; | 854 return; |
849 } | 855 } |
850 } | 856 } |
851 } | 857 } |
852 SetValue(instr, non_constant_); | 858 SetValue(instr, non_constant_); |
853 } | 859 } |
854 | 860 |
855 | 861 |
856 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 862 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
857 const Object& object = | 863 const Object& object = instr->instantiator()->definition()->constant_value(); |
858 instr->instantiator()->definition()->constant_value(); | |
859 if (IsNonConstant(object)) { | 864 if (IsNonConstant(object)) { |
860 SetValue(instr, non_constant_); | 865 SetValue(instr, non_constant_); |
861 return; | 866 return; |
862 } | 867 } |
863 if (IsConstant(object)) { | 868 if (IsConstant(object)) { |
864 if (instr->type().IsTypeParameter()) { | 869 if (instr->type().IsTypeParameter()) { |
865 if (object.IsNull()) { | 870 if (object.IsNull()) { |
866 SetValue(instr, Object::dynamic_type()); | 871 SetValue(instr, Object::dynamic_type()); |
867 return; | 872 return; |
868 } | 873 } |
869 // We could try to instantiate the type parameter and return it if no | 874 // We could try to instantiate the type parameter and return it if no |
870 // malformed error is reported. | 875 // malformed error is reported. |
871 } | 876 } |
872 SetValue(instr, non_constant_); | 877 SetValue(instr, non_constant_); |
873 } | 878 } |
874 } | 879 } |
875 | 880 |
876 | 881 |
877 void ConstantPropagator::VisitInstantiateTypeArguments( | 882 void ConstantPropagator::VisitInstantiateTypeArguments( |
878 InstantiateTypeArgumentsInstr* instr) { | 883 InstantiateTypeArgumentsInstr* instr) { |
879 const Object& object = | 884 const Object& object = instr->instantiator()->definition()->constant_value(); |
880 instr->instantiator()->definition()->constant_value(); | |
881 if (IsNonConstant(object)) { | 885 if (IsNonConstant(object)) { |
882 SetValue(instr, non_constant_); | 886 SetValue(instr, non_constant_); |
883 return; | 887 return; |
884 } | 888 } |
885 if (IsConstant(object)) { | 889 if (IsConstant(object)) { |
886 const intptr_t len = instr->type_arguments().Length(); | 890 const intptr_t len = instr->type_arguments().Length(); |
887 if (instr->type_arguments().IsRawInstantiatedRaw(len) && | 891 if (instr->type_arguments().IsRawInstantiatedRaw(len) && object.IsNull()) { |
888 object.IsNull()) { | |
889 SetValue(instr, object); | 892 SetValue(instr, object); |
890 return; | 893 return; |
891 } | 894 } |
892 if (instr->type_arguments().IsUninstantiatedIdentity() || | 895 if (instr->type_arguments().IsUninstantiatedIdentity() || |
893 instr->type_arguments().CanShareInstantiatorTypeArguments( | 896 instr->type_arguments().CanShareInstantiatorTypeArguments( |
894 instr->instantiator_class())) { | 897 instr->instantiator_class())) { |
895 SetValue(instr, object); | 898 SetValue(instr, object); |
896 return; | 899 return; |
897 } | 900 } |
898 SetValue(instr, non_constant_); | 901 SetValue(instr, non_constant_); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { | 989 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { |
987 // TODO(kmillikin): Handle unbox operation. | 990 // TODO(kmillikin): Handle unbox operation. |
988 SetValue(instr, non_constant_); | 991 SetValue(instr, non_constant_); |
989 } | 992 } |
990 | 993 |
991 | 994 |
992 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { | 995 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { |
993 const Object& value = unary_op->value()->definition()->constant_value(); | 996 const Object& value = unary_op->value()->definition()->constant_value(); |
994 if (IsConstant(value) && value.IsInteger()) { | 997 if (IsConstant(value) && value.IsInteger()) { |
995 const Integer& value_int = Integer::Cast(value); | 998 const Integer& value_int = Integer::Cast(value); |
996 const Integer& result = | 999 const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int)); |
997 Integer::Handle(Z, unary_op->Evaluate(value_int)); | |
998 if (!result.IsNull()) { | 1000 if (!result.IsNull()) { |
999 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); | 1001 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); |
1000 return; | 1002 return; |
1001 } | 1003 } |
1002 } | 1004 } |
1003 | 1005 |
1004 SetValue(unary_op, non_constant_); | 1006 SetValue(unary_op, non_constant_); |
1005 } | 1007 } |
1006 | 1008 |
1007 | 1009 |
(...skipping 14 matching lines...) Expand all Loading... |
1022 } else if (IsConstant(value)) { | 1024 } else if (IsConstant(value)) { |
1023 // TODO(kmillikin): Handle unary operations. | 1025 // TODO(kmillikin): Handle unary operations. |
1024 SetValue(instr, non_constant_); | 1026 SetValue(instr, non_constant_); |
1025 } | 1027 } |
1026 } | 1028 } |
1027 | 1029 |
1028 | 1030 |
1029 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 1031 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
1030 const Object& value = instr->value()->definition()->constant_value(); | 1032 const Object& value = instr->value()->definition()->constant_value(); |
1031 if (IsConstant(value) && value.IsInteger()) { | 1033 if (IsConstant(value) && value.IsInteger()) { |
1032 SetValue(instr, Double::Handle(Z, | 1034 SetValue(instr, |
1033 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 1035 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1036 Heap::kOld))); |
1034 } else if (!IsUnknown(value)) { | 1037 } else if (!IsUnknown(value)) { |
1035 SetValue(instr, non_constant_); | 1038 SetValue(instr, non_constant_); |
1036 } | 1039 } |
1037 } | 1040 } |
1038 | 1041 |
1039 | 1042 |
1040 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { | 1043 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { |
1041 const Object& value = instr->value()->definition()->constant_value(); | 1044 const Object& value = instr->value()->definition()->constant_value(); |
1042 if (IsConstant(value) && value.IsInteger()) { | 1045 if (IsConstant(value) && value.IsInteger()) { |
1043 SetValue(instr, Double::Handle(Z, | 1046 SetValue(instr, |
1044 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 1047 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1048 Heap::kOld))); |
1045 } else if (!IsUnknown(value)) { | 1049 } else if (!IsUnknown(value)) { |
1046 SetValue(instr, non_constant_); | 1050 SetValue(instr, non_constant_); |
1047 } | 1051 } |
1048 } | 1052 } |
1049 | 1053 |
1050 | 1054 |
1051 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { | 1055 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { |
1052 const Object& value = instr->value()->definition()->constant_value(); | 1056 const Object& value = instr->value()->definition()->constant_value(); |
1053 if (IsConstant(value) && value.IsInteger()) { | 1057 if (IsConstant(value) && value.IsInteger()) { |
1054 SetValue(instr, Double::Handle(Z, | 1058 SetValue(instr, |
1055 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 1059 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1060 Heap::kOld))); |
1056 } else if (!IsUnknown(value)) { | 1061 } else if (!IsUnknown(value)) { |
1057 SetValue(instr, non_constant_); | 1062 SetValue(instr, non_constant_); |
1058 } | 1063 } |
1059 } | 1064 } |
1060 | 1065 |
1061 | 1066 |
1062 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | 1067 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { |
1063 // TODO(kmillikin): Handle conversion. | 1068 // TODO(kmillikin): Handle conversion. |
1064 SetValue(instr, non_constant_); | 1069 SetValue(instr, non_constant_); |
1065 } | 1070 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 return value.IsInteger() || value.IsDouble(); | 1138 return value.IsInteger() || value.IsDouble(); |
1134 } | 1139 } |
1135 | 1140 |
1136 | 1141 |
1137 static double ToDouble(const Object& value) { | 1142 static double ToDouble(const Object& value) { |
1138 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() | 1143 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() |
1139 : Double::Cast(value).value(); | 1144 : Double::Cast(value).value(); |
1140 } | 1145 } |
1141 | 1146 |
1142 | 1147 |
1143 void ConstantPropagator::VisitBinaryDoubleOp( | 1148 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { |
1144 BinaryDoubleOpInstr* instr) { | |
1145 const Object& left = instr->left()->definition()->constant_value(); | 1149 const Object& left = instr->left()->definition()->constant_value(); |
1146 const Object& right = instr->right()->definition()->constant_value(); | 1150 const Object& right = instr->right()->definition()->constant_value(); |
1147 if (IsNonConstant(left) || IsNonConstant(right)) { | 1151 if (IsNonConstant(left) || IsNonConstant(right)) { |
1148 SetValue(instr, non_constant_); | 1152 SetValue(instr, non_constant_); |
1149 } else if (left.IsInteger() && right.IsInteger()) { | 1153 } else if (left.IsInteger() && right.IsInteger()) { |
1150 SetValue(instr, non_constant_); | 1154 SetValue(instr, non_constant_); |
1151 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { | 1155 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { |
1152 const double left_val = ToDouble(left); | 1156 const double left_val = ToDouble(left); |
1153 const double right_val = ToDouble(right); | 1157 const double right_val = ToDouble(right); |
1154 double result_val = 0.0; | 1158 double result_val = 0.0; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1193 } | 1197 } |
1194 default: | 1198 default: |
1195 UNREACHABLE(); | 1199 UNREACHABLE(); |
1196 } | 1200 } |
1197 } else { | 1201 } else { |
1198 SetValue(instr, non_constant_); | 1202 SetValue(instr, non_constant_); |
1199 } | 1203 } |
1200 } | 1204 } |
1201 | 1205 |
1202 | 1206 |
1203 void ConstantPropagator::VisitBinaryFloat32x4Op( | 1207 void ConstantPropagator::VisitBinaryFloat32x4Op(BinaryFloat32x4OpInstr* instr) { |
1204 BinaryFloat32x4OpInstr* instr) { | |
1205 const Object& left = instr->left()->definition()->constant_value(); | 1208 const Object& left = instr->left()->definition()->constant_value(); |
1206 const Object& right = instr->right()->definition()->constant_value(); | 1209 const Object& right = instr->right()->definition()->constant_value(); |
1207 if (IsNonConstant(left) || IsNonConstant(right)) { | 1210 if (IsNonConstant(left) || IsNonConstant(right)) { |
1208 SetValue(instr, non_constant_); | 1211 SetValue(instr, non_constant_); |
1209 } else if (IsConstant(left) && IsConstant(right)) { | 1212 } else if (IsConstant(left) && IsConstant(right)) { |
1210 // TODO(kmillikin): Handle binary operation. | 1213 // TODO(kmillikin): Handle binary operation. |
1211 SetValue(instr, non_constant_); | 1214 SetValue(instr, non_constant_); |
1212 } | 1215 } |
1213 } | 1216 } |
1214 | 1217 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 SetValue(instr, non_constant_); | 1344 SetValue(instr, non_constant_); |
1342 } | 1345 } |
1343 | 1346 |
1344 | 1347 |
1345 void ConstantPropagator::VisitFloat64x2ToFloat32x4( | 1348 void ConstantPropagator::VisitFloat64x2ToFloat32x4( |
1346 Float64x2ToFloat32x4Instr* instr) { | 1349 Float64x2ToFloat32x4Instr* instr) { |
1347 SetValue(instr, non_constant_); | 1350 SetValue(instr, non_constant_); |
1348 } | 1351 } |
1349 | 1352 |
1350 | 1353 |
1351 void ConstantPropagator::VisitFloat64x2Zero( | 1354 void ConstantPropagator::VisitFloat64x2Zero(Float64x2ZeroInstr* instr) { |
1352 Float64x2ZeroInstr* instr) { | |
1353 SetValue(instr, non_constant_); | 1355 SetValue(instr, non_constant_); |
1354 } | 1356 } |
1355 | 1357 |
1356 | 1358 |
1357 void ConstantPropagator::VisitFloat64x2Splat( | 1359 void ConstantPropagator::VisitFloat64x2Splat(Float64x2SplatInstr* instr) { |
1358 Float64x2SplatInstr* instr) { | |
1359 SetValue(instr, non_constant_); | 1360 SetValue(instr, non_constant_); |
1360 } | 1361 } |
1361 | 1362 |
1362 | 1363 |
1363 void ConstantPropagator::VisitFloat64x2Constructor( | 1364 void ConstantPropagator::VisitFloat64x2Constructor( |
1364 Float64x2ConstructorInstr* instr) { | 1365 Float64x2ConstructorInstr* instr) { |
1365 SetValue(instr, non_constant_); | 1366 SetValue(instr, non_constant_); |
1366 } | 1367 } |
1367 | 1368 |
1368 | 1369 |
(...skipping 26 matching lines...) Expand all Loading... |
1395 if (IsNonConstant(left) || IsNonConstant(right)) { | 1396 if (IsNonConstant(left) || IsNonConstant(right)) { |
1396 SetValue(instr, non_constant_); | 1397 SetValue(instr, non_constant_); |
1397 } else if (IsConstant(left) && IsConstant(right)) { | 1398 } else if (IsConstant(left) && IsConstant(right)) { |
1398 // TODO(srdjan): Handle min and max. | 1399 // TODO(srdjan): Handle min and max. |
1399 SetValue(instr, non_constant_); | 1400 SetValue(instr, non_constant_); |
1400 } | 1401 } |
1401 } | 1402 } |
1402 | 1403 |
1403 | 1404 |
1404 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | 1405 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
1405 CaseInsensitiveCompareUC16Instr *instr) { | 1406 CaseInsensitiveCompareUC16Instr* instr) { |
1406 SetValue(instr, non_constant_); | 1407 SetValue(instr, non_constant_); |
1407 } | 1408 } |
1408 | 1409 |
1409 | 1410 |
1410 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { | 1411 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { |
1411 const Object& value = instr->value()->definition()->constant_value(); | 1412 const Object& value = instr->value()->definition()->constant_value(); |
1412 if (IsNonConstant(value)) { | 1413 if (IsNonConstant(value)) { |
1413 SetValue(instr, non_constant_); | 1414 SetValue(instr, non_constant_); |
1414 } else if (IsConstant(value)) { | 1415 } else if (IsConstant(value)) { |
1415 // TODO(kmillikin): Handle conversion. | 1416 // TODO(kmillikin): Handle conversion. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 } else { | 1483 } else { |
1483 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 1484 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
1484 block->Accept(this); | 1485 block->Accept(this); |
1485 } | 1486 } |
1486 } | 1487 } |
1487 } | 1488 } |
1488 | 1489 |
1489 | 1490 |
1490 static bool IsEmptyBlock(BlockEntryInstr* block) { | 1491 static bool IsEmptyBlock(BlockEntryInstr* block) { |
1491 return block->next()->IsGoto() && | 1492 return block->next()->IsGoto() && |
1492 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && | 1493 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
1493 !block->IsIndirectEntry(); | 1494 !block->IsIndirectEntry(); |
1494 } | 1495 } |
1495 | 1496 |
1496 | 1497 |
1497 // Traverses a chain of empty blocks and returns the first reachable non-empty | 1498 // Traverses a chain of empty blocks and returns the first reachable non-empty |
1498 // block that is not dominated by the start block. The empty blocks are added | 1499 // block that is not dominated by the start block. The empty blocks are added |
1499 // to the supplied bit vector. | 1500 // to the supplied bit vector. |
1500 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 1501 static BlockEntryInstr* FindFirstNonEmptySuccessor(TargetEntryInstr* block, |
1501 TargetEntryInstr* block, | 1502 BitVector* empty_blocks) { |
1502 BitVector* empty_blocks) { | |
1503 BlockEntryInstr* current = block; | 1503 BlockEntryInstr* current = block; |
1504 while (IsEmptyBlock(current) && block->Dominates(current)) { | 1504 while (IsEmptyBlock(current) && block->Dominates(current)) { |
1505 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 1505 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
1506 empty_blocks->Add(current->preorder_number()); | 1506 empty_blocks->Add(current->preorder_number()); |
1507 current = current->next()->AsGoto()->successor(); | 1507 current = current->next()->AsGoto()->successor(); |
1508 } | 1508 } |
1509 return current; | 1509 return current; |
1510 } | 1510 } |
1511 | 1511 |
1512 | 1512 |
1513 void ConstantPropagator::EliminateRedundantBranches() { | 1513 void ConstantPropagator::EliminateRedundantBranches() { |
1514 // Canonicalize branches that have no side-effects and where true- and | 1514 // Canonicalize branches that have no side-effects and where true- and |
1515 // false-targets are the same. | 1515 // false-targets are the same. |
1516 bool changed = false; | 1516 bool changed = false; |
1517 BitVector* empty_blocks = new(Z) BitVector(Z, | 1517 BitVector* empty_blocks = new (Z) BitVector(Z, graph_->preorder().length()); |
1518 graph_->preorder().length()); | 1518 for (BlockIterator b = graph_->postorder_iterator(); !b.Done(); b.Advance()) { |
1519 for (BlockIterator b = graph_->postorder_iterator(); | |
1520 !b.Done(); | |
1521 b.Advance()) { | |
1522 BlockEntryInstr* block = b.Current(); | 1519 BlockEntryInstr* block = b.Current(); |
1523 BranchInstr* branch = block->last_instruction()->AsBranch(); | 1520 BranchInstr* branch = block->last_instruction()->AsBranch(); |
1524 empty_blocks->Clear(); | 1521 empty_blocks->Clear(); |
1525 if ((branch != NULL) && branch->Effects().IsNone()) { | 1522 if ((branch != NULL) && branch->Effects().IsNone()) { |
1526 ASSERT(branch->previous() != NULL); // Not already eliminated. | 1523 ASSERT(branch->previous() != NULL); // Not already eliminated. |
1527 BlockEntryInstr* if_true = | 1524 BlockEntryInstr* if_true = |
1528 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); | 1525 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); |
1529 BlockEntryInstr* if_false = | 1526 BlockEntryInstr* if_false = |
1530 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); | 1527 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); |
1531 if (if_true == if_false) { | 1528 if (if_true == if_false) { |
1532 // Replace the branch with a jump to the common successor. | 1529 // Replace the branch with a jump to the common successor. |
1533 // Drop the comparison, which does not have side effects | 1530 // Drop the comparison, which does not have side effects |
1534 JoinEntryInstr* join = if_true->AsJoinEntry(); | 1531 JoinEntryInstr* join = if_true->AsJoinEntry(); |
1535 if (join->phis() == NULL) { | 1532 if (join->phis() == NULL) { |
1536 GotoInstr* jump = new(Z) GotoInstr(if_true->AsJoinEntry()); | 1533 GotoInstr* jump = new (Z) GotoInstr(if_true->AsJoinEntry()); |
1537 jump->InheritDeoptTarget(Z, branch); | 1534 jump->InheritDeoptTarget(Z, branch); |
1538 | 1535 |
1539 Instruction* previous = branch->previous(); | 1536 Instruction* previous = branch->previous(); |
1540 branch->set_previous(NULL); | 1537 branch->set_previous(NULL); |
1541 previous->LinkTo(jump); | 1538 previous->LinkTo(jump); |
1542 | 1539 |
1543 // Remove uses from branch and all the empty blocks that | 1540 // Remove uses from branch and all the empty blocks that |
1544 // are now unreachable. | 1541 // are now unreachable. |
1545 branch->UnuseAllInputs(); | 1542 branch->UnuseAllInputs(); |
1546 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { | 1543 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { |
(...skipping 25 matching lines...) Expand all Loading... |
1572 void ConstantPropagator::Transform() { | 1569 void ConstantPropagator::Transform() { |
1573 if (FLAG_trace_constant_propagation && | 1570 if (FLAG_trace_constant_propagation && |
1574 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1571 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
1575 FlowGraphPrinter::PrintGraph("Before CP", graph_); | 1572 FlowGraphPrinter::PrintGraph("Before CP", graph_); |
1576 } | 1573 } |
1577 | 1574 |
1578 // We will recompute dominators, block ordering, block ids, block last | 1575 // We will recompute dominators, block ordering, block ids, block last |
1579 // instructions, previous pointers, predecessors, etc. after eliminating | 1576 // instructions, previous pointers, predecessors, etc. after eliminating |
1580 // unreachable code. We do not maintain those properties during the | 1577 // unreachable code. We do not maintain those properties during the |
1581 // transformation. | 1578 // transformation. |
1582 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 1579 for (BlockIterator b = graph_->reverse_postorder_iterator(); !b.Done(); |
1583 !b.Done(); | |
1584 b.Advance()) { | 1580 b.Advance()) { |
1585 BlockEntryInstr* block = b.Current(); | 1581 BlockEntryInstr* block = b.Current(); |
1586 if (!reachable_->Contains(block->preorder_number())) { | 1582 if (!reachable_->Contains(block->preorder_number())) { |
1587 if (FLAG_trace_constant_propagation && | 1583 if (FLAG_trace_constant_propagation && |
1588 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1584 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
1589 THR_Print("Unreachable B%" Pd "\n", block->block_id()); | 1585 THR_Print("Unreachable B%" Pd "\n", block->block_id()); |
1590 } | 1586 } |
1591 // Remove all uses in unreachable blocks. | 1587 // Remove all uses in unreachable blocks. |
1592 block->ClearAllInstructions(); | 1588 block->ClearAllInstructions(); |
1593 continue; | 1589 continue; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1642 } | 1638 } |
1643 } | 1639 } |
1644 } | 1640 } |
1645 } | 1641 } |
1646 | 1642 |
1647 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { | 1643 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { |
1648 Definition* defn = i.Current()->AsDefinition(); | 1644 Definition* defn = i.Current()->AsDefinition(); |
1649 // Replace constant-valued instructions without observable side | 1645 // Replace constant-valued instructions without observable side |
1650 // effects. Do this for smis only to avoid having to copy other | 1646 // effects. Do this for smis only to avoid having to copy other |
1651 // objects into the heap's old generation. | 1647 // objects into the heap's old generation. |
1652 if ((defn != NULL) && | 1648 if ((defn != NULL) && IsConstant(defn->constant_value()) && |
1653 IsConstant(defn->constant_value()) && | |
1654 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && | 1649 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && |
1655 !defn->IsConstant() && | 1650 !defn->IsConstant() && !defn->IsPushArgument() && |
1656 !defn->IsPushArgument() && | 1651 !defn->IsStoreIndexed() && !defn->IsStoreInstanceField() && |
1657 !defn->IsStoreIndexed() && | |
1658 !defn->IsStoreInstanceField() && | |
1659 !defn->IsStoreStaticField()) { | 1652 !defn->IsStoreStaticField()) { |
1660 if (FLAG_trace_constant_propagation && | 1653 if (FLAG_trace_constant_propagation && |
1661 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1654 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
1662 THR_Print("Constant v%" Pd " = %s\n", | 1655 THR_Print("Constant v%" Pd " = %s\n", defn->ssa_temp_index(), |
1663 defn->ssa_temp_index(), | |
1664 defn->constant_value().ToCString()); | 1656 defn->constant_value().ToCString()); |
1665 } | 1657 } |
1666 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); | 1658 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); |
1667 defn->ReplaceUsesWith(constant); | 1659 defn->ReplaceUsesWith(constant); |
1668 i.RemoveCurrentFromGraph(); | 1660 i.RemoveCurrentFromGraph(); |
1669 } | 1661 } |
1670 } | 1662 } |
1671 | 1663 |
1672 // Replace branches where one target is unreachable with jumps. | 1664 // Replace branches where one target is unreachable with jumps. |
1673 BranchInstr* branch = block->last_instruction()->AsBranch(); | 1665 BranchInstr* branch = block->last_instruction()->AsBranch(); |
1674 if (branch != NULL) { | 1666 if (branch != NULL) { |
1675 TargetEntryInstr* if_true = branch->true_successor(); | 1667 TargetEntryInstr* if_true = branch->true_successor(); |
1676 TargetEntryInstr* if_false = branch->false_successor(); | 1668 TargetEntryInstr* if_false = branch->false_successor(); |
1677 JoinEntryInstr* join = NULL; | 1669 JoinEntryInstr* join = NULL; |
1678 Instruction* next = NULL; | 1670 Instruction* next = NULL; |
1679 | 1671 |
1680 if (!reachable_->Contains(if_true->preorder_number())) { | 1672 if (!reachable_->Contains(if_true->preorder_number())) { |
1681 ASSERT(reachable_->Contains(if_false->preorder_number())); | 1673 ASSERT(reachable_->Contains(if_false->preorder_number())); |
1682 ASSERT(if_false->parallel_move() == NULL); | 1674 ASSERT(if_false->parallel_move() == NULL); |
1683 ASSERT(if_false->loop_info() == NULL); | 1675 ASSERT(if_false->loop_info() == NULL); |
1684 join = new(Z) JoinEntryInstr(if_false->block_id(), | 1676 join = |
1685 if_false->try_index()); | 1677 new (Z) JoinEntryInstr(if_false->block_id(), if_false->try_index()); |
1686 join->InheritDeoptTarget(Z, if_false); | 1678 join->InheritDeoptTarget(Z, if_false); |
1687 if_false->UnuseAllInputs(); | 1679 if_false->UnuseAllInputs(); |
1688 next = if_false->next(); | 1680 next = if_false->next(); |
1689 } else if (!reachable_->Contains(if_false->preorder_number())) { | 1681 } else if (!reachable_->Contains(if_false->preorder_number())) { |
1690 ASSERT(if_true->parallel_move() == NULL); | 1682 ASSERT(if_true->parallel_move() == NULL); |
1691 ASSERT(if_true->loop_info() == NULL); | 1683 ASSERT(if_true->loop_info() == NULL); |
1692 join = new(Z) JoinEntryInstr(if_true->block_id(), | 1684 join = |
1693 if_true->try_index()); | 1685 new (Z) JoinEntryInstr(if_true->block_id(), if_true->try_index()); |
1694 join->InheritDeoptTarget(Z, if_true); | 1686 join->InheritDeoptTarget(Z, if_true); |
1695 if_true->UnuseAllInputs(); | 1687 if_true->UnuseAllInputs(); |
1696 next = if_true->next(); | 1688 next = if_true->next(); |
1697 } | 1689 } |
1698 | 1690 |
1699 if (join != NULL) { | 1691 if (join != NULL) { |
1700 // Replace the branch with a jump to the reachable successor. | 1692 // Replace the branch with a jump to the reachable successor. |
1701 // Drop the comparison, which does not have side effects as long | 1693 // Drop the comparison, which does not have side effects as long |
1702 // as it is a strict compare (the only one we can determine is | 1694 // as it is a strict compare (the only one we can determine is |
1703 // constant with the current analysis). | 1695 // constant with the current analysis). |
1704 GotoInstr* jump = new(Z) GotoInstr(join); | 1696 GotoInstr* jump = new (Z) GotoInstr(join); |
1705 jump->InheritDeoptTarget(Z, branch); | 1697 jump->InheritDeoptTarget(Z, branch); |
1706 | 1698 |
1707 Instruction* previous = branch->previous(); | 1699 Instruction* previous = branch->previous(); |
1708 branch->set_previous(NULL); | 1700 branch->set_previous(NULL); |
1709 previous->LinkTo(jump); | 1701 previous->LinkTo(jump); |
1710 | 1702 |
1711 // Replace the false target entry with the new join entry. We will | 1703 // Replace the false target entry with the new join entry. We will |
1712 // recompute the dominators after this pass. | 1704 // recompute the dominators after this pass. |
1713 join->LinkTo(next); | 1705 join->LinkTo(next); |
1714 branch->UnuseAllInputs(); | 1706 branch->UnuseAllInputs(); |
1715 } | 1707 } |
1716 } | 1708 } |
1717 } | 1709 } |
1718 | 1710 |
1719 graph_->DiscoverBlocks(); | 1711 graph_->DiscoverBlocks(); |
1720 graph_->MergeBlocks(); | 1712 graph_->MergeBlocks(); |
1721 GrowableArray<BitVector*> dominance_frontier; | 1713 GrowableArray<BitVector*> dominance_frontier; |
1722 graph_->ComputeDominators(&dominance_frontier); | 1714 graph_->ComputeDominators(&dominance_frontier); |
1723 | 1715 |
1724 if (FLAG_trace_constant_propagation && | 1716 if (FLAG_trace_constant_propagation && |
1725 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1717 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
1726 FlowGraphPrinter::PrintGraph("After CP", graph_); | 1718 FlowGraphPrinter::PrintGraph("After CP", graph_); |
1727 } | 1719 } |
1728 } | 1720 } |
1729 | 1721 |
1730 } // namespace dart | 1722 } // namespace dart |
OLD | NEW |