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 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1361 UNREACHABLE(); | 1361 UNREACHABLE(); |
1362 } | 1362 } |
1363 } | 1363 } |
1364 | 1364 |
1365 | 1365 |
1366 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1366 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
1367 GenerateOsrPrologue(); | 1367 GenerateOsrPrologue(); |
1368 } | 1368 } |
1369 | 1369 |
1370 | 1370 |
| 1371 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { |
| 1372 Register dividend = ToRegister(instr->dividend()); |
| 1373 int32_t divisor = instr->divisor(); |
| 1374 ASSERT(dividend.is(ToRegister(instr->result()))); |
| 1375 |
| 1376 // Theoretically, a variation of the branch-free code for integer division by |
| 1377 // a power of 2 (calculating the remainder via an additional multiplication |
| 1378 // (which gets simplified to an 'and') and subtraction) should be faster, and |
| 1379 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to |
| 1380 // indicate that positive dividends are heavily favored, so the branching |
| 1381 // version performs better. |
| 1382 HMod* hmod = instr->hydrogen(); |
| 1383 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1384 Label dividend_is_not_negative, done; |
| 1385 if (hmod->left()->CanBeNegative()) { |
| 1386 __ test(dividend, dividend); |
| 1387 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); |
| 1388 // Note that this is correct even for kMinInt operands. |
| 1389 __ neg(dividend); |
| 1390 __ and_(dividend, mask); |
| 1391 __ neg(dividend); |
| 1392 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1393 DeoptimizeIf(zero, instr->environment()); |
| 1394 } |
| 1395 __ jmp(&done, Label::kNear); |
| 1396 } |
| 1397 |
| 1398 __ bind(÷nd_is_not_negative); |
| 1399 __ and_(dividend, mask); |
| 1400 __ bind(&done); |
| 1401 } |
| 1402 |
| 1403 |
1371 void LCodeGen::DoModI(LModI* instr) { | 1404 void LCodeGen::DoModI(LModI* instr) { |
1372 HMod* hmod = instr->hydrogen(); | 1405 HMod* hmod = instr->hydrogen(); |
1373 HValue* left = hmod->left(); | 1406 HValue* left = hmod->left(); |
1374 HValue* right = hmod->right(); | 1407 HValue* right = hmod->right(); |
1375 if (hmod->RightIsPowerOf2()) { | 1408 |
1376 // TODO(svenpanne) We should really do the strength reduction on the | 1409 Register left_reg = ToRegister(instr->left()); |
1377 // Hydrogen level. | 1410 ASSERT(left_reg.is(eax)); |
1378 Register left_reg = ToRegister(instr->left()); | 1411 Register right_reg = ToRegister(instr->right()); |
1379 ASSERT(left_reg.is(ToRegister(instr->result()))); | 1412 ASSERT(!right_reg.is(eax)); |
1380 | 1413 ASSERT(!right_reg.is(edx)); |
1381 // Note: The code below even works when right contains kMinInt. | 1414 Register result_reg = ToRegister(instr->result()); |
1382 int32_t divisor = Abs(right->GetInteger32Constant()); | 1415 ASSERT(result_reg.is(edx)); |
1383 | 1416 |
1384 Label left_is_not_negative, done; | 1417 Label done; |
1385 if (left->CanBeNegative()) { | 1418 // Check for x % 0, idiv would signal a divide error. We have to |
1386 __ test(left_reg, Operand(left_reg)); | 1419 // deopt in this case because we can't return a NaN. |
1387 __ j(not_sign, &left_is_not_negative, Label::kNear); | 1420 if (right->CanBeZero()) { |
1388 __ neg(left_reg); | 1421 __ test(right_reg, Operand(right_reg)); |
1389 __ and_(left_reg, divisor - 1); | 1422 DeoptimizeIf(zero, instr->environment()); |
1390 __ neg(left_reg); | 1423 } |
1391 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1424 |
1392 DeoptimizeIf(zero, instr->environment()); | 1425 // Check for kMinInt % -1, idiv would signal a divide error. We |
1393 } | 1426 // have to deopt if we care about -0, because we can't return that. |
| 1427 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { |
| 1428 Label no_overflow_possible; |
| 1429 __ cmp(left_reg, kMinInt); |
| 1430 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1431 __ cmp(right_reg, -1); |
| 1432 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1433 DeoptimizeIf(equal, instr->environment()); |
| 1434 } else { |
| 1435 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1436 __ Set(result_reg, Immediate(0)); |
1394 __ jmp(&done, Label::kNear); | 1437 __ jmp(&done, Label::kNear); |
1395 } | 1438 } |
1396 | 1439 __ bind(&no_overflow_possible); |
1397 __ bind(&left_is_not_negative); | 1440 } |
1398 __ and_(left_reg, divisor - 1); | 1441 |
1399 __ bind(&done); | 1442 // Sign extend dividend in eax into edx:eax. |
1400 } else { | 1443 __ cdq(); |
1401 Register left_reg = ToRegister(instr->left()); | 1444 |
1402 ASSERT(left_reg.is(eax)); | 1445 // If we care about -0, test if the dividend is <0 and the result is 0. |
1403 Register right_reg = ToRegister(instr->right()); | 1446 if (left->CanBeNegative() && |
1404 ASSERT(!right_reg.is(eax)); | 1447 hmod->CanBeZero() && |
1405 ASSERT(!right_reg.is(edx)); | 1448 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1406 Register result_reg = ToRegister(instr->result()); | 1449 Label positive_left; |
1407 ASSERT(result_reg.is(edx)); | 1450 __ test(left_reg, Operand(left_reg)); |
1408 | 1451 __ j(not_sign, &positive_left, Label::kNear); |
1409 Label done; | |
1410 // Check for x % 0, idiv would signal a divide error. We have to | |
1411 // deopt in this case because we can't return a NaN. | |
1412 if (right->CanBeZero()) { | |
1413 __ test(right_reg, Operand(right_reg)); | |
1414 DeoptimizeIf(zero, instr->environment()); | |
1415 } | |
1416 | |
1417 // Check for kMinInt % -1, idiv would signal a divide error. We | |
1418 // have to deopt if we care about -0, because we can't return that. | |
1419 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { | |
1420 Label no_overflow_possible; | |
1421 __ cmp(left_reg, kMinInt); | |
1422 __ j(not_equal, &no_overflow_possible, Label::kNear); | |
1423 __ cmp(right_reg, -1); | |
1424 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1425 DeoptimizeIf(equal, instr->environment()); | |
1426 } else { | |
1427 __ j(not_equal, &no_overflow_possible, Label::kNear); | |
1428 __ Set(result_reg, Immediate(0)); | |
1429 __ jmp(&done, Label::kNear); | |
1430 } | |
1431 __ bind(&no_overflow_possible); | |
1432 } | |
1433 | |
1434 // Sign extend dividend in eax into edx:eax. | |
1435 __ cdq(); | |
1436 | |
1437 // If we care about -0, test if the dividend is <0 and the result is 0. | |
1438 if (left->CanBeNegative() && | |
1439 hmod->CanBeZero() && | |
1440 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1441 Label positive_left; | |
1442 __ test(left_reg, Operand(left_reg)); | |
1443 __ j(not_sign, &positive_left, Label::kNear); | |
1444 __ idiv(right_reg); | |
1445 __ test(result_reg, Operand(result_reg)); | |
1446 DeoptimizeIf(zero, instr->environment()); | |
1447 __ jmp(&done, Label::kNear); | |
1448 __ bind(&positive_left); | |
1449 } | |
1450 __ idiv(right_reg); | 1452 __ idiv(right_reg); |
1451 __ bind(&done); | 1453 __ test(result_reg, Operand(result_reg)); |
1452 } | 1454 DeoptimizeIf(zero, instr->environment()); |
| 1455 __ jmp(&done, Label::kNear); |
| 1456 __ bind(&positive_left); |
| 1457 } |
| 1458 __ idiv(right_reg); |
| 1459 __ bind(&done); |
| 1460 } |
| 1461 |
| 1462 |
| 1463 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1464 Register dividend = ToRegister(instr->dividend()); |
| 1465 int32_t divisor = instr->divisor(); |
| 1466 Register result = ToRegister(instr->result()); |
| 1467 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); |
| 1468 ASSERT(!result.is(dividend)); |
| 1469 |
| 1470 // Check for (0 / -x) that will produce negative zero. |
| 1471 HDiv* hdiv = instr->hydrogen(); |
| 1472 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1473 hdiv->left()->RangeCanInclude(0) && divisor < 0) { |
| 1474 __ test(dividend, dividend); |
| 1475 DeoptimizeIf(zero, instr->environment()); |
| 1476 } |
| 1477 // Check for (kMinInt / -1). |
| 1478 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1479 hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) { |
| 1480 __ cmp(dividend, kMinInt); |
| 1481 DeoptimizeIf(zero, instr->environment()); |
| 1482 } |
| 1483 // Deoptimize if remainder will not be 0. |
| 1484 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1485 divisor != 1 && divisor != -1) { |
| 1486 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1487 __ test(dividend, Immediate(mask)); |
| 1488 DeoptimizeIf(not_zero, instr->environment()); |
| 1489 } |
| 1490 __ Move(result, dividend); |
| 1491 int32_t shift = WhichPowerOf2Abs(divisor); |
| 1492 if (shift > 0) { |
| 1493 // The arithmetic shift is always OK, the 'if' is an optimization only. |
| 1494 if (shift > 1) __ sar(result, 31); |
| 1495 __ shr(result, 32 - shift); |
| 1496 __ add(result, dividend); |
| 1497 __ sar(result, shift); |
| 1498 } |
| 1499 if (divisor < 0) __ neg(result); |
1453 } | 1500 } |
1454 | 1501 |
1455 | 1502 |
1456 void LCodeGen::DoDivI(LDivI* instr) { | 1503 void LCodeGen::DoDivI(LDivI* instr) { |
1457 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { | 1504 Register dividend = ToRegister(instr->left()); |
1458 Register dividend = ToRegister(instr->left()); | 1505 Register divisor = ToRegister(instr->right()); |
1459 HDiv* hdiv = instr->hydrogen(); | 1506 Register remainder = ToRegister(instr->temp()); |
1460 int32_t divisor = hdiv->right()->GetInteger32Constant(); | 1507 Register result = ToRegister(instr->result()); |
1461 Register result = ToRegister(instr->result()); | 1508 ASSERT(dividend.is(eax)); |
1462 ASSERT(!result.is(dividend)); | 1509 ASSERT(remainder.is(edx)); |
1463 | 1510 ASSERT(result.is(eax)); |
1464 // Check for (0 / -x) that will produce negative zero. | 1511 ASSERT(!divisor.is(eax)); |
1465 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && | 1512 ASSERT(!divisor.is(edx)); |
1466 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1467 __ test(dividend, Operand(dividend)); | |
1468 DeoptimizeIf(zero, instr->environment()); | |
1469 } | |
1470 // Check for (kMinInt / -1). | |
1471 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && | |
1472 hdiv->CheckFlag(HValue::kCanOverflow)) { | |
1473 __ cmp(dividend, kMinInt); | |
1474 DeoptimizeIf(zero, instr->environment()); | |
1475 } | |
1476 // Deoptimize if remainder will not be 0. | |
1477 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | |
1478 Abs(divisor) != 1) { | |
1479 __ test(dividend, Immediate(Abs(divisor) - 1)); | |
1480 DeoptimizeIf(not_zero, instr->environment()); | |
1481 } | |
1482 __ Move(result, dividend); | |
1483 int32_t shift = WhichPowerOf2(Abs(divisor)); | |
1484 if (shift > 0) { | |
1485 // The arithmetic shift is always OK, the 'if' is an optimization only. | |
1486 if (shift > 1) __ sar(result, 31); | |
1487 __ shr(result, 32 - shift); | |
1488 __ add(result, dividend); | |
1489 __ sar(result, shift); | |
1490 } | |
1491 if (divisor < 0) __ neg(result); | |
1492 return; | |
1493 } | |
1494 | |
1495 LOperand* right = instr->right(); | |
1496 ASSERT(ToRegister(instr->result()).is(eax)); | |
1497 ASSERT(ToRegister(instr->left()).is(eax)); | |
1498 ASSERT(!ToRegister(instr->right()).is(eax)); | |
1499 ASSERT(!ToRegister(instr->right()).is(edx)); | |
1500 | |
1501 Register left_reg = eax; | |
1502 | 1513 |
1503 // Check for x / 0. | 1514 // Check for x / 0. |
1504 Register right_reg = ToRegister(right); | 1515 HBinaryOperation* hdiv = instr->hydrogen(); |
1505 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 1516 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1506 __ test(right_reg, ToOperand(right)); | 1517 __ test(divisor, divisor); |
1507 DeoptimizeIf(zero, instr->environment()); | 1518 DeoptimizeIf(zero, instr->environment()); |
1508 } | 1519 } |
1509 | 1520 |
1510 // Check for (0 / -x) that will produce negative zero. | 1521 // Check for (0 / -x) that will produce negative zero. |
1511 if (instr->hydrogen_value()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1522 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1512 Label left_not_zero; | 1523 Label dividend_not_zero; |
1513 __ test(left_reg, Operand(left_reg)); | 1524 __ test(dividend, dividend); |
1514 __ j(not_zero, &left_not_zero, Label::kNear); | 1525 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
1515 __ test(right_reg, ToOperand(right)); | 1526 __ test(divisor, divisor); |
1516 DeoptimizeIf(sign, instr->environment()); | 1527 DeoptimizeIf(sign, instr->environment()); |
1517 __ bind(&left_not_zero); | 1528 __ bind(÷nd_not_zero); |
1518 } | 1529 } |
1519 | 1530 |
1520 // Check for (kMinInt / -1). | 1531 // Check for (kMinInt / -1). |
1521 if (instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)) { | 1532 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
1522 Label left_not_min_int; | 1533 Label dividend_not_min_int; |
1523 __ cmp(left_reg, kMinInt); | 1534 __ cmp(dividend, kMinInt); |
1524 __ j(not_zero, &left_not_min_int, Label::kNear); | 1535 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
1525 __ cmp(right_reg, -1); | 1536 __ cmp(divisor, -1); |
1526 DeoptimizeIf(zero, instr->environment()); | 1537 DeoptimizeIf(zero, instr->environment()); |
1527 __ bind(&left_not_min_int); | 1538 __ bind(÷nd_not_min_int); |
1528 } | 1539 } |
1529 | 1540 |
1530 // Sign extend to edx. | 1541 // Sign extend to edx (= remainder). |
1531 __ cdq(); | 1542 __ cdq(); |
1532 __ idiv(right_reg); | 1543 __ idiv(divisor); |
1533 | 1544 |
1534 if (instr->is_flooring()) { | 1545 if (instr->is_flooring()) { |
1535 Label done; | 1546 Label done; |
1536 __ test(edx, edx); | 1547 __ test(remainder, remainder); |
1537 __ j(zero, &done, Label::kNear); | 1548 __ j(zero, &done, Label::kNear); |
1538 __ xor_(edx, right_reg); | 1549 __ xor_(remainder, divisor); |
1539 __ sar(edx, 31); | 1550 __ sar(remainder, 31); |
1540 __ add(eax, edx); | 1551 __ add(result, remainder); |
1541 __ bind(&done); | 1552 __ bind(&done); |
1542 } else if (!instr->hydrogen()->CheckFlag( | 1553 } else if (!instr->hydrogen()->CheckFlag( |
1543 HInstruction::kAllUsesTruncatingToInt32)) { | 1554 HInstruction::kAllUsesTruncatingToInt32)) { |
1544 // Deoptimize if remainder is not 0. | 1555 // Deoptimize if remainder is not 0. |
1545 __ test(edx, Operand(edx)); | 1556 __ test(remainder, remainder); |
1546 DeoptimizeIf(not_zero, instr->environment()); | 1557 DeoptimizeIf(not_zero, instr->environment()); |
1547 } | 1558 } |
1548 } | 1559 } |
1549 | 1560 |
1550 | 1561 |
1551 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 1562 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
1552 ASSERT(instr->right()->IsConstantOperand()); | 1563 Register dividend = ToRegister(instr->dividend()); |
1553 | 1564 int32_t divisor = instr->divisor(); |
1554 Register dividend = ToRegister(instr->left()); | 1565 ASSERT(dividend.is(ToRegister(instr->result()))); |
1555 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); | 1566 |
1556 Register result = ToRegister(instr->result()); | 1567 // If the divisor is positive, things are easy: There can be no deopts and we |
1557 | 1568 // can simply do an arithmetic right shift. |
1558 switch (divisor) { | 1569 if (divisor == 1) return; |
1559 case 0: | 1570 int32_t shift = WhichPowerOf2Abs(divisor); |
| 1571 if (divisor > 1) { |
| 1572 __ sar(dividend, shift); |
| 1573 return; |
| 1574 } |
| 1575 |
| 1576 // If the divisor is negative, we have to negate and handle edge cases. |
| 1577 Label not_kmin_int, done; |
| 1578 __ neg(dividend); |
| 1579 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1580 DeoptimizeIf(zero, instr->environment()); |
| 1581 } |
| 1582 if (instr->hydrogen()->left()->RangeCanInclude(kMinInt)) { |
| 1583 // Note that we could emit branch-free code, but that would need one more |
| 1584 // register. |
| 1585 __ j(no_overflow, ¬_kmin_int, Label::kNear); |
| 1586 if (divisor == -1) { |
| 1587 DeoptimizeIf(no_condition, instr->environment()); |
| 1588 } else { |
| 1589 __ mov(dividend, Immediate(kMinInt / divisor)); |
| 1590 __ jmp(&done, Label::kNear); |
| 1591 } |
| 1592 } |
| 1593 __ bind(¬_kmin_int); |
| 1594 __ sar(dividend, shift); |
| 1595 __ bind(&done); |
| 1596 } |
| 1597 |
| 1598 |
| 1599 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
| 1600 Register dividend = ToRegister(instr->dividend()); |
| 1601 int32_t divisor = instr->divisor(); |
| 1602 Register scratch = ToRegister(instr->temp()); |
| 1603 ASSERT(ToRegister(instr->dividend()).is(eax)); |
| 1604 ASSERT(ToRegister(instr->result()).is(edx)); |
| 1605 |
| 1606 if (divisor == 0) { |
1560 DeoptimizeIf(no_condition, instr->environment()); | 1607 DeoptimizeIf(no_condition, instr->environment()); |
1561 return; | 1608 return; |
1562 | 1609 } |
1563 case 1: | 1610 |
1564 __ Move(result, dividend); | 1611 // Find b which: 2^b < divisor_abs < 2^(b+1). |
1565 return; | |
1566 | |
1567 case -1: | |
1568 __ Move(result, dividend); | |
1569 __ neg(result); | |
1570 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1571 DeoptimizeIf(zero, instr->environment()); | |
1572 } | |
1573 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
1574 DeoptimizeIf(overflow, instr->environment()); | |
1575 } | |
1576 return; | |
1577 } | |
1578 | |
1579 uint32_t divisor_abs = abs(divisor); | 1612 uint32_t divisor_abs = abs(divisor); |
1580 if (IsPowerOf2(divisor_abs)) { | 1613 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); |
1581 int32_t power = WhichPowerOf2(divisor_abs); | 1614 unsigned shift = 32 + b; // Precision +1bit (effectively). |
1582 if (divisor < 0) { | 1615 double multiplier_f = |
1583 // Input[dividend] is clobbered. | 1616 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; |
1584 // The sequence is tedious because neg(dividend) might overflow. | 1617 int64_t multiplier; |
1585 __ mov(result, dividend); | 1618 if (multiplier_f - std::floor(multiplier_f) < 0.5) { |
1586 __ sar(dividend, 31); | 1619 multiplier = static_cast<int64_t>(std::floor(multiplier_f)); |
1587 __ neg(result); | |
1588 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1589 DeoptimizeIf(zero, instr->environment()); | |
1590 } | |
1591 __ shl(dividend, 32 - power); | |
1592 __ sar(result, power); | |
1593 __ not_(dividend); | |
1594 // Clear result.sign if dividend.sign is set. | |
1595 __ and_(result, dividend); | |
1596 } else { | |
1597 __ Move(result, dividend); | |
1598 __ sar(result, power); | |
1599 } | |
1600 } else { | 1620 } else { |
1601 ASSERT(ToRegister(instr->left()).is(eax)); | 1621 multiplier = static_cast<int64_t>(std::floor(multiplier_f)) + 1; |
1602 ASSERT(ToRegister(instr->result()).is(edx)); | 1622 } |
1603 Register scratch = ToRegister(instr->temp()); | 1623 // The multiplier is a uint32. |
1604 | 1624 ASSERT(multiplier > 0 && |
1605 // Find b which: 2^b < divisor_abs < 2^(b+1). | 1625 multiplier < (static_cast<int64_t>(1) << 32)); |
1606 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); | 1626 __ mov(scratch, dividend); |
1607 unsigned shift = 32 + b; // Precision +1bit (effectively). | 1627 if (divisor < 0 && |
1608 double multiplier_f = | 1628 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1609 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; | 1629 __ test(dividend, dividend); |
1610 int64_t multiplier; | 1630 DeoptimizeIf(zero, instr->environment()); |
1611 if (multiplier_f - std::floor(multiplier_f) < 0.5) { | 1631 } |
1612 multiplier = static_cast<int64_t>(std::floor(multiplier_f)); | 1632 __ mov(edx, static_cast<int32_t>(multiplier)); |
1613 } else { | 1633 __ imul(edx); |
1614 multiplier = static_cast<int64_t>(std::floor(multiplier_f)) + 1; | 1634 if (static_cast<int32_t>(multiplier) < 0) { |
1615 } | 1635 __ add(edx, scratch); |
1616 // The multiplier is a uint32. | 1636 } |
1617 ASSERT(multiplier > 0 && | 1637 Register reg_lo = eax; |
1618 multiplier < (static_cast<int64_t>(1) << 32)); | 1638 Register reg_byte_scratch = scratch; |
1619 __ mov(scratch, dividend); | 1639 if (!reg_byte_scratch.is_byte_register()) { |
1620 if (divisor < 0 && | 1640 __ xchg(reg_lo, reg_byte_scratch); |
1621 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1641 reg_lo = scratch; |
1622 __ test(dividend, dividend); | 1642 reg_byte_scratch = eax; |
1623 DeoptimizeIf(zero, instr->environment()); | 1643 } |
1624 } | 1644 if (divisor < 0) { |
1625 __ mov(edx, static_cast<int32_t>(multiplier)); | 1645 __ xor_(reg_byte_scratch, reg_byte_scratch); |
1626 __ imul(edx); | 1646 __ cmp(reg_lo, 0x40000000); |
1627 if (static_cast<int32_t>(multiplier) < 0) { | 1647 __ setcc(above, reg_byte_scratch); |
1628 __ add(edx, scratch); | 1648 __ neg(edx); |
1629 } | 1649 __ sub(edx, reg_byte_scratch); |
1630 Register reg_lo = eax; | 1650 } else { |
1631 Register reg_byte_scratch = scratch; | 1651 __ xor_(reg_byte_scratch, reg_byte_scratch); |
1632 if (!reg_byte_scratch.is_byte_register()) { | 1652 __ cmp(reg_lo, 0xC0000000); |
1633 __ xchg(reg_lo, reg_byte_scratch); | 1653 __ setcc(above_equal, reg_byte_scratch); |
1634 reg_lo = scratch; | 1654 __ add(edx, reg_byte_scratch); |
1635 reg_byte_scratch = eax; | 1655 } |
1636 } | 1656 __ sar(edx, shift - 32); |
1637 if (divisor < 0) { | 1657 } |
1638 __ xor_(reg_byte_scratch, reg_byte_scratch); | 1658 |
1639 __ cmp(reg_lo, 0x40000000); | 1659 |
1640 __ setcc(above, reg_byte_scratch); | |
1641 __ neg(edx); | |
1642 __ sub(edx, reg_byte_scratch); | |
1643 } else { | |
1644 __ xor_(reg_byte_scratch, reg_byte_scratch); | |
1645 __ cmp(reg_lo, 0xC0000000); | |
1646 __ setcc(above_equal, reg_byte_scratch); | |
1647 __ add(edx, reg_byte_scratch); | |
1648 } | |
1649 __ sar(edx, shift - 32); | |
1650 } | |
1651 } | |
1652 | |
1653 | |
1654 void LCodeGen::DoMulI(LMulI* instr) { | 1660 void LCodeGen::DoMulI(LMulI* instr) { |
1655 Register left = ToRegister(instr->left()); | 1661 Register left = ToRegister(instr->left()); |
1656 LOperand* right = instr->right(); | 1662 LOperand* right = instr->right(); |
1657 | 1663 |
1658 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1664 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1659 __ mov(ToRegister(instr->temp()), left); | 1665 __ mov(ToRegister(instr->temp()), left); |
1660 } | 1666 } |
1661 | 1667 |
1662 if (right->IsConstantOperand()) { | 1668 if (right->IsConstantOperand()) { |
1663 // Try strength reductions on the multiplication. | 1669 // Try strength reductions on the multiplication. |
(...skipping 4619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6283 FixedArray::kHeaderSize - kPointerSize)); | 6289 FixedArray::kHeaderSize - kPointerSize)); |
6284 __ bind(&done); | 6290 __ bind(&done); |
6285 } | 6291 } |
6286 | 6292 |
6287 | 6293 |
6288 #undef __ | 6294 #undef __ |
6289 | 6295 |
6290 } } // namespace v8::internal | 6296 } } // namespace v8::internal |
6291 | 6297 |
6292 #endif // V8_TARGET_ARCH_IA32 | 6298 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |