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 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1237 | 1237 |
1238 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1238 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1239 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1239 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1240 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1240 return DefineAsRegister(new(zone()) LBitI(left, right)); |
1241 } else { | 1241 } else { |
1242 return DoArithmeticT(instr->op(), instr); | 1242 return DoArithmeticT(instr->op(), instr); |
1243 } | 1243 } |
1244 } | 1244 } |
1245 | 1245 |
1246 | 1246 |
| 1247 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
| 1248 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1249 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1250 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1251 LOperand* dividend = UseRegister(instr->left()); |
| 1252 LOperand* divisor = UseRegister(instr->right()); |
| 1253 LDivI* div = new(zone()) LDivI(dividend, divisor); |
| 1254 return AssignEnvironment(DefineAsRegister(div)); |
| 1255 } |
| 1256 |
| 1257 |
1247 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1258 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1248 if (instr->representation().IsSmiOrInteger32()) { | 1259 if (instr->representation().IsSmiOrInteger32()) { |
1249 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1260 return DoDivI(instr); |
1250 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
1251 LOperand* dividend = UseRegister(instr->left()); | |
1252 LOperand* divisor = UseRegister(instr->right()); | |
1253 LDivI* div = new(zone()) LDivI(dividend, divisor); | |
1254 return AssignEnvironment(DefineAsRegister(div)); | |
1255 } else if (instr->representation().IsDouble()) { | 1261 } else if (instr->representation().IsDouble()) { |
1256 return DoArithmeticD(Token::DIV, instr); | 1262 return DoArithmeticD(Token::DIV, instr); |
1257 } else { | 1263 } else { |
1258 return DoArithmeticT(Token::DIV, instr); | 1264 return DoArithmeticT(Token::DIV, instr); |
1259 } | 1265 } |
1260 } | 1266 } |
1261 | 1267 |
1262 | 1268 |
1263 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1269 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
1264 uint32_t divisor_abs = abs(divisor); | 1270 uint32_t divisor_abs = abs(divisor); |
1265 // Dividing by 0, 1, and powers of 2 is easy. | 1271 // Dividing by 0 or powers of 2 is easy. |
1266 // Note that IsPowerOf2(0) returns true; | 1272 if (divisor == 0 || IsPowerOf2(divisor_abs)) return true; |
1267 ASSERT(IsPowerOf2(0) == true); | |
1268 if (IsPowerOf2(divisor_abs)) return true; | |
1269 | 1273 |
1270 // We have magic numbers for a few specific divisors. | 1274 // We have magic numbers for a few specific divisors. |
1271 // Details and proofs can be found in: | 1275 // Details and proofs can be found in: |
1272 // - Hacker's Delight, Henry S. Warren, Jr. | 1276 // - Hacker's Delight, Henry S. Warren, Jr. |
1273 // - The PowerPC Compiler Writer's Guide | 1277 // - The PowerPC Compiler Writer's Guide |
1274 // and probably many others. | 1278 // and probably many others. |
1275 // | 1279 // |
1276 // We handle | 1280 // We handle |
1277 // <divisor with magic numbers> * <power of 2> | 1281 // <divisor with magic numbers> * <power of 2> |
1278 // but not | 1282 // but not |
1279 // <divisor with magic numbers> * <other divisor with magic numbers> | 1283 // <divisor with magic numbers> * <other divisor with magic numbers> |
1280 int32_t power_of_2_factor = | 1284 int32_t power_of_2_factor = |
1281 CompilerIntrinsics::CountTrailingZeros(divisor_abs); | 1285 CompilerIntrinsics::CountTrailingZeros(divisor_abs); |
1282 DivMagicNumbers magic_numbers = | 1286 DivMagicNumbers magic_numbers = |
1283 DivMagicNumberFor(divisor_abs >> power_of_2_factor); | 1287 DivMagicNumberFor(divisor_abs >> power_of_2_factor); |
1284 if (magic_numbers.M != InvalidDivMagicNumber.M) return true; | 1288 return magic_numbers.M != InvalidDivMagicNumber.M; |
| 1289 } |
1285 | 1290 |
1286 return false; | 1291 |
| 1292 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { |
| 1293 LOperand* dividend = UseRegister(instr->left()); |
| 1294 LOperand* divisor = UseOrConstant(instr->right()); |
| 1295 LOperand* remainder = TempRegister(); |
| 1296 LInstruction* result = |
| 1297 DefineAsRegister( |
| 1298 new(zone()) LFlooringDivByConstI(dividend, divisor, remainder)); |
| 1299 return AssignEnvironment(result); |
1287 } | 1300 } |
1288 | 1301 |
1289 | 1302 |
1290 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1303 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1304 if (instr->right()->IsConstant()) { |
| 1305 return DoFlooringDivByConstI(instr); |
| 1306 } else { |
1291 HValue* right = instr->right(); | 1307 HValue* right = instr->right(); |
1292 LOperand* dividend = UseRegister(instr->left()); | 1308 LOperand* dividend = UseRegister(instr->left()); |
1293 LOperand* divisor = UseRegisterOrConstant(right); | 1309 LOperand* divisor = UseRegisterOrConstant(right); |
1294 LOperand* remainder = TempRegister(); | 1310 LOperand* remainder = TempRegister(); |
1295 return AssignEnvironment(DefineAsRegister( | 1311 return AssignEnvironment(DefineAsRegister( |
1296 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); | 1312 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); |
| 1313 } |
| 1314 } |
| 1315 |
| 1316 |
| 1317 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
| 1318 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1319 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1320 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1321 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1322 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1323 LInstruction* result = |
| 1324 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor)); |
| 1325 bool can_deopt = |
| 1326 instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1327 instr->left()->CanBeNegative(); |
| 1328 return can_deopt ? AssignEnvironment(result) : result; |
| 1329 } |
| 1330 |
| 1331 |
| 1332 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
| 1333 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1334 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1335 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1336 LOperand* dividend = UseRegister(instr->left()); |
| 1337 LOperand* divisor = UseRegister(instr->right()); |
| 1338 LModI* mod = new(zone()) LModI(dividend, |
| 1339 divisor); |
| 1340 LInstruction* result = DefineAsRegister(mod); |
| 1341 bool can_deopt = (instr->right()->CanBeZero() || |
| 1342 (instr->left()->RangeCanInclude(kMinInt) && |
| 1343 instr->right()->RangeCanInclude(-1) && |
| 1344 instr->CheckFlag(HValue::kBailoutOnMinusZero)) || |
| 1345 (instr->left()->CanBeNegative() && |
| 1346 instr->CanBeZero() && |
| 1347 instr->CheckFlag(HValue::kBailoutOnMinusZero))); |
| 1348 return can_deopt ? AssignEnvironment(result) : result; |
1297 } | 1349 } |
1298 | 1350 |
1299 | 1351 |
1300 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1352 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
1301 HValue* left = instr->left(); | |
1302 HValue* right = instr->right(); | |
1303 if (instr->representation().IsSmiOrInteger32()) { | 1353 if (instr->representation().IsSmiOrInteger32()) { |
1304 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1354 return instr->RightIsPowerOf2() ? DoModByPowerOf2I(instr) : DoModI(instr); |
1305 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
1306 if (instr->RightIsPowerOf2()) { | |
1307 ASSERT(!right->CanBeZero()); | |
1308 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | |
1309 UseConstant(right)); | |
1310 LInstruction* result = DefineAsRegister(mod); | |
1311 return (left->CanBeNegative() && | |
1312 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | |
1313 ? AssignEnvironment(result) | |
1314 : result; | |
1315 } else { | |
1316 LModI* mod = new(zone()) LModI(UseRegister(left), | |
1317 UseRegister(right), | |
1318 TempRegister(), | |
1319 FixedTemp(f20), | |
1320 FixedTemp(f22)); | |
1321 LInstruction* result = DefineAsRegister(mod); | |
1322 return (right->CanBeZero() || | |
1323 (left->RangeCanInclude(kMinInt) && | |
1324 right->RangeCanInclude(-1)) || | |
1325 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | |
1326 ? AssignEnvironment(result) | |
1327 : result; | |
1328 } | |
1329 } else if (instr->representation().IsDouble()) { | 1355 } else if (instr->representation().IsDouble()) { |
1330 return DoArithmeticD(Token::MOD, instr); | 1356 return DoArithmeticD(Token::MOD, instr); |
1331 } else { | 1357 } else { |
1332 return DoArithmeticT(Token::MOD, instr); | 1358 return DoArithmeticT(Token::MOD, instr); |
1333 } | 1359 } |
1334 } | 1360 } |
1335 | 1361 |
1336 | 1362 |
1337 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1363 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1338 if (instr->representation().IsSmiOrInteger32()) { | 1364 if (instr->representation().IsSmiOrInteger32()) { |
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2407 | 2433 |
2408 | 2434 |
2409 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2435 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2410 LOperand* object = UseRegister(instr->object()); | 2436 LOperand* object = UseRegister(instr->object()); |
2411 LOperand* index = UseRegister(instr->index()); | 2437 LOperand* index = UseRegister(instr->index()); |
2412 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2438 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
2413 } | 2439 } |
2414 | 2440 |
2415 | 2441 |
2416 } } // namespace v8::internal | 2442 } } // namespace v8::internal |
OLD | NEW |