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 |