| 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 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |