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

Side by Side Diff: runtime/vm/intrinsifier_x64.cc

Issue 12545067: On x64 use 32bit idiv when possible instead of 64bit one. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rename movsxl to movsxd Created 7 years, 8 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 | « runtime/vm/intermediate_language_x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intrinsifier.h" 8 #include "vm/intrinsifier.h"
9 9
10 #include "vm/assembler.h" 10 #include "vm/assembler.h"
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 return false; 714 return false;
715 } 715 }
716 716
717 717
718 bool Intrinsifier::Integer_mul(Assembler* assembler) { 718 bool Intrinsifier::Integer_mul(Assembler* assembler) {
719 return Integer_mulFromInteger(assembler); 719 return Integer_mulFromInteger(assembler);
720 } 720 }
721 721
722 722
723 bool Intrinsifier::Integer_modulo(Assembler* assembler) { 723 bool Intrinsifier::Integer_modulo(Assembler* assembler) {
724 Label fall_through, return_zero, try_modulo; 724 Label fall_through, return_zero, try_modulo, not_32bit;
725 TestBothArgumentsSmis(assembler, &fall_through); 725 TestBothArgumentsSmis(assembler, &fall_through);
726 // RAX: right argument (divisor) 726 // RAX: right argument (divisor)
727 // Check if modulo by zero -> exception thrown in main function. 727 // Check if modulo by zero -> exception thrown in main function.
728 __ cmpq(RAX, Immediate(0)); 728 __ cmpq(RAX, Immediate(0));
729 __ j(EQUAL, &fall_through, Assembler::kNearJump); 729 __ j(EQUAL, &fall_through, Assembler::kNearJump);
730 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend). 730 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend).
731 __ cmpq(RCX, Immediate(0)); 731 __ cmpq(RCX, Immediate(0));
732 __ j(LESS, &fall_through, Assembler::kNearJump); 732 __ j(LESS, &fall_through, Assembler::kNearJump);
733 __ cmpq(RCX, RAX); 733 __ cmpq(RCX, RAX);
734 __ j(EQUAL, &return_zero, Assembler::kNearJump); 734 __ j(EQUAL, &return_zero, Assembler::kNearJump);
735 __ j(GREATER, &try_modulo, Assembler::kNearJump); 735 __ j(GREATER, &try_modulo, Assembler::kNearJump);
736 __ movq(RAX, RCX); // Return dividend as it is smaller than divisor. 736 __ movq(RAX, RCX); // Return dividend as it is smaller than divisor.
737 __ ret(); 737 __ ret();
738
738 __ Bind(&return_zero); 739 __ Bind(&return_zero);
739 __ xorq(RAX, RAX); // Return zero. 740 __ xorq(RAX, RAX); // Return zero.
740 __ ret(); 741 __ ret();
742
741 __ Bind(&try_modulo); 743 __ Bind(&try_modulo);
742 // RAX: right (non-null divisor). 744 // RAX: right (non-null divisor).
743 __ movq(RCX, RAX); 745 __ movq(RCX, RAX);
746 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend).
747
748 // Check if both operands fit into 32bits as idiv with 64bit operands
749 // requires twice as many cycles and has much higher latency. We are checking
750 // this before untagging them to avoid corner case dividing INT_MAX by -1 that
751 // raises exception because quotient is too large for 32bit register.
752 __ movsxd(RBX, RAX);
753 __ cmpq(RBX, RAX);
754 __ j(NOT_EQUAL, &not_32bit);
755 __ movsxd(RBX, RCX);
756 __ cmpq(RBX, RCX);
757 __ j(NOT_EQUAL, &not_32bit);
758
759 // Both operands are 31bit smis. Divide using 32bit idiv.
760 __ SmiUntag(RAX);
744 __ SmiUntag(RCX); 761 __ SmiUntag(RCX);
745 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend). 762 __ cdq();
763 __ idivl(RCX);
764 __ movsxd(RAX, RDX);
765 __ SmiTag(RAX);
766 __ ret();
767
768 // Divide using 64bit idiv.
769 __ Bind(&not_32bit);
746 __ SmiUntag(RAX); 770 __ SmiUntag(RAX);
771 __ SmiUntag(RCX);
747 __ cqo(); 772 __ cqo();
748 __ idivq(RCX); 773 __ idivq(RCX);
749 __ movq(RAX, RDX); 774 __ movq(RAX, RDX);
750 __ SmiTag(RAX); 775 __ SmiTag(RAX);
751 __ ret(); 776 __ ret();
777
752 __ Bind(&fall_through); 778 __ Bind(&fall_through);
753 return false; 779 return false;
754 } 780 }
755 781
756 782
757 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { 783 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
758 Label fall_through; 784 Label fall_through, not_32bit;
759 TestBothArgumentsSmis(assembler, &fall_through); 785 TestBothArgumentsSmis(assembler, &fall_through);
760 // RAX: right argument (divisor) 786 // RAX: right argument (divisor)
761 __ cmpq(RAX, Immediate(0)); 787 __ cmpq(RAX, Immediate(0));
762 __ j(EQUAL, &fall_through, Assembler::kNearJump); 788 __ j(EQUAL, &fall_through, Assembler::kNearJump);
763 __ movq(RCX, RAX); 789 __ movq(RCX, RAX);
790 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend).
791
792 // Check if both operands fit into 32bits as idiv with 64bit operands
793 // requires twice as many cycles and has much higher latency. We are checking
794 // this before untagging them to avoid corner case dividing INT_MAX by -1 that
795 // raises exception because quotient is too large for 32bit register.
796 __ movsxd(RBX, RAX);
797 __ cmpq(RBX, RAX);
798 __ j(NOT_EQUAL, &not_32bit);
799 __ movsxd(RBX, RCX);
800 __ cmpq(RBX, RCX);
801 __ j(NOT_EQUAL, &not_32bit);
802
803 // Both operands are 31bit smis. Divide using 32bit idiv.
804 __ SmiUntag(RAX);
764 __ SmiUntag(RCX); 805 __ SmiUntag(RCX);
765 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend). 806 __ cdq();
807 __ idivl(RCX);
808 __ movsxd(RAX, RAX);
809 __ SmiTag(RAX); // Result is guaranteed to fit into a smi.
810 __ ret();
811
812 // Divide using 64bit idiv.
813 __ Bind(&not_32bit);
766 __ SmiUntag(RAX); 814 __ SmiUntag(RAX);
815 __ SmiUntag(RCX);
767 __ pushq(RDX); // Preserve RDX in case of 'fall_through'. 816 __ pushq(RDX); // Preserve RDX in case of 'fall_through'.
768 __ cqo(); 817 __ cqo();
769 __ idivq(RCX); 818 __ idivq(RCX);
770 __ popq(RDX); 819 __ popq(RDX);
771 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we 820 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
772 // cannot tag the result. 821 // cannot tag the result.
773 __ cmpq(RAX, Immediate(0x4000000000000000)); 822 __ cmpq(RAX, Immediate(0x4000000000000000));
774 __ j(EQUAL, &fall_through); 823 __ j(EQUAL, &fall_through);
775 __ SmiTag(RAX); 824 __ SmiTag(RAX);
776 __ ret(); 825 __ ret();
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 __ ret(); 1507 __ ret();
1459 return true; 1508 return true;
1460 } 1509 }
1461 1510
1462 1511
1463 #undef __ 1512 #undef __
1464 1513
1465 } // namespace dart 1514 } // namespace dart
1466 1515
1467 #endif // defined TARGET_ARCH_X64 1516 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698