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

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 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 } 308 }
309 309
310 310
311 int HValue::UseCount() const { 311 int HValue::UseCount() const {
312 int count = 0; 312 int count = 0;
313 for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count; 313 for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
314 return count; 314 return count;
315 } 315 }
316 316
317 317
318 int HValue::UseCountIgnoringInputsRequiringNone() const {
319 int count = 0;
320 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
321 Representation req = it.value()->RequiredInputRepresentation(it.index());
322 if (!req.IsNone()) count++;
323 }
324 return count;
325 }
326
327
318 HUseListNode* HValue::RemoveUse(HValue* value, int index) { 328 HUseListNode* HValue::RemoveUse(HValue* value, int index) {
319 HUseListNode* previous = NULL; 329 HUseListNode* previous = NULL;
320 HUseListNode* current = use_list_; 330 HUseListNode* current = use_list_;
321 while (current != NULL) { 331 while (current != NULL) {
322 if (current->value() == value && current->index() == index) { 332 if (current->value() == value && current->index() == index) {
323 if (previous == NULL) { 333 if (previous == NULL) {
324 use_list_ = current->tail(); 334 use_list_ = current->tail();
325 } else { 335 } else {
326 previous->set_tail(current->tail()); 336 previous->set_tail(current->tail());
327 } 337 }
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 1105
1096 1106
1097 Range* HValue::InferRange(Zone* zone) { 1107 Range* HValue::InferRange(Zone* zone) {
1098 // Untagged integer32 cannot be -0, all other representations can. 1108 // Untagged integer32 cannot be -0, all other representations can.
1099 Range* result = new(zone) Range(); 1109 Range* result = new(zone) Range();
1100 result->set_can_be_minus_zero(!representation().IsInteger32()); 1110 result->set_can_be_minus_zero(!representation().IsInteger32());
1101 return result; 1111 return result;
1102 } 1112 }
1103 1113
1104 1114
1115 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
1116
1117 // Return an integer value or NULL, which may involve skipping over a
1118 // representation change
1119 static HValue* SimplifiedValueForIntDiv(HValue* value) {
1120 if (value->representation().IsInteger32()) {
1121 return value;
1122 } else if (value->IsConstant() &&
1123 HConstant::cast(value)->HasInteger32Value()) {
1124 return value;
1125 } else if (value->IsChange() &&
1126 HChange::cast(value)->from().IsInteger32()) {
1127 return HChange::cast(value)->value();
1128 }
1129 return NULL;
1130 }
1131
1132
1133 // Insert an integer constant into the graph when given a non-integer constant
1134 static HValue* EnsureIntegerConstantForIntDiv(HValue* value,
1135 HInstruction* insertBefore) {
1136 if (value->IsConstant() && !value->representation().IsInteger32()) {
1137 ASSERT(HConstant::cast(value)->HasInteger32Value());
1138 HConstant* constant = HConstant::cast(value)->CopyToRepresentation(
1139 Representation::Integer32(), insertBefore->block()->zone());
1140 constant->InsertBefore(insertBefore);
1141 return constant;
1142 }
1143 return value;
1144 }
1145
1146
1147 // Try to replace the division of a non-negative integer by a positive integer
1148 // that is then truncated to an integer with an integer division instruction.
1149 // This gives a 2x speedup over using double division. Return NULL on failure.
1150 static HDiv* MaybeConvertToIntDiv(HChange* change, Zone* zone) {
1151 if (change->value()->IsDiv() &&
Vyacheslav Egorov (Google) 2012/07/30 12:01:44 I am a little bit uncomfortable that we apply this
Evan Wallace 2012/07/30 16:43:13 These aren't the only conditions that trigger this
Vyacheslav Egorov (Google) 2012/07/30 16:59:26 I don't dispute that it can be truncated to int32.
Evan Wallace 2012/07/30 19:35:43 I did not realize normal double to integer represe
1152 change->from().IsDouble() &&
1153 change->to().IsInteger32()) {
1154 HDiv* div = HDiv::cast(change->value());
1155
1156 // We want to be sure that the use count is 1 for div so we can swap it
1157 // out, but there may be other instructions (such as HSimulate) that do
1158 // not need the resulting value and so shouldn't stop this optimization
1159 if (div->UseCountIgnoringInputsRequiringNone() == 1) {
Vyacheslav Egorov (Google) 2012/07/30 12:01:44 I am not sure that your approach to simulates is c
Evan Wallace 2012/07/30 16:43:13 Thanks for pointing this out! I guess I don't unde
Vyacheslav Egorov (Google) 2012/07/30 16:59:26 Simulate is a pseudo-instruction that "simulates"
1160 HValue* left = div->left();
1161 HValue* right = div->right();
1162 HValue* new_left = SimplifiedValueForIntDiv(left);
1163 HValue* new_right = SimplifiedValueForIntDiv(right);
1164
1165 // Only apply this optimization if we know it won't hit any special cases
1166 if (new_left != NULL && new_right != NULL &&
1167 new_left->range()->lower() >= 0 &&
1168 new_right->range()->lower() > 0) {
1169 // Change non-integer constants to integer constants
1170 new_left = EnsureIntegerConstantForIntDiv(new_left, div);
1171 new_right = EnsureIntegerConstantForIntDiv(new_right, div);
1172 ASSERT(new_left->representation().IsInteger32());
1173 ASSERT(new_right->representation().IsInteger32());
1174
1175 // Replace this representation change with an integer division
1176 HDiv* new_div = new(div->block()->zone()) HDiv(div->context(),
1177 new_left, new_right);
1178 new_div->AssumeRepresentation(Representation::Integer32());
1179 new_div->InsertBefore(div);
1180 change->DeleteAndReplaceWith(new_div);
1181
1182 // Delete unused instructions
1183 div->DeleteAndReplaceWith(new_div);
1184 if (left->HasNoUses()) left->DeleteAndReplaceWith(NULL);
1185 if (right->HasNoUses()) right->DeleteAndReplaceWith(NULL);
1186
1187 // Tell codegen not to emit code to check for a non-zero remainder.
1188 // Codegen can't use CheckUsesForFlag(kTruncatingToInt32) because
1189 // that flag is on the HChange instruction which is now deleted.
1190 new_div->SetFlag(HValue::kWillTruncateToInt32);
1191
1192 // Make sure all new values have ranges
1193 if (!new_left->HasRange()) new_left->ComputeInitialRange(zone);
1194 if (!new_right->HasRange()) new_right->ComputeInitialRange(zone);
1195 new_div->ComputeInitialRange(zone);
1196 return new_div;
1197 }
1198 }
1199 }
1200 return NULL;
1201 }
1202
1203 #endif
1204
1205
1105 Range* HChange::InferRange(Zone* zone) { 1206 Range* HChange::InferRange(Zone* zone) {
1207 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
1208 HDiv *div = MaybeConvertToIntDiv(this, zone);
1209 if (div != NULL) {
1210 return div->range();
1211 }
1212 #endif
1213
1106 Range* input_range = value()->range(); 1214 Range* input_range = value()->range();
1107 if (from().IsInteger32() && 1215 if (from().IsInteger32() &&
1108 to().IsTagged() && 1216 to().IsTagged() &&
1109 input_range != NULL && input_range->IsInSmiRange()) { 1217 input_range != NULL && input_range->IsInSmiRange()) {
1110 set_type(HType::Smi()); 1218 set_type(HType::Smi());
1111 } 1219 }
1112 Range* result = (input_range != NULL) 1220 Range* result = (input_range != NULL)
1113 ? input_range->Copy(zone) 1221 ? input_range->Copy(zone)
1114 : HValue::InferRange(zone); 1222 : HValue::InferRange(zone);
1115 if (to().IsInteger32()) result->set_can_be_minus_zero(false); 1223 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()) { 1310 if (left()->range()->CanBeMinusZero()) {
1203 result->set_can_be_minus_zero(true); 1311 result->set_can_be_minus_zero(true);
1204 } 1312 }
1205 1313
1206 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) { 1314 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
1207 result->set_can_be_minus_zero(true); 1315 result->set_can_be_minus_zero(true);
1208 } 1316 }
1209 1317
1210 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) { 1318 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
1211 SetFlag(HValue::kCanOverflow); 1319 SetFlag(HValue::kCanOverflow);
1320 } else {
1321 ClearFlag(HValue::kCanOverflow);
1212 } 1322 }
1213 1323
1214 if (!right()->range()->CanBeZero()) { 1324 if (!right()->range()->CanBeZero()) {
1215 ClearFlag(HValue::kCanBeDivByZero); 1325 ClearFlag(HValue::kCanBeDivByZero);
1216 } 1326 }
1327
1328 // An exact range can be inferred for division with integer operands
1329 if (left()->representation().IsInteger32() &&
1330 right()->representation().IsInteger32() &&
1331 left()->range()->lower() >= 0 &&
1332 right()->range()->lower() > 0) {
1333 Range limits(left()->range()->lower() / right()->range()->upper(),
1334 left()->range()->upper() / right()->range()->lower());
1335 result->Intersect(&limits);
1336 }
1217 return result; 1337 return result;
1218 } else { 1338 } else {
1219 return HValue::InferRange(zone); 1339 return HValue::InferRange(zone);
1220 } 1340 }
1221 } 1341 }
1222 1342
1223 1343
1224 Range* HMod::InferRange(Zone* zone) { 1344 Range* HMod::InferRange(Zone* zone) {
1225 if (representation().IsInteger32()) { 1345 if (representation().IsInteger32()) {
1226 Range* a = left()->range(); 1346 Range* a = left()->range();
(...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 2704
2585 2705
2586 void HCheckPrototypeMaps::Verify() { 2706 void HCheckPrototypeMaps::Verify() {
2587 HInstruction::Verify(); 2707 HInstruction::Verify();
2588 ASSERT(HasNoUses()); 2708 ASSERT(HasNoUses());
2589 } 2709 }
2590 2710
2591 #endif 2711 #endif
2592 2712
2593 } } // namespace v8::internal 2713 } } // 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