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

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

Issue 23757016: Simplify compilation of relational operators. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 new LoadIndexedInstr(new Value(array), 1070 new LoadIndexedInstr(new Value(array),
1071 new Value(index), 1071 new Value(index),
1072 index_scale, 1072 index_scale,
1073 array_cid, 1073 array_cid,
1074 deopt_id); 1074 deopt_id);
1075 ReplaceCall(call, array_op); 1075 ReplaceCall(call, array_op);
1076 return true; 1076 return true;
1077 } 1077 }
1078 1078
1079 1079
1080 static bool SmiFitsInDouble() { return kSmiBits < 53; }
1081
1082
1083 bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
1084 Token::Kind op_kind) {
1085 const ICData& ic_data = *call->ic_data();
1086 ASSERT(ic_data.num_args_tested() == 2);
1087
1088 ASSERT(call->ArgumentCount() == 2);
1089 Definition* left = call->ArgumentAt(0);
1090 Definition* right = call->ArgumentAt(1);
1091
1092 intptr_t cid = kIllegalCid;
1093 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1094 InsertBefore(call,
1095 new CheckSmiInstr(new Value(left), call->deopt_id()),
1096 call->env(),
1097 Definition::kEffect);
1098 InsertBefore(call,
1099 new CheckSmiInstr(new Value(right), call->deopt_id()),
1100 call->env(),
1101 Definition::kEffect);
1102 cid = kSmiCid;
1103 } else if (HasTwoMintOrSmi(ic_data) &&
1104 FlowGraphCompiler::SupportsUnboxedMints()) {
1105 cid = kMintCid;
1106 } else if (HasTwoDoubleOrSmi(ic_data)) {
1107 // Use double comparison.
1108 if (SmiFitsInDouble()) {
1109 cid = kDoubleCid;
1110 } else {
1111 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
1112 // We cannot use double comparison on two smis. Need polymorphic
1113 // call.
1114 return false;
1115 } else {
1116 InsertBefore(call,
1117 new CheckEitherNonSmiInstr(new Value(left),
1118 new Value(right),
1119 call->deopt_id()),
1120 call->env(),
1121 Definition::kEffect);
1122 cid = kDoubleCid;
1123 }
1124 }
1125 } else {
1126 return false;
1127 }
1128 ASSERT(cid != kIllegalCid);
1129 RelationalOpInstr* comp = new RelationalOpInstr(call->token_pos(),
1130 op_kind,
1131 new Value(left),
1132 new Value(right),
1133 cid,
1134 call->deopt_id());
1135 ReplaceCall(call, comp);
1136 return true;
1137 }
1138
1139
1080 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, 1140 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
1081 Token::Kind op_kind) { 1141 Token::Kind op_kind) {
1082 intptr_t operands_type = kIllegalCid; 1142 intptr_t operands_type = kIllegalCid;
1083 ASSERT(call->HasICData()); 1143 ASSERT(call->HasICData());
1084 const ICData& ic_data = *call->ic_data(); 1144 const ICData& ic_data = *call->ic_data();
1085 switch (op_kind) { 1145 switch (op_kind) {
1086 case Token::kADD: 1146 case Token::kADD:
1087 case Token::kSUB: 1147 case Token::kSUB:
1088 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1148 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1089 // Don't generate smi code if the IC data is marked because 1149 // Don't generate smi code if the IC data is marked because
(...skipping 1513 matching lines...) Expand 10 before | Expand all | Expand 10 after
2603 instr->set_ic_data(&unary_checks); 2663 instr->set_ic_data(&unary_checks);
2604 return; 2664 return;
2605 } 2665 }
2606 2666
2607 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { 2667 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) {
2608 return; 2668 return;
2609 } 2669 }
2610 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) { 2670 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) {
2611 return; 2671 return;
2612 } 2672 }
2673
2674 if (Token::IsRelationalOperator(op_kind) &&
2675 TryReplaceWithRelationalOp(instr, op_kind)) {
2676 return;
2677 }
2678
2613 if (Token::IsBinaryOperator(op_kind) && 2679 if (Token::IsBinaryOperator(op_kind) &&
2614 TryReplaceWithBinaryOp(instr, op_kind)) { 2680 TryReplaceWithBinaryOp(instr, op_kind)) {
2615 return; 2681 return;
2616 } 2682 }
2617 if (Token::IsPrefixOperator(op_kind) && 2683 if (Token::IsPrefixOperator(op_kind) &&
2618 TryReplaceWithUnaryOp(instr, op_kind)) { 2684 TryReplaceWithUnaryOp(instr, op_kind)) {
2619 return; 2685 return;
2620 } 2686 }
2621 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) { 2687 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) {
2622 return; 2688 return;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2691 push->RemoveFromGraph(); 2757 push->RemoveFromGraph();
2692 } 2758 }
2693 // Manually replace call with global null constant. ReplaceCall can't 2759 // Manually replace call with global null constant. ReplaceCall can't
2694 // be used for definitions that are already in the graph. 2760 // be used for definitions that are already in the graph.
2695 call->ReplaceUsesWith(flow_graph_->constant_null()); 2761 call->ReplaceUsesWith(flow_graph_->constant_null());
2696 ASSERT(current_iterator()->Current() == call); 2762 ASSERT(current_iterator()->Current() == call);
2697 current_iterator()->RemoveCurrentFromGraph();; 2763 current_iterator()->RemoveCurrentFromGraph();;
2698 } else if ((recognized_kind == MethodRecognizer::kMathMin) || 2764 } else if ((recognized_kind == MethodRecognizer::kMathMin) ||
2699 (recognized_kind == MethodRecognizer::kMathMax)) { 2765 (recognized_kind == MethodRecognizer::kMathMax)) {
2700 // We can handle only monomorphic min/max call sites with both arguments 2766 // We can handle only monomorphic min/max call sites with both arguments
2701 // being either doubles or Smi-s 2767 // being either doubles or smis.
2702 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 2768 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
2703 const ICData& ic_data = *call->ic_data(); 2769 const ICData& ic_data = *call->ic_data();
2704 intptr_t result_cid = kIllegalCid; 2770 intptr_t result_cid = kIllegalCid;
2705 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) { 2771 if (ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid)) {
2706 result_cid = kDoubleCid; 2772 result_cid = kDoubleCid;
2707 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { 2773 } else if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
2708 result_cid = kSmiCid; 2774 result_cid = kSmiCid;
2709 } 2775 }
2710 if (result_cid != kIllegalCid) { 2776 if (result_cid != kIllegalCid) {
2711 MathMinMaxInstr* min_max = new MathMinMaxInstr( 2777 MathMinMaxInstr* min_max = new MathMinMaxInstr(
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2806 new Value(instr->ArgumentAt(1)), 2872 new Value(instr->ArgumentAt(1)),
2807 needs_store_barrier); 2873 needs_store_barrier);
2808 // Discard the environment from the original instruction because the store 2874 // Discard the environment from the original instruction because the store
2809 // can't deoptimize. 2875 // can't deoptimize.
2810 instr->RemoveEnvironment(); 2876 instr->RemoveEnvironment();
2811 ReplaceCall(instr, store); 2877 ReplaceCall(instr, store);
2812 return true; 2878 return true;
2813 } 2879 }
2814 2880
2815 2881
2816 static bool SmiFitsInDouble() { return kSmiBits < 53; }
2817
2818
2819 void FlowGraphOptimizer::HandleComparison(ComparisonInstr* comp,
2820 const ICData& ic_data,
2821 Instruction* current_instruction) {
2822 ASSERT(ic_data.num_args_tested() == 2);
2823 ASSERT(comp->operation_cid() == kIllegalCid);
2824 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
2825 InsertBefore(current_instruction,
2826 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
2827 current_instruction->env(),
2828 Definition::kEffect);
2829 InsertBefore(current_instruction,
2830 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
2831 current_instruction->env(),
2832 Definition::kEffect);
2833 comp->set_operation_cid(kSmiCid);
2834 } else if (HasTwoMintOrSmi(ic_data) &&
2835 FlowGraphCompiler::SupportsUnboxedMints()) {
2836 comp->set_operation_cid(kMintCid);
2837 } else if (HasTwoDoubleOrSmi(ic_data)) {
2838 // Use double comparison.
2839 if (SmiFitsInDouble()) {
2840 comp->set_operation_cid(kDoubleCid);
2841 } else {
2842 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
2843 // We cannot use double comparison on two Smi-s.
2844 ASSERT(comp->operation_cid() == kIllegalCid);
2845 } else {
2846 InsertBefore(current_instruction,
2847 new CheckEitherNonSmiInstr(comp->left()->Copy(),
2848 comp->right()->Copy(),
2849 comp->deopt_id()),
2850 current_instruction->env(),
2851 Definition::kEffect);
2852 comp->set_operation_cid(kDoubleCid);
2853 }
2854 }
2855 } else {
2856 ASSERT(comp->operation_cid() == kIllegalCid);
2857 }
2858 }
2859
2860
2861 void FlowGraphOptimizer::HandleRelationalOp(RelationalOpInstr* comp) {
2862 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) {
2863 return;
2864 }
2865 HandleComparison(comp, *comp->ic_data(), current_iterator()->Current());
2866 }
2867
2868
2869 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpInstr* instr) {
2870 HandleRelationalOp(instr);
2871 }
2872
2873
2874 bool FlowGraphOptimizer::CanStrictifyEqualityCompare( 2882 bool FlowGraphOptimizer::CanStrictifyEqualityCompare(
2875 EqualityCompareInstr* compare) { 2883 EqualityCompareInstr* compare) {
2876 // If one of the inputs is null this is a strict comparison. 2884 // If one of the inputs is null this is a strict comparison.
2877 if (compare->left()->BindsToConstantNull() || 2885 if (compare->left()->BindsToConstantNull() ||
2878 compare->right()->BindsToConstantNull()) { 2886 compare->right()->BindsToConstantNull()) {
2879 return true; 2887 return true;
2880 } 2888 }
2881 2889
2882 if (compare->left()->Type()->IsNone()) { 2890 if (compare->left()->Type()->IsNone()) {
2883 return false; // We might be running prior to any type propagation passes. 2891 return false; // We might be running prior to any type propagation passes.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2986 if (StrictifyEqualityCompare(comp, current_instruction)) { 2994 if (StrictifyEqualityCompare(comp, current_instruction)) {
2987 // Based on input types, equality converted to strict-equality. 2995 // Based on input types, equality converted to strict-equality.
2988 return; 2996 return;
2989 } 2997 }
2990 2998
2991 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { 2999 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) {
2992 return; 3000 return;
2993 } 3001 }
2994 3002
2995 const ICData& ic_data = *comp->ic_data(); 3003 const ICData& ic_data = *comp->ic_data();
2996 HandleComparison(comp, ic_data, current_instruction); 3004 ASSERT(ic_data.num_args_tested() == 2);
3005 ASSERT(comp->operation_cid() == kIllegalCid);
3006 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
3007 InsertBefore(current_instruction,
3008 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
3009 current_instruction->env(),
3010 Definition::kEffect);
3011 InsertBefore(current_instruction,
3012 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
3013 current_instruction->env(),
3014 Definition::kEffect);
3015 comp->set_operation_cid(kSmiCid);
3016 } else if (HasTwoMintOrSmi(ic_data) &&
3017 FlowGraphCompiler::SupportsUnboxedMints()) {
3018 comp->set_operation_cid(kMintCid);
3019 } else if (HasTwoDoubleOrSmi(ic_data)) {
3020 // Use double comparison.
3021 if (SmiFitsInDouble()) {
3022 comp->set_operation_cid(kDoubleCid);
3023 } else {
3024 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
3025 // We cannot use double comparison on two smis.
3026 ASSERT(comp->operation_cid() == kIllegalCid);
3027 } else {
3028 InsertBefore(current_instruction,
3029 new CheckEitherNonSmiInstr(comp->left()->Copy(),
3030 comp->right()->Copy(),
3031 comp->deopt_id()),
3032 current_instruction->env(),
3033 Definition::kEffect);
3034 comp->set_operation_cid(kDoubleCid);
3035 }
3036 }
3037 }
2997 3038
2998 if (comp->operation_cid() != kIllegalCid) { 3039 if (comp->operation_cid() != kIllegalCid) {
2999 // Done. 3040 // Done.
3000 return; 3041 return;
3001 } 3042 }
3002 3043
3003 const ICData& unary_checks_0 = 3044 const ICData& unary_checks_0 =
3004 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); 3045 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
3005 if (StrictifyEqualityCompareWithICData( 3046 if (StrictifyEqualityCompareWithICData(
3006 comp, unary_checks_0, current_instruction)) { 3047 comp, unary_checks_0, current_instruction)) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3038 3079
3039 3080
3040 3081
3041 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { 3082 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) {
3042 HandleEqualityCompare(instr, instr); 3083 HandleEqualityCompare(instr, instr);
3043 } 3084 }
3044 3085
3045 3086
3046 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { 3087 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) {
3047 ComparisonInstr* comparison = instr->comparison(); 3088 ComparisonInstr* comparison = instr->comparison();
3048 if (comparison->IsRelationalOp()) { 3089 if (comparison->IsEqualityCompare()) {
3049 HandleRelationalOp(comparison->AsRelationalOp());
3050 } else if (comparison->IsEqualityCompare()) {
3051 HandleEqualityCompare(comparison->AsEqualityCompare(), instr); 3090 HandleEqualityCompare(comparison->AsEqualityCompare(), instr);
3052 } else { 3091 } else {
3053 ASSERT(comparison->IsStrictCompare()); 3092 ASSERT(comparison->IsStrictCompare());
3054 // Nothing to do. 3093 // Nothing to do.
3055 } 3094 }
3056 } 3095 }
3057 3096
3058 3097
3059 static bool MayBeBoxableNumber(intptr_t cid) { 3098 static bool MayBeBoxableNumber(intptr_t cid) {
3060 return (cid == kDynamicCid) || 3099 return (cid == kDynamicCid) ||
(...skipping 3879 matching lines...) Expand 10 before | Expand all | Expand 10 after
6940 new_equality_compare->set_operation_cid(equality_compare->operation_cid()); 6979 new_equality_compare->set_operation_cid(equality_compare->operation_cid());
6941 new_comparison = new_equality_compare; 6980 new_comparison = new_equality_compare;
6942 } else { 6981 } else {
6943 ASSERT(comparison->IsRelationalOp()); 6982 ASSERT(comparison->IsRelationalOp());
6944 RelationalOpInstr* relational_op = comparison->AsRelationalOp(); 6983 RelationalOpInstr* relational_op = comparison->AsRelationalOp();
6945 RelationalOpInstr* new_relational_op = 6984 RelationalOpInstr* new_relational_op =
6946 new RelationalOpInstr(relational_op->token_pos(), 6985 new RelationalOpInstr(relational_op->token_pos(),
6947 comparison->kind(), 6986 comparison->kind(),
6948 left, 6987 left,
6949 right, 6988 right,
6950 Object::null_array()); 6989 relational_op->operation_cid(),
6951 new_relational_op->set_ic_data(relational_op->ic_data()); 6990 relational_op->deopt_id());
6952 new_relational_op->set_operation_cid(relational_op->operation_cid());
6953 new_comparison = new_relational_op; 6991 new_comparison = new_relational_op;
6954 } 6992 }
6955 return new BranchInstr(new_comparison, branch->is_checked()); 6993 return new BranchInstr(new_comparison, branch->is_checked());
6956 } 6994 }
6957 6995
6958 6996
6959 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { 6997 void BranchSimplifier::Simplify(FlowGraph* flow_graph) {
6960 // Optimize some branches that test the value of a phi. When it is safe 6998 // Optimize some branches that test the value of a phi. When it is safe
6961 // to do so, push the branch to each of the predecessor blocks. This is 6999 // to do so, push the branch to each of the predecessor blocks. This is
6962 // an optimization when (a) it can avoid materializing a boolean object at 7000 // an optimization when (a) it can avoid materializing a boolean object at
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
7475 } 7513 }
7476 7514
7477 // Insert materializations at environment uses. 7515 // Insert materializations at environment uses.
7478 for (intptr_t i = 0; i < exits.length(); i++) { 7516 for (intptr_t i = 0; i < exits.length(); i++) {
7479 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7517 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7480 } 7518 }
7481 } 7519 }
7482 7520
7483 7521
7484 } // namespace dart 7522 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698