Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 175143002: Consistenly handle power-of-2 divisors in division-like operations (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &dividend_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(&dividend_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, &dividend_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(&dividend_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, &dividend_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(&dividend_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, &not_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(&not_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
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
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698