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

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

Issue 12091100: Use SAR for positive divident by a power-of two constant divisor. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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 (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/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 __ j(BELOW_EQUAL, slow_path->entry_label()); 1779 __ j(BELOW_EQUAL, slow_path->entry_label());
1780 __ Bind(slow_path->exit_label()); 1780 __ Bind(slow_path->exit_label());
1781 } 1781 }
1782 1782
1783 1783
1784 static bool CanBeImmediate(const Object& constant) { 1784 static bool CanBeImmediate(const Object& constant) {
1785 return constant.IsSmi() && 1785 return constant.IsSmi() &&
1786 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); 1786 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
1787 } 1787 }
1788 1788
1789
1789 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 1790 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
1790 const intptr_t kNumInputs = 2; 1791 const intptr_t kNumInputs = 2;
1791 1792
1792 ConstantInstr* right_constant = right()->definition()->AsConstant(); 1793 ConstantInstr* right_constant = right()->definition()->AsConstant();
1793 if ((right_constant != NULL) && 1794 if ((right_constant != NULL) &&
1794 (op_kind() != Token::kTRUNCDIV) && 1795 (op_kind() != Token::kTRUNCDIV) &&
1795 (op_kind() != Token::kSHL) && 1796 (op_kind() != Token::kSHL) &&
1796 (op_kind() != Token::kMUL) && 1797 (op_kind() != Token::kMUL) &&
1797 CanBeImmediate(right_constant->value())) { 1798 CanBeImmediate(right_constant->value())) {
1798 const intptr_t kNumTemps = 0; 1799 const intptr_t kNumTemps = 0;
1799 LocationSummary* summary = 1800 LocationSummary* summary =
1800 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1801 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1801 summary->set_in(0, Location::RequiresRegister()); 1802 summary->set_in(0, Location::RequiresRegister());
1802 summary->set_in(1, Location::Constant(right_constant->value())); 1803 summary->set_in(1, Location::Constant(right_constant->value()));
1803 summary->set_out(Location::SameAsFirstInput()); 1804 summary->set_out(Location::SameAsFirstInput());
1804 return summary; 1805 return summary;
1805 } 1806 }
1806 1807
1807 if (op_kind() == Token::kTRUNCDIV) { 1808 if (op_kind() == Token::kTRUNCDIV) {
1808 const intptr_t kNumTemps = 1; 1809 const intptr_t kNumTemps = RightIsPowerOfTwoConstant() ? 2 : 1;
1809 LocationSummary* summary = 1810 LocationSummary* summary =
1810 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1811 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1811 // Both inputs must be writable because they will be untagged. 1812 // Both inputs must be writable because they will be untagged.
1812 summary->set_in(0, Location::RegisterLocation(RAX)); 1813 summary->set_in(0, Location::RegisterLocation(RAX));
1813 summary->set_in(1, Location::WritableRegister()); 1814 if (kNumTemps == 1) {
1815 summary->set_in(1, Location::WritableRegister());
1816 } else {
1817 ConstantInstr* right_constant = right()->definition()->AsConstant();
1818 summary->set_in(1, Location::Constant(right_constant->value()));
1819 // Temporary to hold divisor constant.
1820 summary->set_temp(1, Location::RegisterLocation(RBX));
1821 }
1814 summary->set_out(Location::SameAsFirstInput()); 1822 summary->set_out(Location::SameAsFirstInput());
1815 // Will be used for sign extension and division. 1823 // Will be used for sign extension and division.
1816 summary->set_temp(0, Location::RegisterLocation(RDX)); 1824 summary->set_temp(0, Location::RegisterLocation(RDX));
1817 return summary; 1825 return summary;
1818 } else if (op_kind() == Token::kSHR) { 1826 } else if (op_kind() == Token::kSHR) {
1819 const intptr_t kNumTemps = 0; 1827 const intptr_t kNumTemps = 0;
1820 LocationSummary* summary = 1828 LocationSummary* summary =
1821 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1829 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1822 summary->set_in(0, Location::RequiresRegister()); 1830 summary->set_in(0, Location::RequiresRegister());
1823 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); 1831 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1870 if (deopt != NULL) __ j(OVERFLOW, deopt); 1878 if (deopt != NULL) __ j(OVERFLOW, deopt);
1871 break; 1879 break;
1872 } 1880 }
1873 case Token::kMUL: { 1881 case Token::kMUL: {
1874 // Keep left value tagged and untag right value. 1882 // Keep left value tagged and untag right value.
1875 const intptr_t value = Smi::Cast(constant).Value(); 1883 const intptr_t value = Smi::Cast(constant).Value();
1876 __ imulq(left, Immediate(value)); 1884 __ imulq(left, Immediate(value));
1877 if (deopt != NULL) __ j(OVERFLOW, deopt); 1885 if (deopt != NULL) __ j(OVERFLOW, deopt);
1878 break; 1886 break;
1879 } 1887 }
1888 case Token::kTRUNCDIV: {
1889 Label use_div, done;
1890 const intptr_t value = Smi::Cast(constant).Value();
1891 ASSERT((value > 0) && Utils::IsPowerOfTwo(value));
1892 __ cmpq(left, Immediate(0));
1893 __ j(LESS, &use_div, Assembler::kNearJump);
1894 // Positive division by power of two is an arithmetic left shift.
1895 intptr_t shift_count = Utils::ShiftForPowerOfTwo(value) + kSmiTagSize;
1896 __ sarq(left, Immediate(shift_count));
1897 __ jmp(&done, Assembler::kNearJump);
1898 __ Bind(&use_div);
1899 Register right = locs()->temp(1).reg();
1900 ASSERT(left == RAX);
1901 ASSERT((right != RDX) && (right != RAX));
1902 ASSERT(locs()->temp(0).reg() == RDX);
1903 ASSERT(result == RAX);
1904 __ movq(right, Immediate(value));
1905 __ SmiUntag(left);
1906 __ cqo(); // Sign extend RAX -> RDX:RAX.
1907 __ idivq(right); // RAX: quotient, RDX: remainder.
1908 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
1909 // case we cannot tag the result.
1910 __ cmpq(result, Immediate(0x4000000000000000));
1911 __ j(EQUAL, deopt);
1912 __ Bind(&done);
1913 __ SmiTag(result);
1914 break;
1915 }
1880 case Token::kBIT_AND: { 1916 case Token::kBIT_AND: {
1881 // No overflow check. 1917 // No overflow check.
1882 __ andq(left, Immediate(imm)); 1918 __ andq(left, Immediate(imm));
1883 break; 1919 break;
1884 } 1920 }
1885 case Token::kBIT_OR: { 1921 case Token::kBIT_OR: {
1886 // No overflow check. 1922 // No overflow check.
1887 __ orq(left, Immediate(imm)); 1923 __ orq(left, Immediate(imm));
1888 break; 1924 break;
1889 } 1925 }
(...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2992 PcDescriptors::kOther, 3028 PcDescriptors::kOther,
2993 locs()); 3029 locs());
2994 __ Drop(2); // Discard type arguments and receiver. 3030 __ Drop(2); // Discard type arguments and receiver.
2995 } 3031 }
2996 3032
2997 } // namespace dart 3033 } // namespace dart
2998 3034
2999 #undef __ 3035 #undef __
3000 3036
3001 #endif // defined TARGET_ARCH_X64 3037 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/intermediate_language_ia32.cc ('K') | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698