Bug 969203: Take out non strictly commutative Float32 functions; r=sstangl
authorBenjamin Bouvier <benj@benj.me>
Thu, 27 Feb 2014 14:24:59 +0100
changeset 171024 5d9d0a9f3e1f301f99b2f920b1bda85b25e9e3ba
parent 171023 3834353710588f4e2d2bba565127eb7782b781af
child 171025 9bd0b172034c1e763afa36765272fb187f8a9055
push id26308
push userryanvm@gmail.com
push dateThu, 27 Feb 2014 21:55:01 +0000
treeherdermozilla-central@82508f3c2088 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs969203
milestone30.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 969203: Take out non strictly commutative Float32 functions; r=sstangl
js/src/jit-test/tests/asm.js/testFloat32.js
js/src/jit-test/tests/ion/bug969203.js
js/src/jit-test/tests/ion/testFloat32-trigo.js
js/src/jit-test/tests/ion/testFloat32.js
js/src/jit/AsmJS.cpp
js/src/jit/AsmJSModule.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/MIR.h
js/src/jit/shared/Assembler-shared.h
--- a/js/src/jit-test/tests/asm.js/testFloat32.js
+++ b/js/src/jit-test/tests/asm.js/testFloat32.js
@@ -127,32 +127,39 @@ assertEq(asmLink(asmCompile('glob', USE_
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return +sqrt(x);} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(1.5); return sqrt(x) | 0;} return f");
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(2.25); return toF(sqrt(x))} return f"), this)(), Math.fround(1.5));
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f() {var x = toF(-1.); return toF(sqrt(x))} return f"), this)(), NaN);
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; var inf = glob.Infinity; function f() {var x = toF(0.); x = toF(inf); return toF(sqrt(x))} return f"), this)(), Infinity);
 
 // float?s
 assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var sqrt = glob.Math.sqrt; function f(x) { x = toF(x); f32[0] = x; return toF(sqrt(f32[0])) } return f"), this, null, heap)(64), Math.fround(8));
-assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var cos = glob.Math.cos; function f(x) { x = toF(x); f32[0] = x; return toF(cos(f32[0])) } return f"), this, null, heap)(3.141592653), -1);
+
+// The only other Math functions that can receive float32 as arguments and that strictly commute are floor and ceil (see
+// also bug 969203).
+var floorModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.floor; function f(x) {x = toF(x); return toF(g(x))} return f"), this);
+for (v of [-10.5, -1.2345, -1, 0, 1, 3.141592653, 13.37, Math.Infinity, NaN])
+    assertEq(floorModule(v), Math.fround(Math.floor(Math.fround(v))));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var floor = glob.Math.floor; function f(x) { x = toF(x); f32[0] = x; return toF(floor(f32[0])) } return f"), this, null, heap)(13.37), 13);
 
-// All Math functions with arity 1 behave like cos and sin
-var cosModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return toF(g(x))} return f"), this);
-for (v of [0, 3.141592653, Math.Infinity, NaN])
-    assertEq(cosModule(v), Math.fround(Math.cos(Math.fround(v))));
+var ceilModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.ceil; function f(x) {x = toF(x); return toF(g(x))} return f"), this);
+for (v of [-10.5, -1.2345, -1, 0, 1, 3.141592653, 13.37, Math.Infinity, NaN])
+    assertEq(ceilModule(v), Math.fround(Math.ceil(Math.fround(v))));
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var ceil = glob.Math.ceil; function f(x) { x = toF(x); f32[0] = x; return toF(ceil(f32[0])) } return f"), this, null, heap)(13.37), 14);
 
-var sinModule = asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.sin; function f(x) {x = toF(x); return toF(g(x))} return f"), this);
-for (v of [0, 3.141592653, Math.Infinity, NaN])
-    assertEq(sinModule(v), Math.fround(Math.sin(Math.fround(v))));
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return toF(g(x))} return f");
+assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = +x; return toF(g(+x))} return f");
 
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return +(g(x))} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = +x; return toF(g(x))} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = x|0; return toF(g(x))} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) {x = toF(x); return g(x) | 0} return f");
 
