Bug 927389 - IonMonkey: Refine a range's lower and upper bounds when clearing its fractional part. r=nbp
authorDan Gohman <sunfish@google.com>
Mon, 21 Oct 2013 13:04:15 -0700
changeset 165416 ce54c42790f64757ed5cdc69b3fe61a7a9fbf477
parent 165415 ec37f434044acfde23203d4a8b267689becc8109
child 165417 3f03e8b077ca29eef3b7dbdf2fddfbd794cb88b7
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs927389
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 927389 - IonMonkey: Refine a range's lower and upper bounds when clearing its fractional part. r=nbp
js/src/jit-test/tests/asm.js/bug927389.js
js/src/jit-test/tests/ion/bug927389.js
js/src/jit/RangeAnalysis.cpp
js/src/jit/RangeAnalysis.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/bug927389.js
@@ -0,0 +1,6 @@
+(function() {
+    "use asm"
+    function f() {
+        +~~1.1
+    }
+})()
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug927389.js
@@ -0,0 +1,4 @@
+(function () {
+    var x = 0 || 1.1;
+    x >> x;
+})();
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -384,26 +384,18 @@ Range::intersect(const Range *lhs, const
     // possible that we will have computed a newExponent that's more precise
     // than our newLower and newUpper. This is unusual, so we handle it here
     // instead of in optimize().
     //
     // For example, when the floating-point range has an actual maximum value
     // of 1.5, it may have a range like [0,2] and the max_exponent may be zero.
     // When intersecting such a range with an integer range, the fractional part
     // of the range is dropped, but the max exponent of 0 remains valid.
-    if (lhs->canHaveFractionalPart_ != rhs->canHaveFractionalPart_ &&
-        newExponent < MaxInt32Exponent)
-    {
-        // pow(2, newExponent+1)-1 to compute the maximum value for newExponent.
-        int32_t limit = (uint32_t(1) << (newExponent + 1)) - 1;
-        if (limit != INT32_MIN) {
-            newUpper = Min(newUpper, limit);
-            newLower = Max(newLower, -limit);
-        }
-    }
+    if (lhs->canHaveFractionalPart_ != rhs->canHaveFractionalPart_)
+        refineInt32BoundsByExponent(newExponent, &newLower, &newUpper);
 
     return new Range(newLower, newHasInt32LowerBound, newUpper, newHasInt32UpperBound,
                      newFractional, newExponent);
 }
 
 void
 Range::unionWith(const Range *other)
 {
@@ -1936,20 +1928,27 @@ Range::clampToInt32()
     int32_t l = hasInt32LowerBound() ? lower() : JSVAL_INT_MIN;
     int32_t h = hasInt32UpperBound() ? upper() : JSVAL_INT_MAX;
     setInt32(l, h);
 }
 
 void
 Range::wrapAroundToInt32()
 {
-    if (!hasInt32Bounds())
+    if (!hasInt32Bounds()) {
         setInt32(JSVAL_INT_MIN, JSVAL_INT_MAX);
-    else if (canHaveFractionalPart())
+    } else if (canHaveFractionalPart()) {
         canHaveFractionalPart_ = false;
+
+        // Clearing the fractional field may provide an opportunity to refine
+        // lower_ or upper_.
+        refineInt32BoundsByExponent(max_exponent_, &lower_, &upper_);
+
+        assertInvariants();
+    }
 }
 
 void
 Range::wrapAroundToShiftCount()
 {
     wrapAroundToInt32();
     if (lower() < 0 || upper() >= 32)
         setInt32(0, 31);
--- a/js/src/jit/RangeAnalysis.h
+++ b/js/src/jit/RangeAnalysis.h
@@ -249,16 +249,34 @@ class Range : public TempObject {
     uint16_t exponentImpliedByInt32Bounds() const {
          // The number of bits needed to encode |max| is the power of 2 plus one.
          uint32_t max = Max(mozilla::Abs(lower()), mozilla::Abs(upper()));
          uint16_t result = mozilla::FloorLog2(max);
          JS_ASSERT(result == (max == 0 ? 0 : mozilla::ExponentComponent(double(max))));
          return result;
     }
 
+    // When converting a range which contains fractional values to a range
+    // containing only integers, the old max_exponent_ value may imply a better
+    // lower and/or upper bound than was previously available, because they no
+    // longer need to be conservative about fractional offsets and the ends of
+    // the range.
+    //
+    // Given an exponent value and pointers to the lower and upper bound values,
+    // this function refines the lower and upper bound values to the tighest
+    // bound for integer values implied by the exponent.
+    static void refineInt32BoundsByExponent(uint16_t e, int32_t *l, int32_t *h) {
+       if (e < MaxInt32Exponent) {
+           // pow(2, max_exponent_+1)-1 to compute a maximum absolute value.
+           int32_t limit = (uint32_t(1) << (e + 1)) - 1;
+           *h = Min(*h, limit);
+           *l = Max(*l, -limit);
+       }
+    }
+
     // If the value of any of the fields implies a stronger possible value for
     // any other field, update that field to the stronger value. The range must
     // be completely valid before and it is guaranteed to be kept valid.
     void optimize() {
         assertInvariants();
 
         if (hasInt32Bounds()) {
             // Examine lower() and upper(), and if they imply a better exponent