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

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

Issue 23703014: Orthogonalize Lithium binary op instructions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 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
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 744 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 755 }
756 756
757 757
758 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { 758 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
759 return AssignEnvironment(new(zone()) LDeoptimize); 759 return AssignEnvironment(new(zone()) LDeoptimize);
760 } 760 }
761 761
762 762
763 LInstruction* LChunkBuilder::DoShift(Token::Value op, 763 LInstruction* LChunkBuilder::DoShift(Token::Value op,
764 HBitwiseBinaryOperation* instr) { 764 HBitwiseBinaryOperation* instr) {
765 if (instr->representation().IsTagged()) { 765 if (instr->representation().IsSmiOrInteger32()) {
766 ASSERT(instr->left()->representation().IsSmiOrTagged()); 766 ASSERT(instr->left()->representation().Equals(instr->representation()));
767 ASSERT(instr->right()->representation().IsSmiOrTagged()); 767 ASSERT(instr->right()->representation().Equals(instr->representation()));
768 LOperand* left = UseRegisterAtStart(instr->left());
768 769
769 LOperand* context = UseFixed(instr->context(), esi); 770 HValue* right_value = instr->right();
770 LOperand* left = UseFixed(instr->left(), edx); 771 LOperand* right = NULL;
771 LOperand* right = UseFixed(instr->right(), eax); 772 int constant_value = 0;
772 LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right); 773 bool does_deopt = false;
773 return MarkAsCall(DefineFixed(result, eax), instr); 774 if (right_value->IsConstant()) {
775 HConstant* constant = HConstant::cast(right_value);
776 right = chunk_->DefineConstantOperand(constant);
777 constant_value = constant->Integer32Value() & 0x1f;
778 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
779 // truncated to smi.
780 if (instr->representation().IsSmi() && constant_value > 0) {
781 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
782 }
783 } else {
784 right = UseFixed(right_value, ecx);
785 }
786
787 // Shift operations can only deoptimize if we do a logical shift by 0 and
788 // the result cannot be truncated to int32.
789 if (op == Token::SHR && constant_value == 0) {
790 if (FLAG_opt_safe_uint32_operations) {
791 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
792 } else {
793 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
794 }
795 }
796
797 LInstruction* result =
798 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
799 return does_deopt ? AssignEnvironment(result) : result;
800 } else {
801 return DoArithmeticT(op, instr);
774 } 802 }
775
776 ASSERT(instr->representation().IsSmiOrInteger32());
777 ASSERT(instr->left()->representation().Equals(instr->representation()));
778 ASSERT(instr->right()->representation().Equals(instr->representation()));
779 LOperand* left = UseRegisterAtStart(instr->left());
780
781 HValue* right_value = instr->right();
782 LOperand* right = NULL;
783 int constant_value = 0;
784 bool does_deopt = false;
785 if (right_value->IsConstant()) {
786 HConstant* constant = HConstant::cast(right_value);
787 right = chunk_->DefineConstantOperand(constant);
788 constant_value = constant->Integer32Value() & 0x1f;
789 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
790 // truncated to smi.
791 if (instr->representation().IsSmi() && constant_value > 0) {
792 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
793 }
794 } else {
795 right = UseFixed(right_value, ecx);
796 }
797
798 // Shift operations can only deoptimize if we do a logical shift by 0 and
799 // the result cannot be truncated to int32.
800 if (op == Token::SHR && constant_value == 0) {
801 if (FLAG_opt_safe_uint32_operations) {
802 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
803 } else {
804 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
805 }
806 }
807
808 LInstruction* result =
809 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
810 return does_deopt ? AssignEnvironment(result) : result;
811 } 803 }
812 804
813 805
814 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, 806 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
815 HArithmeticBinaryOperation* instr) { 807 HArithmeticBinaryOperation* instr) {
816 ASSERT(instr->representation().IsDouble()); 808 ASSERT(instr->representation().IsDouble());
817 ASSERT(instr->left()->representation().IsDouble()); 809 ASSERT(instr->left()->representation().IsDouble());
818 ASSERT(instr->right()->representation().IsDouble()); 810 ASSERT(instr->right()->representation().IsDouble());
819 ASSERT(op != Token::MOD);
820 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 811 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
821 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); 812 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
822 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); 813 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
814 if (op == Token::MOD) return MarkAsCall(DefineSameAsFirst(result), instr);
Sven Panne 2013/09/16 13:10:32 This is a border case: Personally I would prefer t
823 return DefineSameAsFirst(result); 815 return DefineSameAsFirst(result);
824 } 816 }
825 817
826 818
827 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, 819 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
828 HArithmeticBinaryOperation* instr) { 820 HBinaryOperation* instr) {
829 ASSERT(op == Token::ADD ||
830 op == Token::DIV ||
831 op == Token::MOD ||
832 op == Token::MUL ||
833 op == Token::SUB);
834 HValue* left = instr->left(); 821 HValue* left = instr->left();
835 HValue* right = instr->right(); 822 HValue* right = instr->right();
836 ASSERT(left->representation().IsTagged()); 823 ASSERT(left->representation().IsTagged());
837 ASSERT(right->representation().IsTagged()); 824 ASSERT(right->representation().IsTagged());
838 LOperand* context = UseFixed(instr->context(), esi); 825 LOperand* context = UseFixed(instr->context(), esi);
839 LOperand* left_operand = UseFixed(left, edx); 826 LOperand* left_operand = UseFixed(left, edx);
840 LOperand* right_operand = UseFixed(right, eax); 827 LOperand* right_operand = UseFixed(right, eax);
841 LArithmeticT* result = 828 LArithmeticT* result =
842 new(zone()) LArithmeticT(op, context, left_operand, right_operand); 829 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
843 return MarkAsCall(DefineFixed(result, eax), instr); 830 return MarkAsCall(DefineFixed(result, eax), instr);
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 1422
1436 LInstruction* LChunkBuilder::DoShl(HShl* instr) { 1423 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1437 return DoShift(Token::SHL, instr); 1424 return DoShift(Token::SHL, instr);
1438 } 1425 }
1439 1426
1440 1427
1441 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { 1428 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1442 if (instr->representation().IsSmiOrInteger32()) { 1429 if (instr->representation().IsSmiOrInteger32()) {
1443 ASSERT(instr->left()->representation().Equals(instr->representation())); 1430 ASSERT(instr->left()->representation().Equals(instr->representation()));
1444 ASSERT(instr->right()->representation().Equals(instr->representation())); 1431 ASSERT(instr->right()->representation().Equals(instr->representation()));
1432 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1445 1433
1446 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1434 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1447 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 1435 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1448 return DefineSameAsFirst(new(zone()) LBitI(left, right)); 1436 return DefineSameAsFirst(new(zone()) LBitI(left, right));
1449 } else { 1437 } else {
1450 ASSERT(instr->representation().IsSmiOrTagged()); 1438 return DoArithmeticT(instr->op(), instr);
1451 ASSERT(instr->left()->representation().IsSmiOrTagged());
1452 ASSERT(instr->right()->representation().IsSmiOrTagged());
1453
1454 LOperand* context = UseFixed(instr->context(), esi);
1455 LOperand* left = UseFixed(instr->left(), edx);
1456 LOperand* right = UseFixed(instr->right(), eax);
1457 LArithmeticT* result =
1458 new(zone()) LArithmeticT(instr->op(), context, left, right);
1459 return MarkAsCall(DefineFixed(result, eax), instr);
1460 } 1439 }
1461 } 1440 }
1462 1441
1463 1442
1464 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1443 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1465 if (instr->representation().IsDouble()) { 1444 if (instr->representation().IsSmiOrInteger32()) {
1466 return DoArithmeticD(Token::DIV, instr);
1467 } else if (instr->representation().IsSmiOrInteger32()) {
1468 ASSERT(instr->left()->representation().Equals(instr->representation())); 1445 ASSERT(instr->left()->representation().Equals(instr->representation()));
1469 ASSERT(instr->right()->representation().Equals(instr->representation())); 1446 ASSERT(instr->right()->representation().Equals(instr->representation()));
1470 if (instr->HasPowerOf2Divisor()) { 1447 if (instr->HasPowerOf2Divisor()) {
1471 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); 1448 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1472 LOperand* value = UseRegisterAtStart(instr->left()); 1449 LOperand* value = UseRegisterAtStart(instr->left());
1473 LDivI* div = 1450 LDivI* div =
1474 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); 1451 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
1475 return AssignEnvironment(DefineSameAsFirst(div)); 1452 return AssignEnvironment(DefineSameAsFirst(div));
1476 } 1453 }
1477 // The temporary operand is necessary to ensure that right is not allocated 1454 // The temporary operand is necessary to ensure that right is not allocated
1478 // into edx. 1455 // into edx.
1479 LOperand* temp = FixedTemp(edx); 1456 LOperand* temp = FixedTemp(edx);
1480 LOperand* dividend = UseFixed(instr->left(), eax); 1457 LOperand* dividend = UseFixed(instr->left(), eax);
1481 LOperand* divisor = UseRegister(instr->right()); 1458 LOperand* divisor = UseRegister(instr->right());
1482 LDivI* result = new(zone()) LDivI(dividend, divisor, temp); 1459 LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
1483 return AssignEnvironment(DefineFixed(result, eax)); 1460 return AssignEnvironment(DefineFixed(result, eax));
1461 } else if (instr->representation().IsDouble()) {
1462 return DoArithmeticD(Token::DIV, instr);
1484 } else { 1463 } else {
1485 ASSERT(instr->representation().IsTagged());
1486 return DoArithmeticT(Token::DIV, instr); 1464 return DoArithmeticT(Token::DIV, instr);
1487 } 1465 }
1488 } 1466 }
1489 1467
1490 1468
1491 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) { 1469 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1492 if (divisor->IsConstant() && 1470 if (divisor->IsConstant() &&
1493 HConstant::cast(divisor)->HasInteger32Value()) { 1471 HConstant::cast(divisor)->HasInteger32Value()) {
1494 HConstant* constant_val = HConstant::cast(divisor); 1472 HConstant* constant_val = HConstant::cast(divisor);
1495 return constant_val->CopyToRepresentation(Representation::Integer32(), 1473 return constant_val->CopyToRepresentation(Representation::Integer32(),
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1577 return (right->CanBeZero() || 1555 return (right->CanBeZero() ||
1578 (left->RangeCanInclude(kMinInt) && 1556 (left->RangeCanInclude(kMinInt) &&
1579 right->RangeCanInclude(-1) && 1557 right->RangeCanInclude(-1) &&
1580 instr->CheckFlag(HValue::kBailoutOnMinusZero)) || 1558 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1581 (left->CanBeNegative() && 1559 (left->CanBeNegative() &&
1582 instr->CanBeZero() && 1560 instr->CanBeZero() &&
1583 instr->CheckFlag(HValue::kBailoutOnMinusZero))) 1561 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1584 ? AssignEnvironment(result) 1562 ? AssignEnvironment(result)
1585 : result; 1563 : result;
1586 } 1564 }
1587 } else if (instr->representation().IsSmiOrTagged()) { 1565 } else if (instr->representation().IsDouble()) {
1566 return DoArithmeticD(Token::MOD, instr);
1567 } else {
1588 return DoArithmeticT(Token::MOD, instr); 1568 return DoArithmeticT(Token::MOD, instr);
1589 } else {
1590 ASSERT(instr->representation().IsDouble());
1591 // We call a C function for double modulo. It can't trigger a GC. We need
1592 // to use fixed result register for the call.
1593 // TODO(fschneider): Allow any register as input registers.
1594 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
1595 UseFixedDouble(left, xmm2),
1596 UseFixedDouble(right, xmm1));
1597 return MarkAsCall(DefineFixedDouble(mod, xmm1), instr);
1598 } 1569 }
1599 } 1570 }
1600 1571
1601 1572
1602 LInstruction* LChunkBuilder::DoMul(HMul* instr) { 1573 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1603 if (instr->representation().IsSmiOrInteger32()) { 1574 if (instr->representation().IsSmiOrInteger32()) {
1604 ASSERT(instr->left()->representation().Equals(instr->representation())); 1575 ASSERT(instr->left()->representation().Equals(instr->representation()));
1605 ASSERT(instr->right()->representation().Equals(instr->representation())); 1576 ASSERT(instr->right()->representation().Equals(instr->representation()));
1606 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1577 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1607 LOperand* right = UseOrConstant(instr->BetterRightOperand()); 1578 LOperand* right = UseOrConstant(instr->BetterRightOperand());
1608 LOperand* temp = NULL; 1579 LOperand* temp = NULL;
1609 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { 1580 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1610 temp = TempRegister(); 1581 temp = TempRegister();
1611 } 1582 }
1612 LMulI* mul = new(zone()) LMulI(left, right, temp); 1583 LMulI* mul = new(zone()) LMulI(left, right, temp);
1613 if (instr->CheckFlag(HValue::kCanOverflow) || 1584 if (instr->CheckFlag(HValue::kCanOverflow) ||
1614 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { 1585 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1615 AssignEnvironment(mul); 1586 AssignEnvironment(mul);
1616 } 1587 }
1617 return DefineSameAsFirst(mul); 1588 return DefineSameAsFirst(mul);
1618 } else if (instr->representation().IsDouble()) { 1589 } else if (instr->representation().IsDouble()) {
1619 return DoArithmeticD(Token::MUL, instr); 1590 return DoArithmeticD(Token::MUL, instr);
1620 } else { 1591 } else {
1621 ASSERT(instr->representation().IsTagged());
1622 return DoArithmeticT(Token::MUL, instr); 1592 return DoArithmeticT(Token::MUL, instr);
1623 } 1593 }
1624 } 1594 }
1625 1595
1626 1596
1627 LInstruction* LChunkBuilder::DoSub(HSub* instr) { 1597 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1628 if (instr->representation().IsSmiOrInteger32()) { 1598 if (instr->representation().IsSmiOrInteger32()) {
1629 ASSERT(instr->left()->representation().Equals(instr->representation())); 1599 ASSERT(instr->left()->representation().Equals(instr->representation()));
1630 ASSERT(instr->right()->representation().Equals(instr->representation())); 1600 ASSERT(instr->right()->representation().Equals(instr->representation()));
1631 LOperand* left = UseRegisterAtStart(instr->left()); 1601 LOperand* left = UseRegisterAtStart(instr->left());
1632 LOperand* right = UseOrConstantAtStart(instr->right()); 1602 LOperand* right = UseOrConstantAtStart(instr->right());
1633 LSubI* sub = new(zone()) LSubI(left, right); 1603 LSubI* sub = new(zone()) LSubI(left, right);
1634 LInstruction* result = DefineSameAsFirst(sub); 1604 LInstruction* result = DefineSameAsFirst(sub);
1635 if (instr->CheckFlag(HValue::kCanOverflow)) { 1605 if (instr->CheckFlag(HValue::kCanOverflow)) {
1636 result = AssignEnvironment(result); 1606 result = AssignEnvironment(result);
1637 } 1607 }
1638 return result; 1608 return result;
1639 } else if (instr->representation().IsDouble()) { 1609 } else if (instr->representation().IsDouble()) {
1640 return DoArithmeticD(Token::SUB, instr); 1610 return DoArithmeticD(Token::SUB, instr);
1641 } else { 1611 } else {
1642 ASSERT(instr->representation().IsSmiOrTagged());
1643 return DoArithmeticT(Token::SUB, instr); 1612 return DoArithmeticT(Token::SUB, instr);
1644 } 1613 }
1645 } 1614 }
1646 1615
1647 1616
1648 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { 1617 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1649 if (instr->representation().IsSmiOrInteger32()) { 1618 if (instr->representation().IsSmiOrInteger32()) {
1650 ASSERT(instr->left()->representation().Equals(instr->representation())); 1619 ASSERT(instr->left()->representation().Equals(instr->representation()));
1651 ASSERT(instr->right()->representation().Equals(instr->representation())); 1620 ASSERT(instr->right()->representation().Equals(instr->representation()));
1652 // Check to see if it would be advantageous to use an lea instruction rather 1621 // Check to see if it would be advantageous to use an lea instruction rather
(...skipping 11 matching lines...) Expand all
1664 LInstruction* result = use_lea 1633 LInstruction* result = use_lea
1665 ? DefineAsRegister(add) 1634 ? DefineAsRegister(add)
1666 : DefineSameAsFirst(add); 1635 : DefineSameAsFirst(add);
1667 if (can_overflow) { 1636 if (can_overflow) {
1668 result = AssignEnvironment(result); 1637 result = AssignEnvironment(result);
1669 } 1638 }
1670 return result; 1639 return result;
1671 } else if (instr->representation().IsDouble()) { 1640 } else if (instr->representation().IsDouble()) {
1672 return DoArithmeticD(Token::ADD, instr); 1641 return DoArithmeticD(Token::ADD, instr);
1673 } else { 1642 } else {
1674 ASSERT(instr->representation().IsSmiOrTagged());
1675 return DoArithmeticT(Token::ADD, instr); 1643 return DoArithmeticT(Token::ADD, instr);
1676 } 1644 }
1677 } 1645 }
1678 1646
1679 1647
1680 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { 1648 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1681 LOperand* left = NULL; 1649 LOperand* left = NULL;
1682 LOperand* right = NULL; 1650 LOperand* right = NULL;
1683 if (instr->representation().IsSmiOrInteger32()) { 1651 if (instr->representation().IsSmiOrInteger32()) {
1684 ASSERT(instr->left()->representation().Equals(instr->representation())); 1652 ASSERT(instr->left()->representation().Equals(instr->representation()));
(...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after
2746 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { 2714 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2747 LOperand* object = UseRegister(instr->object()); 2715 LOperand* object = UseRegister(instr->object());
2748 LOperand* index = UseTempRegister(instr->index()); 2716 LOperand* index = UseTempRegister(instr->index());
2749 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); 2717 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
2750 } 2718 }
2751 2719
2752 2720
2753 } } // namespace v8::internal 2721 } } // namespace v8::internal
2754 2722
2755 #endif // V8_TARGET_ARCH_IA32 2723 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698