+assertEq(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + HEAP32 + TO_FLOAT32 + "var g = glob.Math.cos; function f(x) { x = toF(x); return toF(+g(+x)) } return f"), this, null, heap)(3.14159265358), -1);
+
 // Math functions with arity of two are not specialized for floats, so we shouldn't feed them with floats arguments or
 // return type
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(g(x, 2.))} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return +g(x, 2.)} return f");
 assertAsmTypeFail('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(g(+x, 2.))} return f");
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return +g(+x, 2.)} return f"), this)(3), 9);
 assertEq(asmLink(asmCompile('glob', USE_ASM + TO_FLOAT32 + "var g = glob.Math.pow; function f(x) {x = toF(x); return toF(+g(+x, 2.))} return f"), this)(3), 9);
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug969203.js
@@ -0,0 +1,4 @@
+var f = function (x) {
+    return Math.tan(Math.fround(Math.log(Math.fround(Math.exp(x)))));
+}
+assertEq(f(1), f(1));
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/testFloat32-trigo.js
+++ /dev/null
@@ -1,346 +0,0 @@
-// These tests have been separated, for several reasons:
-// - If we try to run them in a loop (i.e. running through all values in the array),
-// it doesn't get Ion compiled because of the size of the overall function.
-// - If we try to make, for each Math function, a closure that tests all values, the
-// order of running functions has an influence on whether the tests pass or fail (due
-// to bailouts).
-//
-// These tests have been generated by a Python script.
-//
-setJitCompilerOption("ion.usecount.trigger", 50);
-
-// MMath
-function repeat(f) {
-    for (var i = 200; i; i--) {
-        f();
-    }
-}
-
-function assertNear(a, b) {
-    var r = (a != a && b != b) || Math.abs(a-b) < 1e-7 || a === b;
-    if (!r) {
-        print('Precision error: ');
-        print(new Error().stack);
-        print('Got', a, ', expected near', b);
-        assertEq(false, true);
-    }
-}
-
-var trigoInputs = [0, Math.PI / 3, Math.PI, Math.PI * 3 / 4, 1, 1/3, -.5, NaN];
-var f32 = new Float32Array(8);
-for(var i = 0; i < trigoInputs.length; i++) {
-    f32[i] = trigoInputs[i];
-}
-
-function testcos () {
-        var r32, r64;
-
-        r32 = Math.fround(Math.cos(f32[0]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[0]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[1]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[1]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[2]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[2]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[3]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[3]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[4]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[4]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[5]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[5]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[6]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[6]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.cos(f32[7]));
-        assertFloat32(r32, true);
-        r64 = Math.cos(f32[7]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-}
-repeat(testcos);
-function testacos () {
-        var r32, r64;
-
-        r32 = Math.fround(Math.acos(f32[0]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[0]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[1]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[1]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[2]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[2]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[3]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[3]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[4]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[4]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[5]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[5]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[6]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[6]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.acos(f32[7]));
-        assertFloat32(r32, true);
-        r64 = Math.acos(f32[7]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-}
-repeat(testacos);
-function testsin () {
-        var r32, r64;
-
-        r32 = Math.fround(Math.sin(f32[0]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[0]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[1]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[1]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[2]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[2]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[3]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[3]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[4]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[4]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[5]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[5]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[6]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[6]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.sin(f32[7]));
-        assertFloat32(r32, true);
-        r64 = Math.sin(f32[7]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-}
-repeat(testsin);
-function testasin () {
-        var r32, r64;
-
-        r32 = Math.fround(Math.asin(f32[0]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[0]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[1]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[1]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[2]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[2]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[3]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[3]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[4]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[4]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[5]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[5]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[6]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[6]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.asin(f32[7]));
-        assertFloat32(r32, true);
-        r64 = Math.asin(f32[7]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-}
-repeat(testasin);
-function testtan () {
-        var r32, r64;
-
-        r32 = Math.fround(Math.tan(f32[0]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[0]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[1]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[1]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[2]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[2]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[3]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[3]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[4]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[4]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[5]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[5]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[6]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[6]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.tan(f32[7]));
-        assertFloat32(r32, true);
-        r64 = Math.tan(f32[7]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-}
-repeat(testtan);
-function testatan () {
-        var r32, r64;
-
-        r32 = Math.fround(Math.atan(f32[0]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[0]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[1]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[1]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[2]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[2]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[3]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[3]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[4]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[4]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[5]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[5]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[6]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[6]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-
-        r32 = Math.fround(Math.atan(f32[7]));
-        assertFloat32(r32, true);
-        r64 = Math.atan(f32[7]);
-        assertFloat32(r64, false);
-        assertNear(r32, r64);
-}
-repeat(testatan);
--- a/js/src/jit-test/tests/ion/testFloat32.js
+++ b/js/src/jit-test/tests/ion/testFloat32.js
@@ -159,42 +159,42 @@ test(acceptAbs);
 
 function refuseAbs() {
     var res = Math.abs(f32[0]);
     assertFloat32(res, false);
     f64[0] = res + 1;
 }
 test(refuseAbs);
 
-function acceptTrigo() {
+function refuseTrigo() {
     var res = Math.cos(f32[0]);
     f32[0] = res;
-    assertFloat32(res, true);
+    assertFloat32(res, false);
 
     var res = Math.sin(f32[0]);
     f32[0] = res;
-    assertFloat32(res, true);
+    assertFloat32(res, false);
 
     var res = Math.tan(f32[0]);
     f32[0] = res;
-    assertFloat32(res, true);
+    assertFloat32(res, false);
 
     var res = Math.acos(f32[0]);
     f32[0] = res;
-    assertFloat32(res, true);
+    assertFloat32(res, false);
 
     var res = Math.asin(f32[0]);
     f32[0] = res;
-    assertFloat32(res, true);
+    assertFloat32(res, false);
 
     res = Math.atan(f32[0]);
     f32[0] = res;
-    assertFloat32(res, true);
+    assertFloat32(res, false);
 }
-test(acceptTrigo);
+test(refuseTrigo);
 
 function refuseMath() {
     var res = Math.log10(f32[0]);
     f32[0] = res;
     assertFloat32(res, false);
 
     res = Math.log2(f32[0]);
     f32[0] = res;
@@ -293,17 +293,17 @@ function alternateCond(n) {
 function phiTest(n) {
     var x = (f32[0]);
     var y = n;
     if (n > 0) {
         x = x + 2;
         assertFloat32(x, true);
     } else {
         if (n < -10) {
-            x = Math.fround(Math.cos(y));
+            x = Math.fround(Math.sqrt(y));
             assertFloat32(x, true);
         } else {
             x = x - 1;
             assertFloat32(x, true);
         }
     }
     assertFloat32(x, true);
     f32[0] = x;
@@ -318,17 +318,17 @@ function phiTest(n) {
 function mixedPhiTest(n) {
     var x = (f32[0]);
     var y = n;
     if (n > 0) {
         x = x + 2; // non consumer because of (1)
         assertFloat32(x, false);
     } else {
         if (n < -10) {
-            x = Math.fround(Math.cos(y)); // new producer
+            x = Math.fround(Math.sqrt(y)); // new producer
             assertFloat32(x, true);
         } else {
             x = x - 1; // non consumer because of (1)
             assertFloat32(x, false);
         }
     }
     assertFloat32(x, false);
     x = x + 1; // (1) non consumer
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -4131,27 +4131,27 @@ CheckMathBuiltinCall(FunctionCompiler &f
     AsmJSImmKind doubleCallee, floatCallee;
     switch (func) {
       case AsmJSMathBuiltin_imul:   return CheckMathIMul(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_abs:    return CheckMathAbs(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_sqrt:   return CheckMathSqrt(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_fround: return CheckMathFRound(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_min:    return CheckMathMinMax(f, callNode, retType, def, type, /* isMax = */ false);
       case AsmJSMathBuiltin_max:    return CheckMathMinMax(f, callNode, retType, def, type, /* isMax = */ true);
-      case AsmJSMathBuiltin_sin:    arity = 1; doubleCallee = AsmJSImm_SinD; floatCallee = AsmJSImm_SinF;      break;
-      case AsmJSMathBuiltin_cos:    arity = 1; doubleCallee = AsmJSImm_CosD; floatCallee = AsmJSImm_CosF;      break;
-      case AsmJSMathBuiltin_tan:    arity = 1; doubleCallee = AsmJSImm_TanD; floatCallee = AsmJSImm_TanF;      break;
-      case AsmJSMathBuiltin_asin:   arity = 1; doubleCallee = AsmJSImm_ASinD; floatCallee = AsmJSImm_ASinF;    break;
-      case AsmJSMathBuiltin_acos:   arity = 1; doubleCallee = AsmJSImm_ACosD; floatCallee = AsmJSImm_ACosF;    break;
-      case AsmJSMathBuiltin_atan:   arity = 1; doubleCallee = AsmJSImm_ATanD; floatCallee = AsmJSImm_ATanF;    break;
-      case AsmJSMathBuiltin_ceil:   arity = 1; doubleCallee = AsmJSImm_CeilD; floatCallee = AsmJSImm_CeilF;    break;
+      case AsmJSMathBuiltin_ceil:   arity = 1; doubleCallee = AsmJSImm_CeilD;  floatCallee = AsmJSImm_CeilF;   break;
       case AsmJSMathBuiltin_floor:  arity = 1; doubleCallee = AsmJSImm_FloorD; floatCallee = AsmJSImm_FloorF;  break;
-      case AsmJSMathBuiltin_exp:    arity = 1; doubleCallee = AsmJSImm_ExpD; floatCallee = AsmJSImm_ExpF;      break;
-      case AsmJSMathBuiltin_log:    arity = 1; doubleCallee = AsmJSImm_LogD; floatCallee = AsmJSImm_LogF;      break;
-      case AsmJSMathBuiltin_pow:    arity = 2; doubleCallee = AsmJSImm_PowD; floatCallee = AsmJSImm_Invalid;   break;
+      case AsmJSMathBuiltin_sin:    arity = 1; doubleCallee = AsmJSImm_SinD;   floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_cos:    arity = 1; doubleCallee = AsmJSImm_CosD;   floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_tan:    arity = 1; doubleCallee = AsmJSImm_TanD;   floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_asin:   arity = 1; doubleCallee = AsmJSImm_ASinD;  floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_acos:   arity = 1; doubleCallee = AsmJSImm_ACosD;  floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_atan:   arity = 1; doubleCallee = AsmJSImm_ATanD;  floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_exp:    arity = 1; doubleCallee = AsmJSImm_ExpD;   floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_log:    arity = 1; doubleCallee = AsmJSImm_LogD;   floatCallee = AsmJSImm_Invalid; break;
+      case AsmJSMathBuiltin_pow:    arity = 2; doubleCallee = AsmJSImm_PowD;   floatCallee = AsmJSImm_Invalid; break;
       case AsmJSMathBuiltin_atan2:  arity = 2; doubleCallee = AsmJSImm_ATan2D; floatCallee = AsmJSImm_Invalid; break;
       default: MOZ_ASSUME_UNREACHABLE("unexpected mathBuiltin function");
     }
 
     if (retType == RetType::Float && floatCallee == AsmJSImm_Invalid)
         return f.fail(callNode, "math builtin cannot be used as float");
     if (retType != RetType::Double && retType != RetType::Float)
         return f.failf(callNode, "return type of math function is double or float, used as %s", retType.toType().toChars());
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -243,54 +243,38 @@ AddressOf(AsmJSImmKind kind, ExclusiveCo
         return RedirectCall(FuncCast(__aeabi_idivmod), Args_General2);
       case AsmJSImm_aeabi_uidivmod:
         return RedirectCall(FuncCast(__aeabi_uidivmod), Args_General2);
 #endif
       case AsmJSImm_ModD:
         return RedirectCall(FuncCast(NumberMod), Args_Double_DoubleDouble);
       case AsmJSImm_SinD:
         return RedirectCall(FuncCast<double (double)>(sin), Args_Double_Double);
-      case AsmJSImm_SinF:
-        return RedirectCall(FuncCast<float (float)>(sinf), Args_Float32_Float32);
       case AsmJSImm_CosD:
         return RedirectCall(FuncCast<double (double)>(cos), Args_Double_Double);
-      case AsmJSImm_CosF:
-        return RedirectCall(FuncCast<float (float)>(cosf), Args_Float32_Float32);
       case AsmJSImm_TanD:
         return RedirectCall(FuncCast<double (double)>(tan), Args_Double_Double);
-      case AsmJSImm_TanF:
-        return RedirectCall(FuncCast<float (float)>(tanf), Args_Float32_Float32);
       case AsmJSImm_ASinD:
         return RedirectCall(FuncCast<double (double)>(asin), Args_Double_Double);
-      case AsmJSImm_ASinF:
-        return RedirectCall(FuncCast<float (float)>(asinf), Args_Float32_Float32);
       case AsmJSImm_ACosD:
         return RedirectCall(FuncCast<double (double)>(acos), Args_Double_Double);
-      case AsmJSImm_ACosF:
-        return RedirectCall(FuncCast<float (float)>(acosf), Args_Float32_Float32);
       case AsmJSImm_ATanD:
         return RedirectCall(FuncCast<double (double)>(atan), Args_Double_Double);
-      case AsmJSImm_ATanF:
-        return RedirectCall(FuncCast<float (float)>(atanf), Args_Float32_Float32);
       case AsmJSImm_CeilD:
         return RedirectCall(FuncCast<double (double)>(ceil), Args_Double_Double);
       case AsmJSImm_CeilF:
         return RedirectCall(FuncCast<float (float)>(ceilf), Args_Float32_Float32);
       case AsmJSImm_FloorD:
         return RedirectCall(FuncCast<double (double)>(floor), Args_Double_Double);
       case AsmJSImm_FloorF:
         return RedirectCall(FuncCast<float (float)>(floorf), Args_Float32_Float32);
       case AsmJSImm_ExpD:
         return RedirectCall(FuncCast<double (double)>(exp), Args_Double_Double);
-      case AsmJSImm_ExpF:
-        return RedirectCall(FuncCast<float (float)>(expf), Args_Float32_Float32);
       case AsmJSImm_LogD:
         return RedirectCall(FuncCast<double (double)>(log), Args_Double_Double);
-      case AsmJSImm_LogF:
-        return RedirectCall(FuncCast<float (float)>(logf), Args_Float32_Float32);
       case AsmJSImm_PowD:
         return RedirectCall(FuncCast(ecmaPow), Args_Double_DoubleDouble);
       case AsmJSImm_ATan2D:
         return RedirectCall(FuncCast(ecmaAtan2), Args_Double_DoubleDouble);
       case AsmJSImm_Invalid:
         break;
     }
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4323,24 +4323,16 @@ CodeGenerator::visitMathFunctionF(LMathF
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
 
     masm.setupUnalignedABICall(1, temp);
     masm.passABIArg(input, MoveOp::FLOAT32);
 
     void *funptr = nullptr;
     switch (ins->mir()->function()) {
-      case MMathFunction::Log:   funptr = JS_FUNC_TO_DATA_PTR(void *, logf);   break;
-      case MMathFunction::Sin:   funptr = JS_FUNC_TO_DATA_PTR(void *, sinf);   break;
-      case MMathFunction::Cos:   funptr = JS_FUNC_TO_DATA_PTR(void *, cosf);   break;
-      case MMathFunction::Exp:   funptr = JS_FUNC_TO_DATA_PTR(void *, expf);   break;
-      case MMathFunction::Tan:   funptr = JS_FUNC_TO_DATA_PTR(void *, tanf);   break;
-      case MMathFunction::ATan:  funptr = JS_FUNC_TO_DATA_PTR(void *, atanf);  break;
-      case MMathFunction::ASin:  funptr = JS_FUNC_TO_DATA_PTR(void *, asinf);  break;
-      case MMathFunction::ACos:  funptr = JS_FUNC_TO_DATA_PTR(void *, acosf);  break;
       case MMathFunction::Floor: funptr = JS_FUNC_TO_DATA_PTR(void *, floorf); break;
       case MMathFunction::Ceil:  funptr = JS_FUNC_TO_DATA_PTR(void *, ceilf);  break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function");
     }
 
     masm.callWithABI(funptr, MoveOp::FLOAT32);
     return true;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3925,20 +3925,17 @@ class MMathFunction
         return true;
     }
 
     void printOpcode(FILE *fp) const;
 
     static const char *FunctionName(Function function);
 
     bool isFloat32Commutative() const {
-        return function_ == Log || function_ == Sin || function_ == Cos
-               || function_ == Exp || function_ == Tan || function_ == ATan
-               || function_ == ASin || function_ == ACos || function_ == Floor
-               || function_ == Ceil;
+        return function_ == Floor || function_ == Ceil;
     }
     void trySpecializeFloat32(TempAllocator &alloc);
     void computeRange(TempAllocator &alloc);
 };
 
 class MAdd : public MBinaryArithInstruction
 {
     // Is this instruction really an int at heart?
--- a/js/src/jit/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -686,35 +686,27 @@ enum AsmJSImmKind
     AsmJSImm_EnableActivationFromAsmJS,
     AsmJSImm_DisableActivationFromAsmJS,
 #if defined(JS_CODEGEN_ARM)
     AsmJSImm_aeabi_idivmod,
     AsmJSImm_aeabi_uidivmod,
 #endif
     AsmJSImm_ModD,
     AsmJSImm_SinD,
-    AsmJSImm_SinF,
     AsmJSImm_CosD,
-    AsmJSImm_CosF,
     AsmJSImm_TanD,
-    AsmJSImm_TanF,
     AsmJSImm_ASinD,
-    AsmJSImm_ASinF,
     AsmJSImm_ACosD,
-    AsmJSImm_ACosF,
     AsmJSImm_ATanD,
-    AsmJSImm_ATanF,
     AsmJSImm_CeilD,
     AsmJSImm_CeilF,
     AsmJSImm_FloorD,
     AsmJSImm_FloorF,
     AsmJSImm_ExpD,
-    AsmJSImm_ExpF,
     AsmJSImm_LogD,
-    AsmJSImm_LogF,
     AsmJSImm_PowD,
     AsmJSImm_ATan2D,
     AsmJSImm_Invalid
 };
 
 // Pointer to be embedded as an immediate in asm.js code.
 class AsmJSImmPtr
 {