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 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 } | 1137 } |
1138 __ b(&done); | 1138 __ b(&done); |
1139 } | 1139 } |
1140 | 1140 |
1141 __ bind(÷nd_is_not_negative); | 1141 __ bind(÷nd_is_not_negative); |
1142 __ and_(dividend, dividend, Operand(mask)); | 1142 __ and_(dividend, dividend, Operand(mask)); |
1143 __ bind(&done); | 1143 __ bind(&done); |
1144 } | 1144 } |
1145 | 1145 |
1146 | 1146 |
1147 void LCodeGen::DoModByConstI(LModByConstI* instr) { | |
1148 Register dividend = ToRegister(instr->dividend()); | |
1149 int32_t divisor = instr->divisor(); | |
1150 Register result = ToRegister(instr->result()); | |
1151 ASSERT(!dividend.is(result)); | |
1152 | |
1153 if (divisor == 0) { | |
1154 DeoptimizeIf(al, instr->environment()); | |
1155 return; | |
1156 } | |
1157 | |
1158 __ FlooringDiv(result, dividend, Abs(divisor)); | |
1159 __ mov(ip, Operand(Abs(divisor))); | |
1160 __ smull(result, ip, result, ip); | |
1161 __ sub(result, dividend, result, SetCC); | |
1162 | |
1163 // Check for negative zero. | |
1164 HMod* hmod = instr->hydrogen(); | |
1165 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) && | |
1166 hmod->left()->CanBeNegative()) { | |
1167 Label remainder_not_zero; | |
1168 __ b(ne, &remainder_not_zero); | |
1169 __ cmp(dividend, Operand::Zero()); | |
1170 DeoptimizeIf(lt, instr->environment()); | |
1171 __ bind(&remainder_not_zero); | |
1172 } | |
1173 } | |
1174 | |
1175 | |
1176 void LCodeGen::DoModI(LModI* instr) { | 1147 void LCodeGen::DoModI(LModI* instr) { |
1177 HMod* hmod = instr->hydrogen(); | 1148 HMod* hmod = instr->hydrogen(); |
1178 HValue* left = hmod->left(); | 1149 HValue* left = hmod->left(); |
1179 HValue* right = hmod->right(); | 1150 HValue* right = hmod->right(); |
1180 if (CpuFeatures::IsSupported(SUDIV)) { | 1151 if (CpuFeatures::IsSupported(SUDIV)) { |
1181 CpuFeatureScope scope(masm(), SUDIV); | 1152 CpuFeatureScope scope(masm(), SUDIV); |
1182 | 1153 |
1183 Register left_reg = ToRegister(instr->left()); | 1154 Register left_reg = ToRegister(instr->left()); |
1184 Register right_reg = ToRegister(instr->right()); | 1155 Register right_reg = ToRegister(instr->right()); |
1185 Register result_reg = ToRegister(instr->result()); | 1156 Register result_reg = ToRegister(instr->result()); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1251 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1281 __ b(ne, &done); | 1252 __ b(ne, &done); |
1282 __ cmp(left_reg, Operand::Zero()); | 1253 __ cmp(left_reg, Operand::Zero()); |
1283 DeoptimizeIf(mi, instr->environment()); | 1254 DeoptimizeIf(mi, instr->environment()); |
1284 } | 1255 } |
1285 __ bind(&done); | 1256 __ bind(&done); |
1286 } | 1257 } |
1287 } | 1258 } |
1288 | 1259 |
1289 | 1260 |
| 1261 void LCodeGen::EmitSignedIntegerDivisionByConstant( |
| 1262 Register result, |
| 1263 Register dividend, |
| 1264 int32_t divisor, |
| 1265 Register remainder, |
| 1266 Register scratch, |
| 1267 LEnvironment* environment) { |
| 1268 ASSERT(!AreAliased(dividend, scratch, ip)); |
| 1269 ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor)); |
| 1270 |
| 1271 uint32_t divisor_abs = abs(divisor); |
| 1272 |
| 1273 int32_t power_of_2_factor = |
| 1274 CompilerIntrinsics::CountTrailingZeros(divisor_abs); |
| 1275 |
| 1276 switch (divisor_abs) { |
| 1277 case 0: |
| 1278 DeoptimizeIf(al, environment); |
| 1279 return; |
| 1280 |
| 1281 case 1: |
| 1282 if (divisor > 0) { |
| 1283 __ Move(result, dividend); |
| 1284 } else { |
| 1285 __ rsb(result, dividend, Operand::Zero(), SetCC); |
| 1286 DeoptimizeIf(vs, environment); |
| 1287 } |
| 1288 // Compute the remainder. |
| 1289 __ mov(remainder, Operand::Zero()); |
| 1290 return; |
| 1291 |
| 1292 default: |
| 1293 if (IsPowerOf2(divisor_abs)) { |
| 1294 // Branch and condition free code for integer division by a power |
| 1295 // of two. |
| 1296 int32_t power = WhichPowerOf2(divisor_abs); |
| 1297 if (power > 1) { |
| 1298 __ mov(scratch, Operand(dividend, ASR, power - 1)); |
| 1299 } |
| 1300 __ add(scratch, dividend, Operand(scratch, LSR, 32 - power)); |
| 1301 __ mov(result, Operand(scratch, ASR, power)); |
| 1302 // Negate if necessary. |
| 1303 // We don't need to check for overflow because the case '-1' is |
| 1304 // handled separately. |
| 1305 if (divisor < 0) { |
| 1306 ASSERT(divisor != -1); |
| 1307 __ rsb(result, result, Operand::Zero()); |
| 1308 } |
| 1309 // Compute the remainder. |
| 1310 if (divisor > 0) { |
| 1311 __ sub(remainder, dividend, Operand(result, LSL, power)); |
| 1312 } else { |
| 1313 __ add(remainder, dividend, Operand(result, LSL, power)); |
| 1314 } |
| 1315 return; |
| 1316 } else { |
| 1317 // Use magic numbers for a few specific divisors. |
| 1318 // Details and proofs can be found in: |
| 1319 // - Hacker's Delight, Henry S. Warren, Jr. |
| 1320 // - The PowerPC Compiler Writer’s Guide |
| 1321 // and probably many others. |
| 1322 // |
| 1323 // We handle |
| 1324 // <divisor with magic numbers> * <power of 2> |
| 1325 // but not |
| 1326 // <divisor with magic numbers> * <other divisor with magic numbers> |
| 1327 DivMagicNumbers magic_numbers = |
| 1328 DivMagicNumberFor(divisor_abs >> power_of_2_factor); |
| 1329 // Branch and condition free code for integer division by a power |
| 1330 // of two. |
| 1331 const int32_t M = magic_numbers.M; |
| 1332 const int32_t s = magic_numbers.s + power_of_2_factor; |
| 1333 |
| 1334 __ mov(ip, Operand(M)); |
| 1335 __ smull(ip, scratch, dividend, ip); |
| 1336 if (M < 0) { |
| 1337 __ add(scratch, scratch, Operand(dividend)); |
| 1338 } |
| 1339 if (s > 0) { |
| 1340 __ mov(scratch, Operand(scratch, ASR, s)); |
| 1341 } |
| 1342 __ add(result, scratch, Operand(dividend, LSR, 31)); |
| 1343 if (divisor < 0) __ rsb(result, result, Operand::Zero()); |
| 1344 // Compute the remainder. |
| 1345 __ mov(ip, Operand(divisor)); |
| 1346 // This sequence could be replaced with 'mls' when |
| 1347 // it gets implemented. |
| 1348 __ mul(scratch, result, ip); |
| 1349 __ sub(remainder, dividend, scratch); |
| 1350 } |
| 1351 } |
| 1352 } |
| 1353 |
| 1354 |
1290 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1355 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
1291 Register dividend = ToRegister(instr->dividend()); | 1356 Register dividend = ToRegister(instr->dividend()); |
1292 int32_t divisor = instr->divisor(); | 1357 int32_t divisor = instr->divisor(); |
1293 Register result = ToRegister(instr->result()); | 1358 Register result = ToRegister(instr->result()); |
1294 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); | 1359 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); |
1295 ASSERT(!result.is(dividend)); | 1360 ASSERT(!result.is(dividend)); |
1296 | 1361 |
1297 // Check for (0 / -x) that will produce negative zero. | 1362 // Check for (0 / -x) that will produce negative zero. |
1298 HDiv* hdiv = instr->hydrogen(); | 1363 HDiv* hdiv = instr->hydrogen(); |
1299 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1364 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && |
(...skipping 26 matching lines...) Expand all Loading... |
1326 __ add(result, dividend, Operand(dividend, LSR, 31)); | 1391 __ add(result, dividend, Operand(dividend, LSR, 31)); |
1327 } else { | 1392 } else { |
1328 __ mov(result, Operand(dividend, ASR, 31)); | 1393 __ mov(result, Operand(dividend, ASR, 31)); |
1329 __ add(result, dividend, Operand(result, LSR, 32 - shift)); | 1394 __ add(result, dividend, Operand(result, LSR, 32 - shift)); |
1330 } | 1395 } |
1331 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); | 1396 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); |
1332 if (divisor < 0) __ rsb(result, result, Operand(0)); | 1397 if (divisor < 0) __ rsb(result, result, Operand(0)); |
1333 } | 1398 } |
1334 | 1399 |
1335 | 1400 |
1336 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | |
1337 Register dividend = ToRegister(instr->dividend()); | |
1338 int32_t divisor = instr->divisor(); | |
1339 Register result = ToRegister(instr->result()); | |
1340 ASSERT(!dividend.is(result)); | |
1341 | |
1342 if (divisor == 0) { | |
1343 DeoptimizeIf(al, instr->environment()); | |
1344 return; | |
1345 } | |
1346 | |
1347 // Check for (0 / -x) that will produce negative zero. | |
1348 HDiv* hdiv = instr->hydrogen(); | |
1349 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | |
1350 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
1351 __ cmp(dividend, Operand::Zero()); | |
1352 DeoptimizeIf(eq, instr->environment()); | |
1353 } | |
1354 | |
1355 __ FlooringDiv(result, dividend, Abs(divisor)); | |
1356 if (divisor < 0) __ rsb(result, result, Operand::Zero()); | |
1357 | |
1358 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | |
1359 __ mov(ip, Operand(divisor)); | |
1360 __ smull(scratch0(), ip, result, ip); | |
1361 __ sub(scratch0(), scratch0(), dividend, SetCC); | |
1362 DeoptimizeIf(ne, instr->environment()); | |
1363 } | |
1364 } | |
1365 | |
1366 | |
1367 void LCodeGen::DoDivI(LDivI* instr) { | 1401 void LCodeGen::DoDivI(LDivI* instr) { |
1368 const Register left = ToRegister(instr->left()); | 1402 const Register left = ToRegister(instr->left()); |
1369 const Register right = ToRegister(instr->right()); | 1403 const Register right = ToRegister(instr->right()); |
1370 const Register result = ToRegister(instr->result()); | 1404 const Register result = ToRegister(instr->result()); |
1371 | 1405 |
1372 // Check for x / 0. | 1406 // Check for x / 0. |
1373 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 1407 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { |
1374 __ cmp(right, Operand::Zero()); | 1408 __ cmp(right, Operand::Zero()); |
1375 DeoptimizeIf(eq, instr->environment()); | 1409 DeoptimizeIf(eq, instr->environment()); |
1376 } | 1410 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1490 __ b(&done); | 1524 __ b(&done); |
1491 } | 1525 } |
1492 } | 1526 } |
1493 __ bind(¬_kmin_int); | 1527 __ bind(¬_kmin_int); |
1494 __ mov(dividend, Operand(dividend, ASR, shift)); | 1528 __ mov(dividend, Operand(dividend, ASR, shift)); |
1495 __ bind(&done); | 1529 __ bind(&done); |
1496 } | 1530 } |
1497 | 1531 |
1498 | 1532 |
1499 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1533 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
1500 Register dividend = ToRegister(instr->dividend()); | 1534 Register left = ToRegister(instr->dividend()); |
1501 int32_t divisor = instr->divisor(); | 1535 Register remainder = ToRegister(instr->temp()); |
| 1536 Register scratch = scratch0(); |
1502 Register result = ToRegister(instr->result()); | 1537 Register result = ToRegister(instr->result()); |
1503 ASSERT(!dividend.is(result)); | |
1504 | 1538 |
1505 if (divisor == 0) { | 1539 if (!CpuFeatures::IsSupported(SUDIV)) { |
1506 DeoptimizeIf(al, instr->environment()); | 1540 // If the CPU doesn't support sdiv instruction, we only optimize when we |
1507 return; | 1541 // have magic numbers for the divisor. The standard integer division routine |
| 1542 // is usually slower than transitionning to VFP. |
| 1543 ASSERT(instr->divisor()->IsConstantOperand()); |
| 1544 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->divisor())); |
| 1545 ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor)); |
| 1546 if (divisor < 0) { |
| 1547 __ cmp(left, Operand::Zero()); |
| 1548 DeoptimizeIf(eq, instr->environment()); |
| 1549 } |
| 1550 EmitSignedIntegerDivisionByConstant(result, |
| 1551 left, |
| 1552 divisor, |
| 1553 remainder, |
| 1554 scratch, |
| 1555 instr->environment()); |
| 1556 // We performed a truncating division. Correct the result if necessary. |
| 1557 __ cmp(remainder, Operand::Zero()); |
| 1558 __ teq(remainder, Operand(divisor), ne); |
| 1559 __ sub(result, result, Operand(1), LeaveCC, mi); |
| 1560 } else { |
| 1561 CpuFeatureScope scope(masm(), SUDIV); |
| 1562 // TODO(svenpanne) We *statically* know the divisor, use that fact! |
| 1563 Register right = ToRegister(instr->divisor()); |
| 1564 |
| 1565 // Check for x / 0. |
| 1566 __ cmp(right, Operand::Zero()); |
| 1567 DeoptimizeIf(eq, instr->environment()); |
| 1568 |
| 1569 // Check for (kMinInt / -1). |
| 1570 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1571 __ cmp(left, Operand(kMinInt)); |
| 1572 __ cmp(right, Operand(-1), eq); |
| 1573 DeoptimizeIf(eq, instr->environment()); |
| 1574 } |
| 1575 |
| 1576 // Check for (0 / -x) that will produce negative zero. |
| 1577 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1578 __ cmp(right, Operand::Zero()); |
| 1579 __ cmp(left, Operand::Zero(), mi); |
| 1580 // "right" can't be null because the code would have already been |
| 1581 // deoptimized. The Z flag is set only if (right < 0) and (left == 0). |
| 1582 // In this case we need to deoptimize to produce a -0. |
| 1583 DeoptimizeIf(eq, instr->environment()); |
| 1584 } |
| 1585 |
| 1586 Label done; |
| 1587 __ sdiv(result, left, right); |
| 1588 // If both operands have the same sign then we are done. |
| 1589 __ eor(remainder, left, Operand(right), SetCC); |
| 1590 __ b(pl, &done); |
| 1591 |
| 1592 // Check if the result needs to be corrected. |
| 1593 __ mls(remainder, result, right, left); |
| 1594 __ cmp(remainder, Operand::Zero()); |
| 1595 __ sub(result, result, Operand(1), LeaveCC, ne); |
| 1596 |
| 1597 __ bind(&done); |
1508 } | 1598 } |
1509 | |
1510 // Check for (0 / -x) that will produce negative zero. | |
1511 HMathFloorOfDiv* hdiv = instr->hydrogen(); | |
1512 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | |
1513 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
1514 __ cmp(dividend, Operand::Zero()); | |
1515 DeoptimizeIf(eq, instr->environment()); | |
1516 } | |
1517 | |
1518 __ FlooringDiv(result, dividend, divisor); | |
1519 } | 1599 } |
1520 | 1600 |
1521 | 1601 |
1522 void LCodeGen::DoMulI(LMulI* instr) { | 1602 void LCodeGen::DoMulI(LMulI* instr) { |
1523 Register result = ToRegister(instr->result()); | 1603 Register result = ToRegister(instr->result()); |
1524 // Note that result may alias left. | 1604 // Note that result may alias left. |
1525 Register left = ToRegister(instr->left()); | 1605 Register left = ToRegister(instr->left()); |
1526 LOperand* right_op = instr->right(); | 1606 LOperand* right_op = instr->right(); |
1527 | 1607 |
1528 bool bailout_on_minus_zero = | 1608 bool bailout_on_minus_zero = |
(...skipping 4193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5722 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5802 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5723 __ ldr(result, FieldMemOperand(scratch, | 5803 __ ldr(result, FieldMemOperand(scratch, |
5724 FixedArray::kHeaderSize - kPointerSize)); | 5804 FixedArray::kHeaderSize - kPointerSize)); |
5725 __ bind(&done); | 5805 __ bind(&done); |
5726 } | 5806 } |
5727 | 5807 |
5728 | 5808 |
5729 #undef __ | 5809 #undef __ |
5730 | 5810 |
5731 } } // namespace v8::internal | 5811 } } // namespace v8::internal |
OLD | NEW |