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

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

Issue 312173002: ARM: Use the shifter operand to merge in previous shift instructions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address Ulan's comments Created 6 years, 6 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/arm/lithium-arm.h ('k') | src/arm/lithium-codegen-arm.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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/lithium-allocator-inl.h" 7 #include "src/lithium-allocator-inl.h"
8 #include "src/arm/lithium-arm.h" 8 #include "src/arm/lithium-arm.h"
9 #include "src/arm/lithium-codegen-arm.h" 9 #include "src/arm/lithium-codegen-arm.h"
10 #include "src/hydrogen-osr.h" 10 #include "src/hydrogen-osr.h"
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 UNREACHABLE(); 669 UNREACHABLE();
670 return NULL; 670 return NULL;
671 } 671 }
672 672
673 673
674 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { 674 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
675 return AssignEnvironment(new(zone()) LDeoptimize); 675 return AssignEnvironment(new(zone()) LDeoptimize);
676 } 676 }
677 677
678 678
679 HBitwiseBinaryOperation* LChunkBuilder::CanTransformToShiftedOp(HValue* val,
680 HValue** left) {
681 if (!val->representation().IsInteger32()) return NULL;
682 if (!(val->IsBitwise() || val->IsAdd() || val->IsSub())) return NULL;
683
684 HBinaryOperation* hinstr = HBinaryOperation::cast(val);
685 HValue* hleft = hinstr->left();
686 HValue* hright = hinstr->right();
687 ASSERT(hleft->representation().Equals(hinstr->representation()));
688 ASSERT(hright->representation().Equals(hinstr->representation()));
689
690 if ((hright->IsConstant() &&
691 LikelyFitsImmField(hinstr, HConstant::cast(hright)->Integer32Value())) ||
692 (hinstr->IsCommutative() && hleft->IsConstant() &&
693 LikelyFitsImmField(hinstr, HConstant::cast(hleft)->Integer32Value()))) {
694 // The constant operand will likely fit in the immediate field. We are
695 // better off with
696 // mov r1, r2 LSL #imm
697 // add r0, r1, #imm2
698 // than with
699 // mov r5, #imm2
700 // add r0, r5, r2 LSL #imm
701 return NULL;
702 }
703
704 HBitwiseBinaryOperation* shift = NULL;
705 // TODO(aleram): We will miss situations where a shift operation is used by
706 // different instructions both as a left and right operands.
707 if (hright->IsBitwiseBinaryShift() &&
708 HBitwiseBinaryOperation::cast(hright)->right()->IsConstant()) {
709 shift = HBitwiseBinaryOperation::cast(hright);
710 if (left != NULL) {
711 *left = hleft;
712 }
713 } else if (hinstr->IsCommutative() &&
714 hleft->IsBitwiseBinaryShift() &&
715 HBitwiseBinaryOperation::cast(hleft)->right()->IsConstant()) {
716 shift = HBitwiseBinaryOperation::cast(hleft);
717 if (left != NULL) {
718 *left = hright;
719 }
720 } else {
721 return NULL;
722 }
723
724 if ((JSShiftAmountFromHConstant(shift->right()) == 0) && shift->IsShr()) {
725 // Logical shifts right by zero can deoptimize.
726 return NULL;
727 }
728
729 return shift;
730 }
731
732
733 bool LChunkBuilder::ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift) {
734 if (!shift->representation().IsInteger32()) {
735 return false;
736 }
737 for (HUseIterator it(shift->uses()); !it.Done(); it.Advance()) {
738 if (shift != CanTransformToShiftedOp(it.value())) {
739 return false;
740 }
741 }
742 return true;
743 }
744
745
746 LInstruction* LChunkBuilder::TryDoOpWithShiftedRightOperand(
747 HBinaryOperation* instr) {
748 HValue* left;
749 HBitwiseBinaryOperation* shift = CanTransformToShiftedOp(instr, &left);
750
751 if ((shift != NULL) && ShiftCanBeOptimizedAway(shift)) {
752 return DoShiftedBinaryOp(instr, left, shift);
753 }
754 return NULL;
755 }
756
757
758 LInstruction* LChunkBuilder::DoShiftedBinaryOp(
759 HBinaryOperation* hinstr, HValue* hleft, HBitwiseBinaryOperation* hshift) {
760 ASSERT(hshift->IsBitwiseBinaryShift());
761 ASSERT(!hshift->IsShr() || (JSShiftAmountFromHConstant(hshift->right()) > 0));
762
763 LTemplateResultInstruction<1>* res;
764 LOperand* left = UseRegisterAtStart(hleft);
765 LOperand* right = UseRegisterAtStart(hshift->left());
766 LOperand* shift_amount = UseConstant(hshift->right());
767 ShiftOp shift_op;
768 switch (hshift->opcode()) {
769 case HValue::kShl: shift_op = LSL; break;
770 case HValue::kShr: shift_op = LSR; break;
771 case HValue::kSar: shift_op = ASR; break;
772 default: UNREACHABLE(); shift_op = NO_SHIFT;
773 }
774
775 if (hinstr->IsBitwise()) {
776 res = new(zone()) LBitI(left, right, shift_op, shift_amount);
777 } else if (hinstr->IsAdd()) {
778 res = new(zone()) LAddI(left, right, shift_op, shift_amount);
779 } else {
780 ASSERT(hinstr->IsSub());
781 res = new(zone()) LSubI(left, right, shift_op, shift_amount);
782 }
783 if (hinstr->CheckFlag(HValue::kCanOverflow)) {
784 AssignEnvironment(res);
785 }
786 return DefineAsRegister(res);
787 }
788
789
679 LInstruction* LChunkBuilder::DoShift(Token::Value op, 790 LInstruction* LChunkBuilder::DoShift(Token::Value op,
680 HBitwiseBinaryOperation* instr) { 791 HBitwiseBinaryOperation* instr) {
681 if (instr->representation().IsSmiOrInteger32()) { 792 if (instr->representation().IsSmiOrInteger32()) {
682 ASSERT(instr->left()->representation().Equals(instr->representation())); 793 ASSERT(instr->left()->representation().Equals(instr->representation()));
683 ASSERT(instr->right()->representation().Equals(instr->representation())); 794 ASSERT(instr->right()->representation().Equals(instr->representation()));
795
796 if (ShiftCanBeOptimizedAway(instr)) {
797 return NULL;
798 }
799
684 LOperand* left = UseRegisterAtStart(instr->left()); 800 LOperand* left = UseRegisterAtStart(instr->left());
685 801
686 HValue* right_value = instr->right(); 802 HValue* right_value = instr->right();
687 LOperand* right = NULL; 803 LOperand* right = NULL;
688 int constant_value = 0; 804 int constant_value = 0;
689 bool does_deopt = false; 805 bool does_deopt = false;
690 if (right_value->IsConstant()) { 806 if (right_value->IsConstant()) {
691 HConstant* constant = HConstant::cast(right_value); 807 HConstant* constant = HConstant::cast(right_value);
692 right = chunk_->DefineConstantOperand(constant); 808 right = chunk_->DefineConstantOperand(constant);
693 constant_value = constant->Integer32Value() & 0x1f; 809 constant_value = JSShiftAmountFromHConstant(constant);
694 // Left shifts can deoptimize if we shift by > 0 and the result cannot be 810 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
695 // truncated to smi. 811 // truncated to smi.
696 if (instr->representation().IsSmi() && constant_value > 0) { 812 if (instr->representation().IsSmi() && constant_value > 0) {
697 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); 813 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
698 } 814 }
699 } else { 815 } else {
700 right = UseRegisterAtStart(right_value); 816 right = UseRegisterAtStart(right_value);
701 } 817 }
702 818
703 // Shift operations can only deoptimize if we do a logical shift 819 // Shift operations can only deoptimize if we do a logical shift
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after
1243 return DoShift(Token::SHL, instr); 1359 return DoShift(Token::SHL, instr);
1244 } 1360 }
1245 1361
1246 1362
1247 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { 1363 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1248 if (instr->representation().IsSmiOrInteger32()) { 1364 if (instr->representation().IsSmiOrInteger32()) {
1249 ASSERT(instr->left()->representation().Equals(instr->representation())); 1365 ASSERT(instr->left()->representation().Equals(instr->representation()));
1250 ASSERT(instr->right()->representation().Equals(instr->representation())); 1366 ASSERT(instr->right()->representation().Equals(instr->representation()));
1251 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); 1367 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1252 1368
1369 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
1370 if (shifted_operation != NULL) {
1371 return shifted_operation;
1372 }
1373
1253 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1374 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1254 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 1375 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1255 return DefineAsRegister(new(zone()) LBitI(left, right)); 1376 return DefineAsRegister(new(zone()) LBitI(left, right));
1256 } else { 1377 } else {
1257 return DoArithmeticT(instr->op(), instr); 1378 return DoArithmeticT(instr->op(), instr);
1258 } 1379 }
1259 } 1380 }
1260 1381
1261 1382
1262 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { 1383 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 return DoArithmeticT(Token::MUL, instr); 1647 return DoArithmeticT(Token::MUL, instr);
1527 } 1648 }
1528 } 1649 }
1529 1650
1530 1651
1531 LInstruction* LChunkBuilder::DoSub(HSub* instr) { 1652 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1532 if (instr->representation().IsSmiOrInteger32()) { 1653 if (instr->representation().IsSmiOrInteger32()) {
1533 ASSERT(instr->left()->representation().Equals(instr->representation())); 1654 ASSERT(instr->left()->representation().Equals(instr->representation()));
1534 ASSERT(instr->right()->representation().Equals(instr->representation())); 1655 ASSERT(instr->right()->representation().Equals(instr->representation()));
1535 1656
1657 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
1658 if (shifted_operation != NULL) {
1659 return shifted_operation;
1660 }
1661
1536 if (instr->left()->IsConstant()) { 1662 if (instr->left()->IsConstant()) {
1537 // If lhs is constant, do reverse subtraction instead. 1663 // If lhs is constant, do reverse subtraction instead.
1538 return DoRSub(instr); 1664 return DoRSub(instr);
1539 } 1665 }
1540 1666
1541 LOperand* left = UseRegisterAtStart(instr->left()); 1667 LOperand* left = UseRegisterAtStart(instr->left());
1542 LOperand* right = UseOrConstantAtStart(instr->right()); 1668 LOperand* right = UseOrConstantAtStart(instr->right());
1543 LSubI* sub = new(zone()) LSubI(left, right); 1669 LSubI* sub = new(zone()) LSubI(left, right);
1544 LInstruction* result = DefineAsRegister(sub); 1670 LInstruction* result = DefineAsRegister(sub);
1545 if (instr->CheckFlag(HValue::kCanOverflow)) { 1671 if (instr->CheckFlag(HValue::kCanOverflow)) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 return DefineSameAsFirst(new(zone()) LMultiplySubD(minuend_op, 1719 return DefineSameAsFirst(new(zone()) LMultiplySubD(minuend_op,
1594 multiplier_op, 1720 multiplier_op,
1595 multiplicand_op)); 1721 multiplicand_op));
1596 } 1722 }
1597 1723
1598 1724
1599 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { 1725 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1600 if (instr->representation().IsSmiOrInteger32()) { 1726 if (instr->representation().IsSmiOrInteger32()) {
1601 ASSERT(instr->left()->representation().Equals(instr->representation())); 1727 ASSERT(instr->left()->representation().Equals(instr->representation()));
1602 ASSERT(instr->right()->representation().Equals(instr->representation())); 1728 ASSERT(instr->right()->representation().Equals(instr->representation()));
1729
1730 LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
1731 if (shifted_operation != NULL) {
1732 return shifted_operation;
1733 }
1734
1603 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1735 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1604 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 1736 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1605 LAddI* add = new(zone()) LAddI(left, right); 1737 LAddI* add = new(zone()) LAddI(left, right);
1606 LInstruction* result = DefineAsRegister(add); 1738 LInstruction* result = DefineAsRegister(add);
1607 if (instr->CheckFlag(HValue::kCanOverflow)) { 1739 if (instr->CheckFlag(HValue::kCanOverflow)) {
1608 result = AssignEnvironment(result); 1740 result = AssignEnvironment(result);
1609 } 1741 }
1610 return result; 1742 return result;
1611 } else if (instr->representation().IsExternal()) { 1743 } else if (instr->representation().IsExternal()) {
1612 ASSERT(instr->left()->representation().IsExternal()); 1744 ASSERT(instr->left()->representation().IsExternal());
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
2589 LInstruction* LChunkBuilder::DoAllocateBlockContext( 2721 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2590 HAllocateBlockContext* instr) { 2722 HAllocateBlockContext* instr) {
2591 LOperand* context = UseFixed(instr->context(), cp); 2723 LOperand* context = UseFixed(instr->context(), cp);
2592 LOperand* function = UseRegisterAtStart(instr->function()); 2724 LOperand* function = UseRegisterAtStart(instr->function());
2593 LAllocateBlockContext* result = 2725 LAllocateBlockContext* result =
2594 new(zone()) LAllocateBlockContext(context, function); 2726 new(zone()) LAllocateBlockContext(context, function);
2595 return MarkAsCall(DefineFixed(result, cp), instr); 2727 return MarkAsCall(DefineFixed(result, cp), instr);
2596 } 2728 }
2597 2729
2598 } } // namespace v8::internal 2730 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-arm.h ('k') | src/arm/lithium-codegen-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698