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

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 = 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 if (RightIsPowerOfTwoConstant()) {
1812 summary->set_in(0, Location::RegisterLocation(RAX)); 1813 summary->set_in(0, Location::RequiresRegister());
1813 summary->set_in(1, Location::WritableRegister()); 1814 ConstantInstr* right_constant = right()->definition()->AsConstant();
1814 summary->set_out(Location::SameAsFirstInput()); 1815 summary->set_in(1, Location::Constant(right_constant->value()));
1815 // Will be used for sign extension and division. 1816 summary->set_temp(0, Location::RequiresRegister());
1816 summary->set_temp(0, Location::RegisterLocation(RDX)); 1817 summary->set_out(Location::SameAsFirstInput());
1818 } else {
1819 // Both inputs must be writable because they will be untagged.
1820 summary->set_in(0, Location::RegisterLocation(RAX));
1821 summary->set_in(1, Location::WritableRegister());
1822 summary->set_out(Location::SameAsFirstInput());
1823 // Will be used for sign extension and division.
1824 summary->set_temp(0, Location::RegisterLocation(RDX));
1825 }
1817 return summary; 1826 return summary;
1818 } else if (op_kind() == Token::kSHR) { 1827 } else if (op_kind() == Token::kSHR) {
1819 const intptr_t kNumTemps = 0; 1828 const intptr_t kNumTemps = 0;
1820 LocationSummary* summary = 1829 LocationSummary* summary =
1821 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1830 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1822 summary->set_in(0, Location::RequiresRegister()); 1831 summary->set_in(0, Location::RequiresRegister());
1823 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); 1832 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
1824 summary->set_out(Location::SameAsFirstInput()); 1833 summary->set_out(Location::SameAsFirstInput());
1825 return summary; 1834 return summary;
1826 } else if (op_kind() == Token::kSHL) { 1835 } else if (op_kind() == Token::kSHL) {
1827 const intptr_t kNumTemps = 1; 1836 const intptr_t kNumTemps = 1;
1828 LocationSummary* summary = 1837 LocationSummary* summary =
1829 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1838 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1830 summary->set_in(0, Location::RequiresRegister()); 1839 summary->set_in(0, Location::RequiresRegister());
1831 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); 1840 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
1832 summary->set_temp(0, Location::RequiresRegister()); 1841 summary->set_temp(0, Location::RequiresRegister());
1833 summary->set_out(Location::SameAsFirstInput()); 1842 summary->set_out(Location::SameAsFirstInput());
1834 return summary; 1843 return summary;
1835 } else { 1844 } else {
1836 const intptr_t kNumTemps = 0; 1845 const intptr_t kNumTemps = 0;
1837 LocationSummary* summary = 1846 LocationSummary* summary =
1838 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1847 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1839 summary->set_in(0, Location::RequiresRegister()); 1848 summary->set_in(0, Location::RequiresRegister());
1840 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 1849 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1841 summary->set_out(Location::SameAsFirstInput()); 1850 summary->set_out(Location::SameAsFirstInput());
1842 return summary; 1851 return summary;
1843 } 1852 }
1844 } 1853 }
1845 1854
1846
1847 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1855 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1848 Register left = locs()->in(0).reg(); 1856 Register left = locs()->in(0).reg();
1849 Register result = locs()->out().reg(); 1857 Register result = locs()->out().reg();
1850 ASSERT(left == result); 1858 ASSERT(left == result);
1851 Label* deopt = NULL; 1859 Label* deopt = NULL;
1852 if (CanDeoptimize()) { 1860 if (CanDeoptimize()) {
1853 deopt = compiler->AddDeoptStub(deopt_id(), 1861 deopt = compiler->AddDeoptStub(deopt_id(),
1854 kDeoptBinarySmiOp); 1862 kDeoptBinarySmiOp);
1855 } 1863 }
1856 1864
(...skipping 13 matching lines...) Expand all
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 const intptr_t value = Smi::Cast(constant).Value();
1890 if (value == 1) {
1891 // Do nothing.
1892 break;
1893 } else if (value == -1) {
1894 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
1895 // case we cannot negate the result.
1896 __ cmpq(left, Immediate(0x8000000000000000));
1897 __ j(EQUAL, deopt);
1898 __ negq(left);
1899 break;
1900 }
1901
1902 ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
1903 const intptr_t shift_count =
1904 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
1905 ASSERT(kSmiTagSize == 1);
1906 Register temp = locs()->temp(0).reg();
1907 __ movq(temp, left);
1908 __ sarq(temp, Immediate(63));
1909 ASSERT(shift_count > 1); // 1, -1 case handled above.
1910 __ shrq(temp, Immediate(64 - shift_count));
1911 __ addq(left, temp);
1912 ASSERT(shift_count > 0);
1913 __ sarq(left, Immediate(shift_count));
1914 if (value < 0) {
1915 __ negq(left);
1916 }
1917 __ SmiTag(left);
1918 break;
1919 }
1880 case Token::kBIT_AND: { 1920 case Token::kBIT_AND: {
1881 // No overflow check. 1921 // No overflow check.
1882 __ andq(left, Immediate(imm)); 1922 __ andq(left, Immediate(imm));
1883 break; 1923 break;
1884 } 1924 }
1885 case Token::kBIT_OR: { 1925 case Token::kBIT_OR: {
1886 // No overflow check. 1926 // No overflow check.
1887 __ orq(left, Immediate(imm)); 1927 __ orq(left, Immediate(imm));
1888 break; 1928 break;
1889 } 1929 }
(...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after
2986 PcDescriptors::kOther, 3026 PcDescriptors::kOther,
2987 locs()); 3027 locs());
2988 __ Drop(2); // Discard type arguments and receiver. 3028 __ Drop(2); // Discard type arguments and receiver.
2989 } 3029 }
2990 3030
2991 } // namespace dart 3031 } // namespace dart
2992 3032
2993 #undef __ 3033 #undef __
2994 3034
2995 #endif // defined TARGET_ARCH_X64 3035 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | tests/language/div_with_power_of_two_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698