Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/hash_map.h" | 10 #include "vm/hash_map.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/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
| 15 #include "vm/scopes.h" | 15 #include "vm/scopes.h" |
| 16 #include "vm/symbols.h" | 16 #include "vm/symbols.h" |
| 17 | 17 |
| 18 namespace dart { | 18 namespace dart { |
| 19 | 19 |
| 20 DECLARE_FLAG(bool, eliminate_type_checks); | 20 DECLARE_FLAG(bool, eliminate_type_checks); |
| 21 DECLARE_FLAG(bool, enable_type_checks); | 21 DECLARE_FLAG(bool, enable_type_checks); |
| 22 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | 22 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
| 23 DECLARE_FLAG(bool, trace_type_check_elimination); | 23 DECLARE_FLAG(bool, trace_type_check_elimination); |
| 24 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | 24 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
| 25 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); | 25 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); |
| 26 DEFINE_FLAG(bool, trace_constant_propagation, false, | |
| 27 "Print constant propagation and useless code elimination."); | |
| 26 | 28 |
| 27 void FlowGraphOptimizer::ApplyICData() { | 29 void FlowGraphOptimizer::ApplyICData() { |
| 28 VisitBlocks(); | 30 VisitBlocks(); |
| 29 } | 31 } |
| 30 | 32 |
| 31 | 33 |
| 32 static void ReplaceCurrentInstruction(ForwardInstructionIterator* it, | 34 static void ReplaceCurrentInstruction(ForwardInstructionIterator* it, |
| 33 Instruction* current, | 35 Instruction* current, |
| 34 Instruction* replacement) { | 36 Instruction* replacement) { |
| 35 if ((replacement != NULL) && current->IsDefinition()) { | 37 if ((replacement != NULL) && current->IsDefinition()) { |
| (...skipping 2382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2418 } else if (value.raw() == Bool::True()) { | 2420 } else if (value.raw() == Bool::True()) { |
| 2419 SetReachable(instr->true_successor()); | 2421 SetReachable(instr->true_successor()); |
| 2420 } else if (!IsUnknown(value)) { // Any other constant. | 2422 } else if (!IsUnknown(value)) { // Any other constant. |
| 2421 SetReachable(instr->false_successor()); | 2423 SetReachable(instr->false_successor()); |
| 2422 } | 2424 } |
| 2423 } | 2425 } |
| 2424 } | 2426 } |
| 2425 | 2427 |
| 2426 | 2428 |
| 2427 // -------------------------------------------------------------------------- | 2429 // -------------------------------------------------------------------------- |
| 2430 // Analysis of non-definition instructions. They do not have values so they | |
| 2431 // cannot have constant values. | |
| 2432 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { } | |
| 2433 | |
| 2434 | |
| 2435 void ConstantPropagator::VisitChainContext(ChainContextInstr* instr) { } | |
| 2436 | |
| 2437 | |
| 2438 void ConstantPropagator::VisitCatchEntry(CatchEntryInstr* instr) { } | |
| 2439 | |
| 2440 | |
| 2441 void ConstantPropagator::VisitCheckStackOverflow( | |
| 2442 CheckStackOverflowInstr* instr) { } | |
| 2443 | |
| 2444 | |
| 2445 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } | |
| 2446 | |
| 2447 | |
| 2448 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { } | |
| 2449 | |
| 2450 | |
| 2451 void ConstantPropagator::VisitCheckEitherNonSmi( | |
| 2452 CheckEitherNonSmiInstr* instr) { } | |
| 2453 | |
| 2454 | |
| 2455 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } | |
| 2456 | |
| 2457 | |
| 2458 // -------------------------------------------------------------------------- | |
| 2428 // Analysis of definitions. Compute the constant value. If it has changed | 2459 // Analysis of definitions. Compute the constant value. If it has changed |
| 2429 // and the definition has input uses, add the definition to the definition | 2460 // and the definition has input uses, add the definition to the definition |
| 2430 // worklist so that the used can be processed. | 2461 // worklist so that the used can be processed. |
| 2431 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 2462 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
| 2432 // Compute the join over all the reachable predecessor values. | 2463 // Compute the join over all the reachable predecessor values. |
| 2433 JoinEntryInstr* block = instr->block(); | 2464 JoinEntryInstr* block = instr->block(); |
| 2434 Object& value = Object::ZoneHandle(Unknown()); | 2465 Object& value = Object::ZoneHandle(Unknown()); |
| 2435 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 2466 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
| 2436 if (reachable_->Contains( | 2467 if (reachable_->Contains( |
| 2437 block->PredecessorAt(pred_idx)->preorder_number())) { | 2468 block->PredecessorAt(pred_idx)->preorder_number())) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2481 ArgumentDefinitionTestInstr* instr) { | 2512 ArgumentDefinitionTestInstr* instr) { |
| 2482 SetValue(instr, non_constant_); | 2513 SetValue(instr, non_constant_); |
| 2483 } | 2514 } |
| 2484 | 2515 |
| 2485 | 2516 |
| 2486 void ConstantPropagator::VisitCurrentContext(CurrentContextInstr* instr) { | 2517 void ConstantPropagator::VisitCurrentContext(CurrentContextInstr* instr) { |
| 2487 SetValue(instr, non_constant_); | 2518 SetValue(instr, non_constant_); |
| 2488 } | 2519 } |
| 2489 | 2520 |
| 2490 | 2521 |
| 2491 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { | |
| 2492 // Nothing to do. Not a value. | |
| 2493 } | |
| 2494 | |
| 2495 | |
| 2496 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) { | 2522 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) { |
| 2497 SetValue(instr, non_constant_); | 2523 SetValue(instr, non_constant_); |
| 2498 } | 2524 } |
| 2499 | 2525 |
| 2500 | 2526 |
| 2501 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) { | 2527 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) { |
| 2502 SetValue(instr, non_constant_); | 2528 SetValue(instr, non_constant_); |
| 2503 } | 2529 } |
| 2504 | 2530 |
| 2505 | 2531 |
| 2506 void ConstantPropagator::VisitPolymorphicInstanceCall( | 2532 void ConstantPropagator::VisitPolymorphicInstanceCall( |
| 2507 PolymorphicInstanceCallInstr* instr) { | 2533 PolymorphicInstanceCallInstr* instr) { |
| 2508 SetValue(instr, non_constant_); | 2534 SetValue(instr, non_constant_); |
| 2509 } | 2535 } |
| 2510 | 2536 |
| 2511 | 2537 |
| 2512 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { | 2538 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { |
| 2513 SetValue(instr, non_constant_); | 2539 SetValue(instr, non_constant_); |
| 2514 } | 2540 } |
| 2515 | 2541 |
| 2516 | 2542 |
| 2517 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { | 2543 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { |
| 2544 // Instruction is eliminated when translating to SSA. | |
| 2518 UNREACHABLE(); | 2545 UNREACHABLE(); |
| 2519 } | 2546 } |
| 2520 | 2547 |
| 2521 | 2548 |
| 2522 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { | 2549 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { |
| 2550 // Instruction is eliminated when translating to SSA. | |
| 2523 UNREACHABLE(); | 2551 UNREACHABLE(); |
| 2524 } | 2552 } |
| 2525 | 2553 |
| 2526 | 2554 |
| 2527 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 2555 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
| 2528 const Object& left = instr->left()->definition()->constant_value(); | 2556 const Object& left = instr->left()->definition()->constant_value(); |
| 2529 const Object& right = instr->right()->definition()->constant_value(); | 2557 const Object& right = instr->right()->definition()->constant_value(); |
| 2530 if (IsNonConstant(left) || IsNonConstant(right)) { | 2558 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 2531 SetValue(instr, non_constant_); | 2559 SetValue(instr, non_constant_); |
| 2532 } else if (IsConstant(left) && IsConstant(right)) { | 2560 } else if (IsConstant(left) && IsConstant(right)) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2661 ExtractConstructorInstantiatorInstr* instr) { | 2689 ExtractConstructorInstantiatorInstr* instr) { |
| 2662 SetValue(instr, non_constant_); | 2690 SetValue(instr, non_constant_); |
| 2663 } | 2691 } |
| 2664 | 2692 |
| 2665 | 2693 |
| 2666 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { | 2694 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { |
| 2667 SetValue(instr, non_constant_); | 2695 SetValue(instr, non_constant_); |
| 2668 } | 2696 } |
| 2669 | 2697 |
| 2670 | 2698 |
| 2671 void ConstantPropagator::VisitChainContext(ChainContextInstr* instr) { | |
| 2672 // Nothing to do. Not a value. | |
| 2673 } | |
| 2674 | |
| 2675 | |
| 2676 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { | 2699 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { |
| 2677 SetValue(instr, non_constant_); | 2700 SetValue(instr, non_constant_); |
| 2678 } | 2701 } |
| 2679 | 2702 |
| 2680 | 2703 |
| 2681 void ConstantPropagator::VisitCatchEntry(CatchEntryInstr* instr) { | |
| 2682 // Nothing to do. Not a value. | |
| 2683 } | |
| 2684 | |
| 2685 | |
| 2686 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { | 2704 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { |
| 2687 const Object& left = instr->left()->definition()->constant_value(); | 2705 const Object& left = instr->left()->definition()->constant_value(); |
| 2688 const Object& right = instr->right()->definition()->constant_value(); | 2706 const Object& right = instr->right()->definition()->constant_value(); |
| 2689 if (IsNonConstant(left) || IsNonConstant(right)) { | 2707 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 2690 SetValue(instr, non_constant_); | 2708 SetValue(instr, non_constant_); |
| 2691 } else if (IsConstant(left) && IsConstant(right)) { | 2709 } else if (IsConstant(left) && IsConstant(right)) { |
| 2692 if (left.IsSmi() && right.IsSmi()) { | 2710 if (left.IsSmi() && right.IsSmi()) { |
| 2711 const Smi& left_smi = Smi::Cast(left); | |
| 2712 const Smi& right_smi = Smi::Cast(right); | |
| 2693 switch (instr->op_kind()) { | 2713 switch (instr->op_kind()) { |
| 2694 case Token::kADD: | 2714 case Token::kADD: |
| 2695 case Token::kSUB: | 2715 case Token::kSUB: |
| 2696 case Token::kMUL: | 2716 case Token::kMUL: |
| 2697 case Token::kTRUNCDIV: | 2717 case Token::kTRUNCDIV: |
| 2698 case Token::kMOD: { | 2718 case Token::kMOD: { |
| 2699 const Object& result = | 2719 const Object& result = Integer::ZoneHandle( |
| 2700 Integer::ZoneHandle(Smi::Cast(left).BinaryOp(instr->op_kind(), | 2720 left_smi.ArithmeticOp(instr->op_kind(), right_smi)); |
| 2701 Smi::Cast(right))); | |
| 2702 SetValue(instr, result); | 2721 SetValue(instr, result); |
| 2703 break; | 2722 break; |
| 2704 } | 2723 } |
| 2724 case Token::kSHL: | |
| 2725 case Token::kSHR: { | |
| 2726 const Object& result = Integer::ZoneHandle( | |
| 2727 left_smi.ShiftOp(instr->op_kind(), right_smi)); | |
| 2728 SetValue(instr, result); | |
| 2729 break; | |
| 2730 } | |
| 2731 case Token::kBIT_AND: | |
| 2732 case Token::kBIT_OR: | |
| 2733 case Token::kBIT_XOR: { | |
| 2734 const Object& result = Integer::ZoneHandle( | |
| 2735 left_smi.BitOp(instr->op_kind(), right_smi)); | |
| 2736 SetValue(instr, result); | |
| 2737 break; | |
| 2738 } | |
| 2705 default: | 2739 default: |
| 2706 // TODO(kmillikin): support other smi operations. | 2740 // TODO(kmillikin): support other smi operations. |
| 2707 SetValue(instr, non_constant_); | 2741 SetValue(instr, non_constant_); |
| 2708 } | 2742 } |
| 2709 } else { | 2743 } else { |
| 2710 // TODO(kmillikin): support other types. | 2744 // TODO(kmillikin): support other types. |
| 2711 SetValue(instr, non_constant_); | 2745 SetValue(instr, non_constant_); |
| 2712 } | 2746 } |
| 2713 } | 2747 } |
| 2714 } | 2748 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2730 const Object& value = instr->value()->definition()->constant_value(); | 2764 const Object& value = instr->value()->definition()->constant_value(); |
| 2731 if (IsNonConstant(value)) { | 2765 if (IsNonConstant(value)) { |
| 2732 SetValue(instr, non_constant_); | 2766 SetValue(instr, non_constant_); |
| 2733 } else if (IsConstant(value)) { | 2767 } else if (IsConstant(value)) { |
| 2734 // TODO(kmillikin): Handle unary operations. | 2768 // TODO(kmillikin): Handle unary operations. |
| 2735 SetValue(instr, non_constant_); | 2769 SetValue(instr, non_constant_); |
| 2736 } | 2770 } |
| 2737 } | 2771 } |
| 2738 | 2772 |
| 2739 | 2773 |
| 2740 void ConstantPropagator::VisitCheckStackOverflow( | |
| 2741 CheckStackOverflowInstr* instr) { | |
| 2742 // Nothing to do. Not a value. | |
| 2743 } | |
| 2744 | |
| 2745 | |
| 2746 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { | 2774 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) { |
| 2747 const Object& value = instr->value()->definition()->constant_value(); | 2775 const Object& value = instr->value()->definition()->constant_value(); |
| 2748 if (IsNonConstant(value)) { | 2776 if (IsNonConstant(value)) { |
| 2749 SetValue(instr, non_constant_); | 2777 SetValue(instr, non_constant_); |
| 2750 } else if (IsConstant(value)) { | 2778 } else if (IsConstant(value)) { |
| 2751 // TODO(kmillikin): Handle conversion. | 2779 // TODO(kmillikin): Handle conversion. |
| 2752 SetValue(instr, non_constant_); | 2780 SetValue(instr, non_constant_); |
| 2753 } | 2781 } |
| 2754 } | 2782 } |
| 2755 | 2783 |
| 2756 | 2784 |
| 2757 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 2785 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
| 2758 // TODO(kmillikin): Handle conversion. | 2786 // TODO(kmillikin): Handle conversion. |
| 2759 SetValue(instr, non_constant_); | 2787 SetValue(instr, non_constant_); |
| 2760 } | 2788 } |
| 2761 | 2789 |
| 2762 | 2790 |
| 2763 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { | |
| 2764 // Nothing to do. Not a value. | |
| 2765 } | |
| 2766 | |
| 2767 | |
| 2768 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { | |
| 2769 // Nothing to do. Has no value. | |
| 2770 } | |
| 2771 | |
| 2772 | |
| 2773 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { | 2791 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { |
| 2774 SetValue(instr, instr->value()); | 2792 SetValue(instr, instr->value()); |
| 2775 } | 2793 } |
| 2776 | 2794 |
| 2777 | 2795 |
| 2778 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { | 2796 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { |
| 2779 // Should not be used outside of range analysis. | 2797 // Should not be used outside of range analysis. |
| 2780 UNREACHABLE(); | 2798 UNREACHABLE(); |
| 2781 } | 2799 } |
| 2782 | 2800 |
| 2783 | 2801 |
| 2784 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { | |
| 2785 // Nothing to do. Not a value. | |
| 2786 } | |
| 2787 | |
| 2788 | |
| 2789 void ConstantPropagator::VisitUnboxedDoubleBinaryOp( | 2802 void ConstantPropagator::VisitUnboxedDoubleBinaryOp( |
| 2790 UnboxedDoubleBinaryOpInstr* instr) { | 2803 UnboxedDoubleBinaryOpInstr* instr) { |
| 2791 const Object& left = instr->left()->definition()->constant_value(); | 2804 const Object& left = instr->left()->definition()->constant_value(); |
| 2792 const Object& right = instr->right()->definition()->constant_value(); | 2805 const Object& right = instr->right()->definition()->constant_value(); |
| 2793 if (IsNonConstant(left) || IsNonConstant(right)) { | 2806 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 2794 SetValue(instr, non_constant_); | 2807 SetValue(instr, non_constant_); |
| 2795 } else if (IsConstant(left) && IsConstant(right)) { | 2808 } else if (IsConstant(left) && IsConstant(right)) { |
| 2796 // TODO(kmillikin): Handle binary operation. | 2809 // TODO(kmillikin): Handle binary operation. |
| 2797 SetValue(instr, non_constant_); | 2810 SetValue(instr, non_constant_); |
| 2798 } | 2811 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2825 const Object& value = instr->value()->definition()->constant_value(); | 2838 const Object& value = instr->value()->definition()->constant_value(); |
| 2826 if (IsNonConstant(value)) { | 2839 if (IsNonConstant(value)) { |
| 2827 SetValue(instr, non_constant_); | 2840 SetValue(instr, non_constant_); |
| 2828 } else if (IsConstant(value)) { | 2841 } else if (IsConstant(value)) { |
| 2829 // TODO(kmillikin): Handle conversion. | 2842 // TODO(kmillikin): Handle conversion. |
| 2830 SetValue(instr, non_constant_); | 2843 SetValue(instr, non_constant_); |
| 2831 } | 2844 } |
| 2832 } | 2845 } |
| 2833 | 2846 |
| 2834 | 2847 |
| 2835 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { | |
| 2836 // Nothing to do. Not a value. | |
| 2837 } | |
| 2838 | |
| 2839 | |
| 2840 void ConstantPropagator::Analyze() { | 2848 void ConstantPropagator::Analyze() { |
| 2841 GraphEntryInstr* entry = graph_->graph_entry(); | 2849 GraphEntryInstr* entry = graph_->graph_entry(); |
| 2842 reachable_->Add(entry->preorder_number()); | 2850 reachable_->Add(entry->preorder_number()); |
| 2843 block_worklist_.Add(entry); | 2851 block_worklist_.Add(entry); |
| 2844 | 2852 |
| 2845 while (true) { | 2853 while (true) { |
| 2846 if (block_worklist_.is_empty()) { | 2854 if (block_worklist_.is_empty()) { |
| 2847 if (definition_worklist_.is_empty()) break; | 2855 if (definition_worklist_.is_empty()) break; |
| 2848 Definition* definition = definition_worklist_.Last(); | 2856 Definition* definition = definition_worklist_.Last(); |
| 2849 definition_worklist_.RemoveLast(); | 2857 definition_worklist_.RemoveLast(); |
| 2850 definition_marks_->Remove(definition->ssa_temp_index()); | 2858 definition_marks_->Remove(definition->ssa_temp_index()); |
| 2851 Value* use = definition->input_use_list(); | 2859 Value* use = definition->input_use_list(); |
| 2852 while (use != NULL) { | 2860 while (use != NULL) { |
| 2853 use->instruction()->Accept(this); | 2861 use->instruction()->Accept(this); |
| 2854 use = use->next_use(); | 2862 use = use->next_use(); |
| 2855 } | 2863 } |
| 2856 } else { | 2864 } else { |
| 2857 BlockEntryInstr* block = block_worklist_.Last(); | 2865 BlockEntryInstr* block = block_worklist_.Last(); |
| 2858 block_worklist_.RemoveLast(); | 2866 block_worklist_.RemoveLast(); |
| 2859 block->Accept(this); | 2867 block->Accept(this); |
| 2860 } | 2868 } |
| 2861 } | 2869 } |
| 2862 } | 2870 } |
| 2863 | 2871 |
| 2864 | 2872 |
| 2865 void ConstantPropagator::Transform() { | 2873 void ConstantPropagator::Transform() { |
| 2874 if (FLAG_trace_constant_propagation) { | |
| 2875 OS::Print("\n==== Before constant propagation ====\n"); | |
| 2876 FlowGraphPrinter printer(*graph_); | |
| 2877 printer.PrintBlocks(); | |
| 2878 } | |
| 2879 | |
| 2866 // We will recompute dominators, block ordering, block ids, block last | 2880 // We will recompute dominators, block ordering, block ids, block last |
| 2867 // instructions, previous pointers, predecessors, etc. after eliminating | 2881 // instructions, previous pointers, predecessors, etc. after eliminating |
| 2868 // unreachable code. We do not maintain those properties during the | 2882 // unreachable code. We do not maintain those properties during the |
| 2869 // transformation. | 2883 // transformation. |
| 2870 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 2884 for (BlockIterator b = graph_->reverse_postorder_iterator(); |
| 2871 !b.Done(); | 2885 !b.Done(); |
| 2872 b.Advance()) { | 2886 b.Advance()) { |
| 2873 BlockEntryInstr* block = b.Current(); | 2887 BlockEntryInstr* block = b.Current(); |
| 2874 if (!reachable_->Contains(block->preorder_number())) { | 2888 if (!reachable_->Contains(block->preorder_number())) { |
| 2889 if (FLAG_trace_constant_propagation) { | |
| 2890 OS::Print("Unreachable B%"Pd"\n", block->block_id()); | |
| 2891 } | |
| 2875 continue; | 2892 continue; |
| 2876 } | 2893 } |
| 2877 | 2894 |
| 2878 JoinEntryInstr* join = block->AsJoinEntry(); | 2895 JoinEntryInstr* join = block->AsJoinEntry(); |
| 2879 if (join != NULL) { | 2896 if (join != NULL) { |
| 2880 // Remove phi inputs corresponding to unreachable predecessor blocks. | 2897 // Remove phi inputs corresponding to unreachable predecessor blocks. |
| 2881 // Predecessors will be recomputed (in block id order) after removing | 2898 // Predecessors will be recomputed (in block id order) after removing |
| 2882 // unreachable code so we merely have to keep the phi inputs in order. | 2899 // unreachable code so we merely have to keep the phi inputs in order. |
| 2883 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); | 2900 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
| 2884 if (phis != NULL) { | 2901 if (phis != NULL) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2902 PhiInstr* phi = (*phis)[phi_idx]; | 2919 PhiInstr* phi = (*phis)[phi_idx]; |
| 2903 if (phi == NULL) continue; | 2920 if (phi == NULL) continue; |
| 2904 phi->inputs_.TruncateTo(live_count); | 2921 phi->inputs_.TruncateTo(live_count); |
| 2905 } | 2922 } |
| 2906 } | 2923 } |
| 2907 } | 2924 } |
| 2908 } | 2925 } |
| 2909 | 2926 |
| 2910 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { | 2927 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { |
| 2911 Definition* defn = i.Current()->AsDefinition(); | 2928 Definition* defn = i.Current()->AsDefinition(); |
| 2912 if (defn != NULL && IsConstant(defn->constant_value())) { | 2929 // Replace constant-valued instructions without observable side |
| 2913 if (!defn->IsConstant() && | 2930 // effects. Do this for smis only to avoid having to copy other |
| 2914 !defn->IsPushArgument() && | 2931 // objects into the heap's old generation. |
|
Florian Schneider
2012/09/24 11:36:17
Maybe add a TODO to extend the analysis for bool-v
Kevin Millikin (Google)
2012/09/24 12:23:46
Done.
| |
| 2915 !defn->IsStoreLocal() && | 2932 if ((defn != NULL) && |
| 2916 !defn->IsStoreIndexed() && | 2933 defn->constant_value().IsSmi() && |
| 2917 !defn->IsStoreInstanceField() && | 2934 !defn->IsConstant() && |
| 2918 !defn->IsStoreStaticField() && | 2935 !defn->IsPushArgument() && |
| 2919 !defn->IsStoreVMField()) { | 2936 !defn->IsStoreIndexed() && |
| 2920 // TODO(kmillikin): propagate constants to replace instructions | 2937 !defn->IsStoreInstanceField() && |
| 2921 // without side effects. | 2938 !defn->IsStoreStaticField() && |
| 2939 !defn->IsStoreVMField()) { | |
| 2940 if (FLAG_trace_constant_propagation) { | |
| 2941 OS::Print("Constant v%"Pd" = %s\n", | |
| 2942 defn->ssa_temp_index(), | |
| 2943 defn->constant_value().ToCString()); | |
| 2922 } | 2944 } |
| 2945 i.ReplaceCurrentWith(new ConstantInstr(defn->constant_value())); | |
| 2923 } | 2946 } |
| 2924 } | 2947 } |
| 2925 | 2948 |
| 2926 // Replace branches where one target is unreachable with jumps. | 2949 // Replace branches where one target is unreachable with jumps. |
| 2927 BranchInstr* branch = block->last_instruction()->AsBranch(); | 2950 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 2928 if (branch != NULL) { | 2951 if (branch != NULL) { |
| 2929 TargetEntryInstr* if_true = branch->true_successor(); | 2952 TargetEntryInstr* if_true = branch->true_successor(); |
| 2930 TargetEntryInstr* if_false = branch->false_successor(); | 2953 TargetEntryInstr* if_false = branch->false_successor(); |
| 2931 JoinEntryInstr* join = NULL; | 2954 JoinEntryInstr* join = NULL; |
| 2932 Instruction* next = NULL; | 2955 Instruction* next = NULL; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2946 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); | 2969 join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); |
| 2947 next = if_true->next(); | 2970 next = if_true->next(); |
| 2948 } | 2971 } |
| 2949 | 2972 |
| 2950 if (join != NULL) { | 2973 if (join != NULL) { |
| 2951 // Replace the branch with a jump to the reachable successor. | 2974 // Replace the branch with a jump to the reachable successor. |
| 2952 // Drop the comparison, which does not have side effects as long | 2975 // Drop the comparison, which does not have side effects as long |
| 2953 // as it is a strict compare (the only one we can determine is | 2976 // as it is a strict compare (the only one we can determine is |
| 2954 // constant with the current analysis). | 2977 // constant with the current analysis). |
| 2955 GotoInstr* jump = new GotoInstr(join); | 2978 GotoInstr* jump = new GotoInstr(join); |
| 2956 // Removing the branch from the graph will leave the iterator in a | |
| 2957 // state where current is detached from the graph. Since current | |
| 2958 // has no successors and neither does its replacement, that's | |
| 2959 // safe. | |
| 2960 Instruction* previous = branch->previous(); | 2979 Instruction* previous = branch->previous(); |
| 2961 branch->set_previous(NULL); | 2980 branch->set_previous(NULL); |
| 2962 previous->set_next(jump); | 2981 previous->set_next(jump); |
| 2963 // Replace the false target entry with the new join entry. We will | 2982 // Replace the false target entry with the new join entry. We will |
| 2964 // recompute the dominators after this pass. | 2983 // recompute the dominators after this pass. |
| 2965 join->set_next(next); | 2984 join->set_next(next); |
| 2966 } | 2985 } |
| 2967 } | 2986 } |
| 2968 } | 2987 } |
| 2969 | 2988 |
| 2970 graph_->DiscoverBlocks(); | 2989 graph_->DiscoverBlocks(); |
| 2971 GrowableArray<BitVector*> dominance_frontier; | 2990 GrowableArray<BitVector*> dominance_frontier; |
| 2972 graph_->ComputeDominators(&dominance_frontier); | 2991 graph_->ComputeDominators(&dominance_frontier); |
| 2973 graph_->ComputeUseLists(); | 2992 graph_->ComputeUseLists(); |
| 2993 | |
| 2994 if (FLAG_trace_constant_propagation) { | |
| 2995 OS::Print("\n==== After constant propagation ====\n"); | |
| 2996 FlowGraphPrinter printer(*graph_); | |
| 2997 printer.PrintBlocks(); | |
| 2998 } | |
| 2974 } | 2999 } |
| 2975 | 3000 |
| 2976 | 3001 |
| 2977 } // namespace dart | 3002 } // namespace dart |
| OLD | NEW |