Bug 969203 - Take out non strictly commutative Float32 functions. r=sstangl, a=sledru
authorBenjamin Bouvier <benj@benj.me>
Thu, 27 Feb 2014 14:24:59 +0100
changeset 183644 7e9b33204db9
parent 183643 13bf6fe8df1f
child 183645 9933fa36efa5
push id3434
push userryanvm@gmail.com
push date2014-04-07 16:57 +0000
treeherdermozilla-beta@004a7c15d761 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl, sledru
bugs969203
milestone29.0
Bug 969203 - Take out non strictly commutative Float32 functions. r=sstangl, a=sledru
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
@@ -130,32 +130,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);
 
-// 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))));
+// 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);
 
-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))));
+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);
+
+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
@@ -4026,27 +4026,27 @@ CheckMathBuiltinCall(FunctionCompiler &f
 {
     unsigned arity = 0;
     AsmJSImmKind doubleCallee, floatCallee;
     switch (mathBuiltin) {
       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_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_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_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_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");
     }
 
     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
@@ -241,54 +241,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
@@ -4316,24 +4316,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
@@ -3921,20 +3921,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
 {