Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10968058: Support constant folding of instructions with constant smi values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/platform/utils.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/platform/utils.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698