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

Side by Side Diff: src/hydrogen-instructions.cc

Issue 18434004: Fix and cleanup can_be_minus_zero computation (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 5 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 | « no previous file | test/mjsunit/compiler/minus-zero.js » ('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 // 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 1718 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 context()->PrintNameTo(stream); 1729 context()->PrintNameTo(stream);
1730 } 1730 }
1731 1731
1732 1732
1733 Range* HValue::InferRange(Zone* zone) { 1733 Range* HValue::InferRange(Zone* zone) {
1734 Range* result; 1734 Range* result;
1735 if (type().IsSmi()) { 1735 if (type().IsSmi()) {
1736 result = new(zone) Range(Smi::kMinValue, Smi::kMaxValue); 1736 result = new(zone) Range(Smi::kMinValue, Smi::kMaxValue);
1737 result->set_can_be_minus_zero(false); 1737 result->set_can_be_minus_zero(false);
1738 } else { 1738 } else {
1739 // Untagged integer32 cannot be -0, all other representations can.
1740 result = new(zone) Range(); 1739 result = new(zone) Range();
1741 result->set_can_be_minus_zero(!representation().IsInteger32()); 1740 result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32));
1741 // TODO(jkummerow): The range cannot be minus zero when the upper type
1742 // bound is Integer32.
1742 } 1743 }
1743 return result; 1744 return result;
1744 } 1745 }
1745 1746
1746 1747
1747 Range* HChange::InferRange(Zone* zone) { 1748 Range* HChange::InferRange(Zone* zone) {
1748 Range* input_range = value()->range(); 1749 Range* input_range = value()->range();
1749 if (from().IsInteger32() && 1750 if (from().IsInteger32() &&
1750 to().IsSmiOrTagged() && 1751 to().IsSmiOrTagged() &&
1751 !value()->CheckFlag(HInstruction::kUint32) && 1752 !value()->CheckFlag(HInstruction::kUint32) &&
1752 input_range != NULL && input_range->IsInSmiRange()) { 1753 input_range != NULL && input_range->IsInSmiRange()) {
1753 set_type(HType::Smi()); 1754 set_type(HType::Smi());
1754 ClearGVNFlag(kChangesNewSpacePromotion); 1755 ClearGVNFlag(kChangesNewSpacePromotion);
1755 } 1756 }
1756 Range* result = (input_range != NULL) 1757 Range* result = (input_range != NULL)
1757 ? input_range->Copy(zone) 1758 ? input_range->Copy(zone)
1758 : HValue::InferRange(zone); 1759 : HValue::InferRange(zone);
1759 if (to().IsInteger32()) result->set_can_be_minus_zero(false); 1760 result->set_can_be_minus_zero(!to().IsSmiOrInteger32() ||
1761 !CheckFlag(kAllUsesTruncatingToInt32));
1760 return result; 1762 return result;
1761 } 1763 }
1762 1764
1763 1765
1764 Range* HConstant::InferRange(Zone* zone) { 1766 Range* HConstant::InferRange(Zone* zone) {
1765 if (has_int32_value_) { 1767 if (has_int32_value_) {
1766 Range* result = new(zone) Range(int32_value_, int32_value_); 1768 Range* result = new(zone) Range(int32_value_, int32_value_);
1767 result->set_can_be_minus_zero(false); 1769 result->set_can_be_minus_zero(false);
1768 return result; 1770 return result;
1769 } 1771 }
(...skipping 24 matching lines...) Expand all
1794 1796
1795 Range* HAdd::InferRange(Zone* zone) { 1797 Range* HAdd::InferRange(Zone* zone) {
1796 if (representation().IsInteger32()) { 1798 if (representation().IsInteger32()) {
1797 Range* a = left()->range(); 1799 Range* a = left()->range();
1798 Range* b = right()->range(); 1800 Range* b = right()->range();
1799 Range* res = a->Copy(zone); 1801 Range* res = a->Copy(zone);
1800 if (!res->AddAndCheckOverflow(b) || 1802 if (!res->AddAndCheckOverflow(b) ||
1801 CheckFlag(kAllUsesTruncatingToInt32)) { 1803 CheckFlag(kAllUsesTruncatingToInt32)) {
1802 ClearFlag(kCanOverflow); 1804 ClearFlag(kCanOverflow);
1803 } 1805 }
1804 if (!CheckFlag(kAllUsesTruncatingToInt32)) { 1806 res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1805 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeMinusZero()); 1807 a->CanBeMinusZero() &&
rossberg 2013/07/08 10:49:23 Nit: actual condition may fit on one line.
Jakob Kummerow 2013/07/08 11:12:04 Done.
1806 } 1808 b->CanBeMinusZero());
1807 return res; 1809 return res;
1808 } else { 1810 } else {
1809 return HValue::InferRange(zone); 1811 return HValue::InferRange(zone);
1810 } 1812 }
1811 } 1813 }
1812 1814
1813 1815
1814 Range* HSub::InferRange(Zone* zone) { 1816 Range* HSub::InferRange(Zone* zone) {
1815 if (representation().IsInteger32()) { 1817 if (representation().IsInteger32()) {
1816 Range* a = left()->range(); 1818 Range* a = left()->range();
1817 Range* b = right()->range(); 1819 Range* b = right()->range();
1818 Range* res = a->Copy(zone); 1820 Range* res = a->Copy(zone);
1819 if (!res->SubAndCheckOverflow(b) || 1821 if (!res->SubAndCheckOverflow(b) ||
1820 CheckFlag(kAllUsesTruncatingToInt32)) { 1822 CheckFlag(kAllUsesTruncatingToInt32)) {
1821 ClearFlag(kCanOverflow); 1823 ClearFlag(kCanOverflow);
1822 } 1824 }
1823 if (!CheckFlag(kAllUsesTruncatingToInt32)) { 1825 res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1824 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero()); 1826 a->CanBeMinusZero() &&
rossberg 2013/07/08 10:49:23 Same here.
Jakob Kummerow 2013/07/08 11:12:04 Done.
1825 } 1827 b->CanBeZero());
1826 return res; 1828 return res;
1827 } else { 1829 } else {
1828 return HValue::InferRange(zone); 1830 return HValue::InferRange(zone);
1829 } 1831 }
1830 } 1832 }
1831 1833
1832 1834
1833 Range* HMul::InferRange(Zone* zone) { 1835 Range* HMul::InferRange(Zone* zone) {
1834 if (representation().IsInteger32()) { 1836 if (representation().IsInteger32()) {
1835 Range* a = left()->range(); 1837 Range* a = left()->range();
1836 Range* b = right()->range(); 1838 Range* b = right()->range();
1837 Range* res = a->Copy(zone); 1839 Range* res = a->Copy(zone);
1838 if (!res->MulAndCheckOverflow(b)) { 1840 if (!res->MulAndCheckOverflow(b)) {
1839 // Clearing the kCanOverflow flag when kAllUsesAreTruncatingToInt32 1841 // Clearing the kCanOverflow flag when kAllUsesAreTruncatingToInt32
1840 // would be wrong, because truncated integer multiplication is too 1842 // would be wrong, because truncated integer multiplication is too
1841 // precise and therefore not the same as converting to Double and back. 1843 // precise and therefore not the same as converting to Double and back.
1842 ClearFlag(kCanOverflow); 1844 ClearFlag(kCanOverflow);
1843 } 1845 }
1844 if (!CheckFlag(kAllUsesTruncatingToInt32)) { 1846 res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1845 bool m0 = (a->CanBeZero() && b->CanBeNegative()) || 1847 ((a->CanBeZero() && b->CanBeNegative()) ||
1846 (a->CanBeNegative() && b->CanBeZero()); 1848 (a->CanBeNegative() && b->CanBeZero())));
1847 res->set_can_be_minus_zero(m0);
1848 }
1849 return res; 1849 return res;
1850 } else { 1850 } else {
1851 return HValue::InferRange(zone); 1851 return HValue::InferRange(zone);
1852 } 1852 }
1853 } 1853 }
1854 1854
1855 1855
1856 Range* HDiv::InferRange(Zone* zone) { 1856 Range* HDiv::InferRange(Zone* zone) {
1857 if (representation().IsInteger32()) { 1857 if (representation().IsInteger32()) {
1858 Range* a = left()->range(); 1858 Range* a = left()->range();
1859 Range* b = right()->range(); 1859 Range* b = right()->range();
1860 Range* result = new(zone) Range(); 1860 Range* result = new(zone) Range();
1861 if (!CheckFlag(kAllUsesTruncatingToInt32)) { 1861 result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1862 if (a->CanBeMinusZero()) { 1862 (a->CanBeMinusZero() ||
1863 result->set_can_be_minus_zero(true); 1863 (a->CanBeZero() && b->CanBeNegative())));
1864 }
1865
1866 if (a->CanBeZero() && b->CanBeNegative()) {
1867 result->set_can_be_minus_zero(true);
1868 }
1869 }
1870
1871 if (!a->Includes(kMinInt) || !b->Includes(-1)) { 1864 if (!a->Includes(kMinInt) || !b->Includes(-1)) {
1872 ClearFlag(HValue::kCanOverflow); 1865 ClearFlag(HValue::kCanOverflow);
1873 } 1866 }
1874 1867
1875 if (!b->CanBeZero()) { 1868 if (!b->CanBeZero()) {
1876 ClearFlag(HValue::kCanBeDivByZero); 1869 ClearFlag(HValue::kCanBeDivByZero);
1877 } 1870 }
1878 return result; 1871 return result;
1879 } else { 1872 } else {
1880 return HValue::InferRange(zone); 1873 return HValue::InferRange(zone);
1881 } 1874 }
1882 } 1875 }
1883 1876
1884 1877
1885 Range* HMod::InferRange(Zone* zone) { 1878 Range* HMod::InferRange(Zone* zone) {
1886 if (representation().IsInteger32()) { 1879 if (representation().IsInteger32()) {
1887 Range* a = left()->range(); 1880 Range* a = left()->range();
1888 Range* b = right()->range(); 1881 Range* b = right()->range();
1889 1882
1890 // The magnitude of the modulus is bounded by the right operand. Note that 1883 // The magnitude of the modulus is bounded by the right operand. Note that
1891 // apart for the cases involving kMinInt, the calculation below is the same 1884 // apart for the cases involving kMinInt, the calculation below is the same
1892 // as Max(Abs(b->lower()), Abs(b->upper())) - 1. 1885 // as Max(Abs(b->lower()), Abs(b->upper())) - 1.
1893 int32_t positive_bound = -(Min(NegAbs(b->lower()), NegAbs(b->upper())) + 1); 1886 int32_t positive_bound = -(Min(NegAbs(b->lower()), NegAbs(b->upper())) + 1);
1894 1887
1895 // The result of the modulo operation has the sign of its left operand. 1888 // The result of the modulo operation has the sign of its left operand.
1896 bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative(); 1889 bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative();
1897 Range* result = new(zone) Range(left_can_be_negative ? -positive_bound : 0, 1890 Range* result = new(zone) Range(left_can_be_negative ? -positive_bound : 0,
1898 a->CanBePositive() ? positive_bound : 0); 1891 a->CanBePositive() ? positive_bound : 0);
1899 1892
1900 if (left_can_be_negative && !CheckFlag(kAllUsesTruncatingToInt32)) { 1893 result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1901 result->set_can_be_minus_zero(true); 1894 left_can_be_negative);
1902 }
1903 1895
1904 if (!a->Includes(kMinInt) || !b->Includes(-1)) { 1896 if (!a->Includes(kMinInt) || !b->Includes(-1)) {
1905 ClearFlag(HValue::kCanOverflow); 1897 ClearFlag(HValue::kCanOverflow);
1906 } 1898 }
1907 1899
1908 if (!b->CanBeZero()) { 1900 if (!b->CanBeZero()) {
1909 ClearFlag(HValue::kCanBeDivByZero); 1901 ClearFlag(HValue::kCanBeDivByZero);
1910 } 1902 }
1911 return result; 1903 return result;
1912 } else { 1904 } else {
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
2425 static_cast<uint32_t>( 2417 static_cast<uint32_t>(
2426 left_upper | left_lower | right_upper | right_lower)); 2418 left_upper | left_lower | right_upper | right_lower));
2427 2419
2428 int64_t limit = 1; 2420 int64_t limit = 1;
2429 limit <<= high; 2421 limit <<= high;
2430 int32_t min = (left()->range()->CanBeNegative() || 2422 int32_t min = (left()->range()->CanBeNegative() ||
2431 right()->range()->CanBeNegative()) 2423 right()->range()->CanBeNegative())
2432 ? static_cast<int32_t>(-limit) : 0; 2424 ? static_cast<int32_t>(-limit) : 0;
2433 return new(zone) Range(min, static_cast<int32_t>(limit - 1)); 2425 return new(zone) Range(min, static_cast<int32_t>(limit - 1));
2434 } 2426 }
2435 return HValue::InferRange(zone); 2427 Range* result = HValue::InferRange(zone);
2428 result->set_can_be_minus_zero(false);
2429 return result;
2436 } 2430 }
2437 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff); 2431 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
2438 int32_t left_mask = (left()->range() != NULL) 2432 int32_t left_mask = (left()->range() != NULL)
2439 ? left()->range()->Mask() 2433 ? left()->range()->Mask()
2440 : kDefaultMask; 2434 : kDefaultMask;
2441 int32_t right_mask = (right()->range() != NULL) 2435 int32_t right_mask = (right()->range() != NULL)
2442 ? right()->range()->Mask() 2436 ? right()->range()->Mask()
2443 : kDefaultMask; 2437 : kDefaultMask;
2444 int32_t result_mask = (op() == Token::BIT_AND) 2438 int32_t result_mask = (op() == Token::BIT_AND)
2445 ? left_mask & right_mask 2439 ? left_mask & right_mask
2446 : left_mask | right_mask; 2440 : left_mask | right_mask;
2447 return (result_mask >= 0) 2441 if (result_mask >= 0) return new(zone) Range(0, result_mask);
2448 ? new(zone) Range(0, result_mask) 2442
2449 : HValue::InferRange(zone); 2443 Range* result = HValue::InferRange(zone);
2444 result->set_can_be_minus_zero(false);
2445 return result;
2450 } 2446 }
2451 2447
2452 2448
2453 Range* HSar::InferRange(Zone* zone) { 2449 Range* HSar::InferRange(Zone* zone) {
2454 if (right()->IsConstant()) { 2450 if (right()->IsConstant()) {
2455 HConstant* c = HConstant::cast(right()); 2451 HConstant* c = HConstant::cast(right());
2456 if (c->HasInteger32Value()) { 2452 if (c->HasInteger32Value()) {
2457 Range* result = (left()->range() != NULL) 2453 Range* result = (left()->range() != NULL)
2458 ? left()->range()->Copy(zone) 2454 ? left()->range()->Copy(zone)
2459 : new(zone) Range(); 2455 : new(zone) Range();
2460 result->Sar(c->Integer32Value()); 2456 result->Sar(c->Integer32Value());
2461 result->set_can_be_minus_zero(false);
2462 return result; 2457 return result;
2463 } 2458 }
2464 } 2459 }
2465 return HValue::InferRange(zone); 2460 return HValue::InferRange(zone);
2466 } 2461 }
2467 2462
2468 2463
2469 Range* HShr::InferRange(Zone* zone) { 2464 Range* HShr::InferRange(Zone* zone) {
2470 if (right()->IsConstant()) { 2465 if (right()->IsConstant()) {
2471 HConstant* c = HConstant::cast(right()); 2466 HConstant* c = HConstant::cast(right());
2472 if (c->HasInteger32Value()) { 2467 if (c->HasInteger32Value()) {
2473 int shift_count = c->Integer32Value() & 0x1f; 2468 int shift_count = c->Integer32Value() & 0x1f;
2474 if (left()->range()->CanBeNegative()) { 2469 if (left()->range()->CanBeNegative()) {
2475 // Only compute bounds if the result always fits into an int32. 2470 // Only compute bounds if the result always fits into an int32.
2476 return (shift_count >= 1) 2471 return (shift_count >= 1)
2477 ? new(zone) Range(0, 2472 ? new(zone) Range(0,
2478 static_cast<uint32_t>(0xffffffff) >> shift_count) 2473 static_cast<uint32_t>(0xffffffff) >> shift_count)
2479 : new(zone) Range(); 2474 : new(zone) Range();
2480 } else { 2475 } else {
2481 // For positive inputs we can use the >> operator. 2476 // For positive inputs we can use the >> operator.
2482 Range* result = (left()->range() != NULL) 2477 Range* result = (left()->range() != NULL)
2483 ? left()->range()->Copy(zone) 2478 ? left()->range()->Copy(zone)
2484 : new(zone) Range(); 2479 : new(zone) Range();
2485 result->Sar(c->Integer32Value()); 2480 result->Sar(c->Integer32Value());
2486 result->set_can_be_minus_zero(false);
2487 return result; 2481 return result;
2488 } 2482 }
2489 } 2483 }
2490 } 2484 }
2491 return HValue::InferRange(zone); 2485 return HValue::InferRange(zone);
2492 } 2486 }
2493 2487
2494 2488
2495 Range* HShl::InferRange(Zone* zone) { 2489 Range* HShl::InferRange(Zone* zone) {
2496 if (right()->IsConstant()) { 2490 if (right()->IsConstant()) {
2497 HConstant* c = HConstant::cast(right()); 2491 HConstant* c = HConstant::cast(right());
2498 if (c->HasInteger32Value()) { 2492 if (c->HasInteger32Value()) {
2499 Range* result = (left()->range() != NULL) 2493 Range* result = (left()->range() != NULL)
2500 ? left()->range()->Copy(zone) 2494 ? left()->range()->Copy(zone)
2501 : new(zone) Range(); 2495 : new(zone) Range();
2502 result->Shl(c->Integer32Value()); 2496 result->Shl(c->Integer32Value());
2503 result->set_can_be_minus_zero(false);
2504 return result; 2497 return result;
2505 } 2498 }
2506 } 2499 }
2507 return HValue::InferRange(zone); 2500 return HValue::InferRange(zone);
2508 } 2501 }
2509 2502
2510 2503
2511 Range* HLoadKeyed::InferRange(Zone* zone) { 2504 Range* HLoadKeyed::InferRange(Zone* zone) {
2512 switch (elements_kind()) { 2505 switch (elements_kind()) {
2513 case EXTERNAL_PIXEL_ELEMENTS: 2506 case EXTERNAL_PIXEL_ELEMENTS:
(...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after
3886 case kBackingStore: 3879 case kBackingStore:
3887 if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString()); 3880 if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
3888 stream->Add("[backing-store]"); 3881 stream->Add("[backing-store]");
3889 break; 3882 break;
3890 } 3883 }
3891 3884
3892 stream->Add("@%d", offset()); 3885 stream->Add("@%d", offset());
3893 } 3886 }
3894 3887
3895 } } // namespace v8::internal 3888 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/compiler/minus-zero.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698