Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |