Bug 939868: Merge int32 and float32 types into float32 only if the int32 can be converted; r=sstangl
authorBenjamin Bouvier <benj@benj.me>
Fri, 22 Nov 2013 15:18:08 +0100
changeset 157392 13e33fcc873dd19edac0a3f6beebd285e4f13dbb
parent 157391 8aaed2b8853807676d795241f7557b861582442a
child 157393 535370a8c66f0bb6fcfb28b9481618bce1e442d9
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerssstangl
bugs939868
milestone28.0a1
Bug 939868: Merge int32 and float32 types into float32 only if the int32 can be converted; r=sstangl
js/src/jit-test/tests/ion/bug939868-2.js
js/src/jit-test/tests/ion/bug939868.js
js/src/jit/IonAnalysis.cpp
js/src/jit/MIR.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug939868-2.js
@@ -0,0 +1,47 @@
+function f(x,y,z) {
+    var z;
+    if (x) {
+        if (y) {
+            z = 0xfffffff;
+        } else {
+            z = 0xfffffff;
+        }
+        assertFloat32(z, false);
+    } else {
+        z = Math.fround(z);
+        assertFloat32(z, true);
+    }
+    assertFloat32(z, false);
+    return z;
+}
+
+function g(x,y,z) {
+    var z;
+    if (x) {
+        if (y) {
+            z = 3;
+        } else {
+            z = 6;
+        }
+        assertFloat32(z, false);
+    } else {
+        z = Math.fround(z);
+        assertFloat32(z, true);
+    }
+    assertFloat32(z, true);
+    return z;
+}
+
+setJitCompilerOption("ion.usecount.trigger", 50);
+
+for (var n = 100; n--; ) {
+    assertEq(f(0,1,2), 2);
+    assertEq(f(0,0,2), 2);
+    assertEq(f(1,0,2), 0xfffffff);
+    assertEq(f(1,1,2), 0xfffffff);
+
+    assertEq(g(0,1,2), 2);
+    assertEq(g(0,0,2), 2);
+    assertEq(g(1,0,2), 6);
+    assertEq(g(1,1,2), 3);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug939868.js
@@ -0,0 +1,3 @@
+function f(x, y) { return x || Math.fround(y); }
+assertEq(f(0, 0), 0);
+assertEq(f(0xfffffff, 0), 0xfffffff);
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -447,36 +447,33 @@ GuessPhiType(MPhi *phi)
                 // The operand is a phi we tried to specialize, but we were
                 // unable to guess its type. propagateSpecialization will
                 // propagate the type to this phi when it becomes known.
                 continue;
             }
         }
         if (type == MIRType_None) {
             type = in->type();
-            if (in->isConstant())
+            if (in->canProduceFloat32())
                 convertibleToFloat32 = true;
             continue;
         }
         if (type != in->type()) {
             // Ignore operands which we've never observed.
             if (in->resultTypeSet() && in->resultTypeSet()->empty())
                 continue;
 
-            if (IsFloatType(type) && IsFloatType(in->type())) {
-                // Specialize phis with int32 and float32 operands as float32.
-                type = MIRType_Float32;
-            } else if (convertibleToFloat32 && in->type() == MIRType_Float32) {
-                // If we only saw constants before and encounter a Float32 value, promote previous
-                // constants to Float32
+            if (convertibleToFloat32 && in->type() == MIRType_Float32) {
+                // If we only saw definitions that can be converted into Float32 before and
+                // encounter a Float32 value, promote previous values to Float32
                 type = MIRType_Float32;
             } else if (IsNumberType(type) && IsNumberType(in->type())) {
                 // Specialize phis with int32 and double operands as double.
                 type = MIRType_Double;
-                convertibleToFloat32 &= in->isConstant();
+                convertibleToFloat32 &= in->canProduceFloat32();
             } else {
                 return MIRType_Value;
             }
         }
     }
     return type;
 }
 
@@ -505,18 +502,20 @@ TypeAnalyzer::propagateSpecialization(MP
             // We tried to specialize this phi, but were unable to guess its
             // type. Now that we know the type of one of its operands, we can
             // specialize it.
             if (!respecialize(use, phi->type()))
                 return false;
             continue;
         }
         if (use->type() != phi->type()) {
-            // Specialize phis with int32 and float operands as floats.
-            if (IsFloatType(use->type()) && IsFloatType(phi->type())) {
+            // Specialize phis with int32 that can be converted to float and float operands as floats.
+            if ((use->type() == MIRType_Int32 && use->canProduceFloat32() && phi->type() == MIRType_Float32) ||
+                (phi->type() == MIRType_Int32 && phi->canProduceFloat32() && use->type() == MIRType_Float32))
+            {
                 if (!respecialize(use, MIRType_Float32))
                     return false;
                 continue;
             }
 
             // Specialize phis with int32 and double operands as double.
             if (IsNumberType(use->type()) && IsNumberType(phi->type())) {
                 if (!respecialize(use, MIRType_Double))
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -841,19 +841,17 @@ MakeMIRTypeSet(MIRType type)
 
 void
 jit::MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
                 MIRType newType, types::TemporaryTypeSet *newTypeSet)
 {
     if (newTypeSet && newTypeSet->empty())
         return;
     if (newType != *ptype) {
-        if (IsFloatType(newType) && IsFloatType(*ptype)) {
-            *ptype = MIRType_Float32;
-        } else if (IsNumberType(newType) && IsNumberType(*ptype)) {
+        if (IsNumberType(newType) && IsNumberType(*ptype)) {
             *ptype = MIRType_Double;
         } else if (*ptype != MIRType_Value) {
             if (!*ptypeSet)
                 *ptypeSet = MakeMIRTypeSet(*ptype);
             *ptype = MIRType_Value;
         } else if (*ptypeSet && (*ptypeSet)->empty()) {
             *ptype = newType;
         }