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

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

Issue 21013005: Optimize equuality operation for two Boolean arguments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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') | tests/language/equality_test.dart » ('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 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 if (ic_data.NumberOfChecks() == 1) { 585 if (ic_data.NumberOfChecks() == 1) {
586 return ic_data.HasReceiverClassId(kSmiCid) 586 return ic_data.HasReceiverClassId(kSmiCid)
587 || ic_data.HasReceiverClassId(kMintCid); 587 || ic_data.HasReceiverClassId(kMintCid);
588 } 588 }
589 return (ic_data.NumberOfChecks() == 2) 589 return (ic_data.NumberOfChecks() == 2)
590 && ic_data.HasReceiverClassId(kSmiCid) 590 && ic_data.HasReceiverClassId(kSmiCid)
591 && ic_data.HasReceiverClassId(kMintCid); 591 && ic_data.HasReceiverClassId(kMintCid);
592 } 592 }
593 593
594 594
595 static bool HasOnlyTwoSmis(const ICData& ic_data) { 595 static bool HasOnlyTwoOf(const ICData& ic_data, intptr_t cid) {
596 return (ic_data.NumberOfChecks() == 1) && 596 return (ic_data.NumberOfChecks() == 1) &&
597 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); 597 ICDataHasReceiverArgumentClassIds(ic_data, cid, cid);
598 }
599
600 static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) {
601 return (ic_data.NumberOfChecks() == 1) &&
602 ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid);
603 }
604
605 static bool HasOnlyTwoUint32x4s(const ICData& ic_data) {
606 return (ic_data.NumberOfChecks() == 1) &&
607 ICDataHasReceiverArgumentClassIds(ic_data, kUint32x4Cid, kUint32x4Cid);
608 } 598 }
609 599
610 // Returns false if the ICData contains anything other than the 4 combinations 600 // Returns false if the ICData contains anything other than the 4 combinations
611 // of Mint and Smi for the receiver and argument classes. 601 // of Mint and Smi for the receiver and argument classes.
612 static bool HasTwoMintOrSmi(const ICData& ic_data) { 602 static bool HasTwoMintOrSmi(const ICData& ic_data) {
613 GrowableArray<intptr_t> class_ids(2); 603 GrowableArray<intptr_t> class_ids(2);
614 class_ids.Add(kSmiCid); 604 class_ids.Add(kSmiCid);
615 class_ids.Add(kMintCid); 605 class_ids.Add(kMintCid);
616 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); 606 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids);
617 } 607 }
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 1013
1024 1014
1025 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, 1015 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
1026 Token::Kind op_kind) { 1016 Token::Kind op_kind) {
1027 intptr_t operands_type = kIllegalCid; 1017 intptr_t operands_type = kIllegalCid;
1028 ASSERT(call->HasICData()); 1018 ASSERT(call->HasICData());
1029 const ICData& ic_data = *call->ic_data(); 1019 const ICData& ic_data = *call->ic_data();
1030 switch (op_kind) { 1020 switch (op_kind) {
1031 case Token::kADD: 1021 case Token::kADD:
1032 case Token::kSUB: 1022 case Token::kSUB:
1033 if (HasOnlyTwoSmis(ic_data)) { 1023 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1034 // Don't generate smi code if the IC data is marked because 1024 // Don't generate smi code if the IC data is marked because
1035 // of an overflow. 1025 // of an overflow.
1036 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) 1026 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp)
1037 ? kMintCid 1027 ? kMintCid
1038 : kSmiCid; 1028 : kSmiCid;
1039 } else if (HasTwoMintOrSmi(ic_data) && 1029 } else if (HasTwoMintOrSmi(ic_data) &&
1040 FlowGraphCompiler::SupportsUnboxedMints()) { 1030 FlowGraphCompiler::SupportsUnboxedMints()) {
1041 // Don't generate mint code if the IC data is marked because of an 1031 // Don't generate mint code if the IC data is marked because of an
1042 // overflow. 1032 // overflow.
1043 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; 1033 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false;
1044 operands_type = kMintCid; 1034 operands_type = kMintCid;
1045 } else if (ShouldSpecializeForDouble(ic_data)) { 1035 } else if (ShouldSpecializeForDouble(ic_data)) {
1046 operands_type = kDoubleCid; 1036 operands_type = kDoubleCid;
1047 } else if (HasOnlyTwoFloat32x4s(ic_data)) { 1037 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
1048 operands_type = kFloat32x4Cid; 1038 operands_type = kFloat32x4Cid;
1049 } else { 1039 } else {
1050 return false; 1040 return false;
1051 } 1041 }
1052 break; 1042 break;
1053 case Token::kMUL: 1043 case Token::kMUL:
1054 if (HasOnlyTwoSmis(ic_data)) { 1044 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1055 // Don't generate smi code if the IC data is marked because of an 1045 // Don't generate smi code if the IC data is marked because of an
1056 // overflow. 1046 // overflow.
1057 // TODO(fschneider): Add unboxed mint multiplication. 1047 // TODO(fschneider): Add unboxed mint multiplication.
1058 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; 1048 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false;
1059 operands_type = kSmiCid; 1049 operands_type = kSmiCid;
1060 } else if (ShouldSpecializeForDouble(ic_data)) { 1050 } else if (ShouldSpecializeForDouble(ic_data)) {
1061 operands_type = kDoubleCid; 1051 operands_type = kDoubleCid;
1062 } else if (HasOnlyTwoFloat32x4s(ic_data)) { 1052 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
1063 operands_type = kFloat32x4Cid; 1053 operands_type = kFloat32x4Cid;
1064 } else { 1054 } else {
1065 return false; 1055 return false;
1066 } 1056 }
1067 break; 1057 break;
1068 case Token::kDIV: 1058 case Token::kDIV:
1069 if (ShouldSpecializeForDouble(ic_data) || HasOnlyTwoSmis(ic_data)) { 1059 if (ShouldSpecializeForDouble(ic_data) ||
1060 HasOnlyTwoOf(ic_data, kSmiCid)) {
1070 operands_type = kDoubleCid; 1061 operands_type = kDoubleCid;
1071 } else if (HasOnlyTwoFloat32x4s(ic_data)) { 1062 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
1072 operands_type = kFloat32x4Cid; 1063 operands_type = kFloat32x4Cid;
1073 } else { 1064 } else {
1074 return false; 1065 return false;
1075 } 1066 }
1076 break; 1067 break;
1077 case Token::kMOD: 1068 case Token::kMOD:
1078 if (HasOnlyTwoSmis(ic_data)) { 1069 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1079 operands_type = kSmiCid; 1070 operands_type = kSmiCid;
1080 } else { 1071 } else {
1081 return false; 1072 return false;
1082 } 1073 }
1083 break; 1074 break;
1084 case Token::kBIT_AND: 1075 case Token::kBIT_AND:
1085 case Token::kBIT_OR: 1076 case Token::kBIT_OR:
1086 case Token::kBIT_XOR: 1077 case Token::kBIT_XOR:
1087 if (HasOnlyTwoSmis(ic_data)) { 1078 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1088 operands_type = kSmiCid; 1079 operands_type = kSmiCid;
1089 } else if (HasTwoMintOrSmi(ic_data)) { 1080 } else if (HasTwoMintOrSmi(ic_data)) {
1090 operands_type = kMintCid; 1081 operands_type = kMintCid;
1091 } else if (HasOnlyTwoUint32x4s(ic_data)) { 1082 } else if (HasOnlyTwoOf(ic_data, kUint32x4Cid)) {
1092 operands_type = kUint32x4Cid; 1083 operands_type = kUint32x4Cid;
1093 } else { 1084 } else {
1094 return false; 1085 return false;
1095 } 1086 }
1096 break; 1087 break;
1097 case Token::kSHR: 1088 case Token::kSHR:
1098 case Token::kSHL: 1089 case Token::kSHL:
1099 if (HasOnlyTwoSmis(ic_data)) { 1090 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1100 // Left shift may overflow from smi into mint or big ints. 1091 // Left shift may overflow from smi into mint or big ints.
1101 // Don't generate smi code if the IC data is marked because 1092 // Don't generate smi code if the IC data is marked because
1102 // of an overflow. 1093 // of an overflow.
1103 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; 1094 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false;
1104 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) 1095 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp)
1105 ? kMintCid 1096 ? kMintCid
1106 : kSmiCid; 1097 : kSmiCid;
1107 } else if (HasTwoMintOrSmi(ic_data) && 1098 } else if (HasTwoMintOrSmi(ic_data) &&
1108 HasOnlyOneSmi(ICData::Handle( 1099 HasOnlyOneSmi(ICData::Handle(
1109 ic_data.AsUnaryClassChecksForArgNr(1)))) { 1100 ic_data.AsUnaryClassChecksForArgNr(1)))) {
1110 // Don't generate mint code if the IC data is marked because of an 1101 // Don't generate mint code if the IC data is marked because of an
1111 // overflow. 1102 // overflow.
1112 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; 1103 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false;
1113 // Check for smi/mint << smi or smi/mint >> smi. 1104 // Check for smi/mint << smi or smi/mint >> smi.
1114 operands_type = kMintCid; 1105 operands_type = kMintCid;
1115 } else { 1106 } else {
1116 return false; 1107 return false;
1117 } 1108 }
1118 break; 1109 break;
1119 case Token::kTRUNCDIV: 1110 case Token::kTRUNCDIV:
1120 if (HasOnlyTwoSmis(ic_data)) { 1111 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1121 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; 1112 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false;
1122 operands_type = kSmiCid; 1113 operands_type = kSmiCid;
1123 } else { 1114 } else {
1124 return false; 1115 return false;
1125 } 1116 }
1126 break; 1117 break;
1127 default: 1118 default:
1128 UNREACHABLE(); 1119 UNREACHABLE();
1129 } 1120 }
1130 1121
(...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after
2770 2761
2771 2762
2772 static bool SmiFitsInDouble() { return kSmiBits < 53; } 2763 static bool SmiFitsInDouble() { return kSmiBits < 53; }
2773 2764
2774 2765
2775 void FlowGraphOptimizer::HandleComparison(ComparisonInstr* comp, 2766 void FlowGraphOptimizer::HandleComparison(ComparisonInstr* comp,
2776 const ICData& ic_data, 2767 const ICData& ic_data,
2777 Instruction* current_instruction) { 2768 Instruction* current_instruction) {
2778 ASSERT(ic_data.num_args_tested() == 2); 2769 ASSERT(ic_data.num_args_tested() == 2);
2779 ASSERT(comp->operation_cid() == kIllegalCid); 2770 ASSERT(comp->operation_cid() == kIllegalCid);
2780 if (HasOnlyTwoSmis(ic_data)) { 2771 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
2781 InsertBefore(current_instruction, 2772 InsertBefore(current_instruction,
2782 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), 2773 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
2783 current_instruction->env(), 2774 current_instruction->env(),
2784 Definition::kEffect); 2775 Definition::kEffect);
2785 InsertBefore(current_instruction, 2776 InsertBefore(current_instruction,
2786 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), 2777 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
2787 current_instruction->env(), 2778 current_instruction->env(),
2788 Definition::kEffect); 2779 Definition::kEffect);
2789 comp->set_operation_cid(kSmiCid); 2780 comp->set_operation_cid(kSmiCid);
2790 } else if (HasTwoMintOrSmi(ic_data) && 2781 } else if (HasTwoMintOrSmi(ic_data) &&
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2884 strict_kind, 2875 strict_kind,
2885 compare->left()->CopyWithType(), 2876 compare->left()->CopyWithType(),
2886 compare->right()->CopyWithType()); 2877 compare->right()->CopyWithType());
2887 current_instruction->ReplaceWith(strict_comp, current_iterator()); 2878 current_instruction->ReplaceWith(strict_comp, current_iterator());
2888 return true; 2879 return true;
2889 } 2880 }
2890 return false; 2881 return false;
2891 } 2882 }
2892 2883
2893 2884
2885 // Returns true if we converted EqualityCompare to StrictCompare.
2886 template <typename T>
2887 bool FlowGraphOptimizer::StrictifyEqualityCompareWithICData(
2888 EqualityCompareInstr* compare,
2889 const ICData& unary_ic_data,
2890 T current_instruction) {
2891 ASSERT(unary_ic_data.num_args_tested() == 1);
2892 if (unary_ic_data.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
2893 // If possible classes do not override Object's equality then replace
2894 // with strict equality.
2895 Function& target = Function::Handle();
2896 Class& targets_class = Class::Handle();
2897 for (intptr_t i = 0; i < unary_ic_data.NumberOfChecks(); i++) {
2898 intptr_t cid = kIllegalCid;
2899 unary_ic_data.GetOneClassCheckAt(i, &cid, &target);
2900 targets_class = target.Owner();
2901 if (targets_class.id() != kInstanceCid) {
2902 // Overriden equality operator.
2903 return false;
2904 }
2905 }
2906 AddCheckClass(compare->left()->definition(),
2907 unary_ic_data,
2908 compare->deopt_id(),
2909 current_instruction->env(),
2910 current_instruction);
2911 ASSERT((compare->kind() == Token::kEQ) || (compare->kind() == Token::kNE));
2912 Token::Kind strict_kind = (compare->kind() == Token::kEQ) ?
2913 Token::kEQ_STRICT : Token::kNE_STRICT;
2914 StrictCompareInstr* strict_comp =
2915 new StrictCompareInstr(compare->token_pos(),
2916 strict_kind,
2917 compare->left()->Copy(),
2918 compare->right()->Copy());
2919 current_instruction->ReplaceWith(strict_comp, current_iterator());
2920 return true;
2921 }
2922 return false;
2923 }
2924
2925
2894 template <typename T> 2926 template <typename T>
2895 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp, 2927 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp,
2896 T current_instruction) { 2928 T current_instruction) {
2897 if (StrictifyEqualityCompare(comp, current_instruction)) { 2929 if (StrictifyEqualityCompare(comp, current_instruction)) {
2930 // Based on input types, equality converted to strict-equality.
2898 return; 2931 return;
2899 } 2932 }
2900 2933
2901 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { 2934 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) {
2902 return; 2935 return;
2903 } 2936 }
2904 2937
2905 const ICData& ic_data = *comp->ic_data(); 2938 const ICData& ic_data = *comp->ic_data();
2906 HandleComparison(comp, ic_data, current_instruction); 2939 HandleComparison(comp, ic_data, current_instruction);
2907 2940
2908 if (comp->operation_cid() != kIllegalCid) { 2941 if (comp->operation_cid() != kIllegalCid) {
2909 // Done. 2942 // Done.
2910 return; 2943 return;
2911 } 2944 }
2912 2945
2946 const ICData& unary_checks_0 =
2947 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
2948 if (StrictifyEqualityCompareWithICData(
2949 comp, unary_checks_0, current_instruction)) {
2950 // Based on ICData, equality converted to strict-equality.
2951 return;
2952 }
2953
2913 // Check if ICDData contains checks with Smi/Null combinations. In that case 2954 // Check if ICDData contains checks with Smi/Null combinations. In that case
2914 // we can still emit the optimized Smi equality operation but need to add 2955 // we can still emit the optimized Smi equality operation but need to add
2915 // checks for null or Smi. 2956 // checks for null or Smi.
2916 // TODO(srdjan): Add it for Double and Mint. 2957 // TODO(srdjan): Add it for Double and Mint.
2917 GrowableArray<intptr_t> smi_or_null(2); 2958 GrowableArray<intptr_t> smi_or_null(2);
2918 smi_or_null.Add(kSmiCid); 2959 smi_or_null.Add(kSmiCid);
2919 smi_or_null.Add(kNullCid); 2960 smi_or_null.Add(kNullCid);
2920 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data, 2961 if (ICDataHasOnlyReceiverArgumentClassIds(ic_data,
2921 smi_or_null, 2962 smi_or_null,
2922 smi_or_null)) { 2963 smi_or_null)) {
2923 const ICData& unary_checks_0 =
2924 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
2925 AddCheckClass(comp->left()->definition(), 2964 AddCheckClass(comp->left()->definition(),
2926 unary_checks_0, 2965 unary_checks_0,
2927 comp->deopt_id(), 2966 comp->deopt_id(),
2928 current_instruction->env(), 2967 current_instruction->env(),
2929 current_instruction); 2968 current_instruction);
2930 2969
2931 const ICData& unary_checks_1 = 2970 const ICData& unary_checks_1 =
2932 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecksForArgNr(1)); 2971 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecksForArgNr(1));
2933 AddCheckClass(comp->right()->definition(), 2972 AddCheckClass(comp->right()->definition(),
2934 unary_checks_1, 2973 unary_checks_1,
(...skipping 4431 matching lines...) Expand 10 before | Expand all | Expand 10 after
7366 7405
7367 // Insert materializations at environment uses. 7406 // Insert materializations at environment uses.
7368 const Class& cls = Class::Handle(alloc->constructor().Owner()); 7407 const Class& cls = Class::Handle(alloc->constructor().Owner());
7369 for (intptr_t i = 0; i < exits.length(); i++) { 7408 for (intptr_t i = 0; i < exits.length(); i++) {
7370 CreateMaterializationAt(exits[i], alloc, cls, *fields); 7409 CreateMaterializationAt(exits[i], alloc, cls, *fields);
7371 } 7410 }
7372 } 7411 }
7373 7412
7374 7413
7375 } // namespace dart 7414 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | tests/language/equality_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698