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

Side by Side Diff: src/hydrogen-instructions.cc

Issue 10825071: Use integer division in a certain case. (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 8 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 | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-codegen-ia32.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 1095
1096 1096
1097 Range* HValue::InferRange(Zone* zone) { 1097 Range* HValue::InferRange(Zone* zone) {
1098 // Untagged integer32 cannot be -0, all other representations can. 1098 // Untagged integer32 cannot be -0, all other representations can.
1099 Range* result = new(zone) Range(); 1099 Range* result = new(zone) Range();
1100 result->set_can_be_minus_zero(!representation().IsInteger32()); 1100 result->set_can_be_minus_zero(!representation().IsInteger32());
1101 return result; 1101 return result;
1102 } 1102 }
1103 1103
1104 1104
1105 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
1106
1107 // Return an integer value or NULL, which may involve skipping over a
1108 // representation change
1109 static HValue* SimplifiedValueForIntDiv(HValue* value) {
1110 if (value->representation().IsInteger32()) {
1111 return value;
1112 } else if (value->IsConstant() &&
1113 HConstant::cast(value)->HasInteger32Value()) {
1114 return value;
1115 } else if (value->IsChange() &&
1116 HChange::cast(value)->from().IsInteger32()) {
1117 return HChange::cast(value)->value();
1118 }
1119 return NULL;
1120 }
1121
1122
1123 // Insert an integer constant into the graph when given a non-integer constant
1124 static HValue* EnsureIntegerConstantForIntDiv(HValue* value,
1125 HInstruction* insertBefore) {
1126 if (value->IsConstant() && !value->representation().IsInteger32()) {
1127 ASSERT(HConstant::cast(value)->HasInteger32Value());
1128 HConstant* constant = HConstant::cast(value)->CopyToRepresentation(
1129 Representation::Integer32(), insertBefore->block()->zone());
1130 constant->InsertBefore(insertBefore);
1131 return constant;
1132 }
1133 return value;
1134 }
1135
1136
1137 // Try to replace the division of a non-negative integer by a positive integer
1138 // that is then truncated to an integer with an integer division instruction.
1139 // This gives a 2x speedup over using double division. Return NULL on failure.
1140 static HDiv* MaybeConvertToIntDiv(HChange* change, Zone* zone) {
1141 if (change->value()->IsDiv() &&
1142 HDiv::cast(change->value())->UseCount() == 1 &&
1143 change->from().IsDouble() &&
1144 change->to().IsInteger32() &&
1145 change->CheckFlag(HValue::kTruncatingToInt32)) {
1146 HDiv* div = HDiv::cast(change->value());
1147 HValue* left = div->left();
1148 HValue* right = div->right();
1149 HValue* new_left = SimplifiedValueForIntDiv(left);
1150 HValue* new_right = SimplifiedValueForIntDiv(right);
1151
1152 // Only apply this optimization if we know it won't hit any special cases
1153 // that would otherwise cause a deopt in the representation change
1154 if (new_left != NULL && new_right != NULL &&
1155 new_left->range()->lower() >= 0 &&
1156 new_right->range()->lower() > 0) {
1157 // Change non-integer constants to integer constants
1158 new_left = EnsureIntegerConstantForIntDiv(new_left, div);
1159 new_right = EnsureIntegerConstantForIntDiv(new_right, div);
1160 ASSERT(new_left->representation().IsInteger32());
1161 ASSERT(new_right->representation().IsInteger32());
1162
1163 // Replace this representation change with an integer division
1164 HDiv* new_div = new(div->block()->zone()) HDiv(div->context(),
1165 new_left, new_right);
1166 new_div->AssumeRepresentation(Representation::Integer32());
1167 new_div->InsertBefore(div);
1168 change->DeleteAndReplaceWith(new_div);
1169
1170 // Delete unused instructions
1171 div->DeleteAndReplaceWith(NULL);
1172 if (left->HasNoUses()) left->DeleteAndReplaceWith(NULL);
1173 if (right->HasNoUses()) right->DeleteAndReplaceWith(NULL);
1174
1175 // Tell codegen not to emit code to check for a non-zero remainder.
1176 // Codegen can't use CheckUsesForFlag(kTruncatingToInt32) because
1177 // that flag is on the HChange instruction which is now deleted.
1178 new_div->SetFlag(HValue::kWillTruncateToInt32);
1179
1180 // Make sure all new values have ranges
1181 if (!new_left->HasRange()) new_left->ComputeInitialRange(zone);
1182 if (!new_right->HasRange()) new_right->ComputeInitialRange(zone);
1183 new_div->ComputeInitialRange(zone);
1184 return new_div;
1185 }
1186 }
1187 return NULL;
1188 }
1189
1190 #endif
1191
1192
1105 Range* HChange::InferRange(Zone* zone) { 1193 Range* HChange::InferRange(Zone* zone) {
1194 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
1195 HDiv* div = MaybeConvertToIntDiv(this, zone);
1196 if (div != NULL) {
1197 return div->range();
1198 }
1199 #endif
1200
1106 Range* input_range = value()->range(); 1201 Range* input_range = value()->range();
1107 if (from().IsInteger32() && 1202 if (from().IsInteger32() &&
1108 to().IsTagged() && 1203 to().IsTagged() &&
1109 input_range != NULL && input_range->IsInSmiRange()) { 1204 input_range != NULL && input_range->IsInSmiRange()) {
1110 set_type(HType::Smi()); 1205 set_type(HType::Smi());
1111 } 1206 }
1112 Range* result = (input_range != NULL) 1207 Range* result = (input_range != NULL)
1113 ? input_range->Copy(zone) 1208 ? input_range->Copy(zone)
1114 : HValue::InferRange(zone); 1209 : HValue::InferRange(zone);
1115 if (to().IsInteger32()) result->set_can_be_minus_zero(false); 1210 if (to().IsInteger32()) result->set_can_be_minus_zero(false);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 if (left()->range()->CanBeMinusZero()) { 1297 if (left()->range()->CanBeMinusZero()) {
1203 result->set_can_be_minus_zero(true); 1298 result->set_can_be_minus_zero(true);
1204 } 1299 }
1205 1300
1206 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) { 1301 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
1207 result->set_can_be_minus_zero(true); 1302 result->set_can_be_minus_zero(true);
1208 } 1303 }
1209 1304
1210 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) { 1305 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
1211 SetFlag(HValue::kCanOverflow); 1306 SetFlag(HValue::kCanOverflow);
1307 } else {
1308 ClearFlag(HValue::kCanOverflow);
1212 } 1309 }
1213 1310
1214 if (!right()->range()->CanBeZero()) { 1311 if (!right()->range()->CanBeZero()) {
1215 ClearFlag(HValue::kCanBeDivByZero); 1312 ClearFlag(HValue::kCanBeDivByZero);
1216 } 1313 }
1314
1315 // An exact range can be inferred for division with integer operands
1316 if (left()->representation().IsInteger32() &&
1317 right()->representation().IsInteger32() &&
1318 left()->range()->lower() >= 0 &&
1319 right()->range()->lower() > 0) {
1320 Range limits(left()->range()->lower() / right()->range()->upper(),
1321 left()->range()->upper() / right()->range()->lower());
1322 result->Intersect(&limits);
1323 }
1217 return result; 1324 return result;
1218 } else { 1325 } else {
1219 return HValue::InferRange(zone); 1326 return HValue::InferRange(zone);
1220 } 1327 }
1221 } 1328 }
1222 1329
1223 1330
1224 Range* HMod::InferRange(Zone* zone) { 1331 Range* HMod::InferRange(Zone* zone) {
1225 if (representation().IsInteger32()) { 1332 if (representation().IsInteger32()) {
1226 Range* a = left()->range(); 1333 Range* a = left()->range();
(...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 2691
2585 2692
2586 void HCheckPrototypeMaps::Verify() { 2693 void HCheckPrototypeMaps::Verify() {
2587 HInstruction::Verify(); 2694 HInstruction::Verify();
2588 ASSERT(HasNoUses()); 2695 ASSERT(HasNoUses());
2589 } 2696 }
2590 2697
2591 #endif 2698 #endif
2592 2699
2593 } } // namespace v8::internal 2700 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698