Bug 1301400: Baseline Wasm Compiler: Part 3: Implement ConvertI64, r=lth
authorh4writer <hv1989@gmail.com>
Thu, 29 Sep 2016 22:33:22 +0200
changeset 315903 7c97d5898871280008baf27b37c98d2e22e52ba5
parent 315902 07b4fdd7588aab05136af8c7802d2737d50448ec
child 315904 90989a3b070d3c61961274e842c6ef305b84992a
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1301400
milestone52.0a1
Bug 1301400: Baseline Wasm Compiler: Part 3: Implement ConvertI64, r=lth
js/src/asmjs/WasmBaselineCompile.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm64/MacroAssembler-arm64.h
js/src/jit/mips32/MacroAssembler-mips32.cpp
js/src/jit/mips32/MacroAssembler-mips32.h
js/src/jit/mips64/MacroAssembler-mips64.cpp
js/src/jit/mips64/MacroAssembler-mips64.h
js/src/jit/none/MacroAssembler-none.h
js/src/jit/x64/CodeGenerator-x64.cpp
js/src/jit/x64/Lowering-x64.cpp
js/src/jit/x64/MacroAssembler-x64.cpp
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x86-shared/LIR-x86-shared.h
js/src/jit/x86/CodeGenerator-x86.cpp
js/src/jit/x86/Lowering-x86.cpp
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -2757,33 +2757,41 @@ class BaseCompiler
             masm.wasmTruncateDoubleToInt64(src.reg, dest.reg, ool->entry(),
                                            ool->rejoin(), temp.reg);
 #else
         MOZ_CRASH("BaseCompiler platform hook: truncateF64ToI64");
 #endif
         return true;
     }
 
-    void convertI64ToF32(RegI64 src, bool isUnsigned, RegF32 dest) {
-#ifdef JS_CODEGEN_X64
+    bool convertI64ToFloatNeedsTemp(bool isUnsigned) const {
+#if defined(JS_CODEGEN_X86)
+        return isUnsigned && AssemblerX86Shared::HasSSE3();
+#else
+        return false;
+#endif
+    }
+
+    void convertI64ToF32(RegI64 src, bool isUnsigned, RegF32 dest, RegI32 temp) {
+#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
         if (isUnsigned)
-            masm.convertUInt64ToFloat32(src.reg.reg, dest.reg);
+            masm.convertUInt64ToFloat32(src.reg, dest.reg, temp.reg);
         else
-            masm.convertInt64ToFloat32(src.reg.reg, dest.reg);
+            masm.convertInt64ToFloat32(src.reg, dest.reg);
 #else
         MOZ_CRASH("BaseCompiler platform hook: convertI64ToF32");
 #endif
     }
 
-    void convertI64ToF64(RegI64 src, bool isUnsigned, RegF64 dest) {
-#ifdef JS_CODEGEN_X64
+    void convertI64ToF64(RegI64 src, bool isUnsigned, RegF64 dest, RegI32 temp) {
+#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
         if (isUnsigned)
-            masm.convertUInt64ToDouble(src.reg.reg, dest.reg);
+            masm.convertUInt64ToDouble(src.reg, dest.reg, temp.reg);
         else
-            masm.convertInt64ToDouble(src.reg.reg, dest.reg);
+            masm.convertInt64ToDouble(src.reg, dest.reg);
 #else
         MOZ_CRASH("BaseCompiler platform hook: convertI32ToF64");
 #endif
     }
 
     void cmp64Set(Assembler::Condition cond, RegI64 lhs, RegI64 rhs, RegI32 dest) {
 #if defined(JS_CODEGEN_X64)
         masm.cmpq(rhs.reg.reg, lhs.reg.reg);
@@ -4323,27 +4331,32 @@ BaseCompiler::emitConvertU32ToF32()
     pushF32(f0);
 }
 
 void
 BaseCompiler::emitConvertI64ToF32()
 {
     RegI64 r0 = popI64();
     RegF32 f0 = needF32();
-    convertI64ToF32(r0, IsUnsigned(false), f0);
+    convertI64ToF32(r0, IsUnsigned(false), f0, RegI32());
     freeI64(r0);
     pushF32(f0);
 }
 
 void
 BaseCompiler::emitConvertU64ToF32()
 {
     RegI64 r0 = popI64();
     RegF32 f0 = needF32();
-    convertI64ToF32(r0, IsUnsigned(true), f0);
+    RegI32 temp;
+    if (convertI64ToFloatNeedsTemp(IsUnsigned(true)))
+        temp = needI32();
+    convertI64ToF32(r0, IsUnsigned(true), f0, temp);
+    if (temp.reg != Register::Invalid())
+        freeI32(temp);
     freeI64(r0);
     pushF32(f0);
 }
 
 void
 BaseCompiler::emitConvertF32ToF64()
 {
     RegF32 r0 = popF32();
@@ -4373,27 +4386,32 @@ BaseCompiler::emitConvertU32ToF64()
     pushF64(d0);
 }
 
 void
 BaseCompiler::emitConvertI64ToF64()
 {
     RegI64 r0 = popI64();
     RegF64 d0 = needF64();
-    convertI64ToF64(r0, IsUnsigned(false), d0);
+    convertI64ToF64(r0, IsUnsigned(false), d0, RegI32());
     freeI64(r0);
     pushF64(d0);
 }
 
 void
 BaseCompiler::emitConvertU64ToF64()
 {
     RegI64 r0 = popI64();
     RegF64 d0 = needF64();
-    convertI64ToF64(r0, IsUnsigned(true), d0);
+    RegI32 temp;
+    if (convertI64ToFloatNeedsTemp(IsUnsigned(true)))
+        temp = needI32();
+    convertI64ToF64(r0, IsUnsigned(true), d0, temp);
+    if (temp.reg != Register::Invalid())
+        freeI32(temp);
     freeI64(r0);
     pushF64(d0);
 }
 
 void
 BaseCompiler::emitReinterpretI32AsF32()
 {
     RegI32 r0 = popI32();
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -11899,17 +11899,20 @@ CodeGenerator::visitRandom(LRandom* ins)
     masm.add64(s0Reg, s1Reg);
 
     // See comment in XorShift128PlusRNG::nextDouble().
     static const int MantissaBits = FloatingPoint<double>::kExponentShift + 1;
     static const double ScaleInv = double(1) / (1ULL << MantissaBits);
 
     masm.and64(Imm64((1ULL << MantissaBits) - 1), s1Reg);
 
-    masm.convertUInt64ToDouble(s1Reg, tempReg, output);
+    if (masm.convertUInt64ToDoubleNeedsTemp())
+        masm.convertUInt64ToDouble(s1Reg, output, tempReg);
+    else
+        masm.convertUInt64ToDouble(s1Reg, output, Register::Invalid());
 
     // output *= ScaleInv
     masm.mulDoublePtr(ImmPtr(&ScaleInv), tempReg, output);
 }
 
 void
 CodeGenerator::visitSignExtend(LSignExtend* ins)
 {
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -88,19 +88,26 @@ MacroAssemblerARM::convertUInt32ToDouble
     // Direct conversions aren't possible.
     VFPRegister dest = VFPRegister(dest_);
     as_vxfer(src, InvalidReg, dest.uintOverlay(), CoreToFloat);
     as_vcvt(dest, dest.uintOverlay());
 }
 
 static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
 
-void
-MacroAssemblerARMCompat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
-{
+bool
+MacroAssemblerARMCompat::convertUInt64ToDoubleNeedsTemp()
+{
+    return false;
+}
+
+void
+MacroAssemblerARMCompat::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
+{
+    MOZ_ASSERT(temp == Register::Invalid());
     convertUInt32ToDouble(src.high, dest);
     movePtr(ImmPtr(&TO_DOUBLE_HIGH_SCALE), ScratchRegister);
     loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
     asMasm().mulDouble(ScratchDoubleReg, dest);
     convertUInt32ToDouble(src.low, ScratchDoubleReg);
     asMasm().addDouble(ScratchDoubleReg, dest);
 }
 
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1324,17 +1324,18 @@ class MacroAssemblerARMCompat : public M
     void cmpPtr(Register lhs, ImmGCPtr rhs);
     void cmpPtr(Register lhs, Imm32 rhs);
     void cmpPtr(const Address& lhs, Register rhs);
     void cmpPtr(const Address& lhs, ImmWord rhs);
     void cmpPtr(const Address& lhs, ImmPtr rhs);
     void cmpPtr(const Address& lhs, ImmGCPtr rhs);
     void cmpPtr(const Address& lhs, Imm32 rhs);
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
+    static bool convertUInt64ToDoubleNeedsTemp();
+    void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
 
     void setStackArg(Register reg, uint32_t arg);
 
     void breakpoint();
     // Conditional breakpoint.
     void breakpoint(Condition cc);
 
     // Trigger the simulator's interactive read-eval-print loop.
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -2233,17 +2233,22 @@ class MacroAssemblerCompat : public vixl
 #endif
     }
 
     void abiret() {
         syncStackPtr(); // SP is always used to transmit the stack between calls.
         vixl::MacroAssembler::Ret(vixl::lr);
     }
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest) {
+    bool convertUInt64ToDoubleNeedsTemp() {
+        return false;
+    }
+
+    void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp) {
+        MOZ_ASSERT(temp == Register::Invalid());
         Ucvtf(ARMFPRegister(dest, 64), ARMRegister(src.reg, 64));
     }
 
     void clampCheck(Register r, Label* handleNotAnInt) {
         MOZ_CRASH("clampCheck");
     }
 
     void stackCheck(ImmWord limitAddr, Label* label) {
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -74,19 +74,26 @@ MacroAssemblerMIPSCompat::convertUInt32T
 
     // Add unsigned value of INT32_MIN
     ma_lid(SecondScratchDoubleReg, 2147483648.0);
     as_addd(dest, dest, SecondScratchDoubleReg);
 }
 
 static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
 
+bool
+MacroAssemblerMIPSCompat::convertUInt64ToDoubleNeedsTemp()
+{
+    return false;
+}
+
 void
-MacroAssemblerMIPSCompat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
+MacroAssemblerMIPSCompat::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
 {
+    MOZ_ASSERT(temp == Register::Invalid());
     convertUInt32ToDouble(src.high, dest);
     loadConstantDouble(TO_DOUBLE_HIGH_SCALE, ScratchDoubleReg);
     asMasm().mulDouble(ScratchDoubleReg, dest);
     convertUInt32ToDouble(src.low, ScratchDoubleReg);
     asMasm().addDouble(ScratchDoubleReg, dest);
 }
 
 void
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -936,17 +936,18 @@ class MacroAssemblerMIPSCompat : public 
         as_movd(dest, src);
     }
 
     void zeroDouble(FloatRegister reg) {
         moveToDoubleLo(zero, reg);
         moveToDoubleHi(zero, reg);
     }
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
+    static bool convertUInt64ToDoubleNeedsTemp();
+    void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
 
     void breakpoint();
 
     void checkStackAlignment();
 
     void alignStackPointer();
     void restoreStackPointer();
     static void calculateAlignedStackPointer(void** stackPointer);
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -69,19 +69,27 @@ MacroAssemblerMIPS64Compat::convertUInt3
     as_mtc1(ScratchRegister, dest);
     as_cvtdw(dest, dest);
 
     // Add unsigned value of INT32_MIN
     ma_lid(SecondScratchDoubleReg, 2147483648.0);
     as_addd(dest, dest, SecondScratchDoubleReg);
 }
 
+bool
+MacroAssemblerMIPS64Compat::convertUInt64ToDoubleNeedsTemp()
+{
+    return false;
+}
+
 void
-MacroAssemblerMIPS64Compat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
+MacroAssemblerMIPS64Compat::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
 {
+    MOZ_ASSERT(temp == Register::Invalid());
+
     Label positive, done;
     ma_b(src.reg, src.reg, &positive, NotSigned, ShortJump);
 
     MOZ_ASSERT(src.reg != ScratchRegister);
     MOZ_ASSERT(src.reg != SecondScratchReg);
 
     ma_and(ScratchRegister, src.reg, Imm32(1));
     ma_dsrl(SecondScratchReg, src.reg, Imm32(1));
--- a/js/src/jit/mips64/MacroAssembler-mips64.h
+++ b/js/src/jit/mips64/MacroAssembler-mips64.h
@@ -941,17 +941,18 @@ class MacroAssemblerMIPS64Compat : publi
     void moveDouble(FloatRegister src, FloatRegister dest) {
         as_movd(dest, src);
     }
 
     void zeroDouble(FloatRegister reg) {
         moveToDouble(zero, reg);
     }
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
+    static bool convertUInt64ToDoubleNeedsTemp();
+    void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
 
     void breakpoint();
 
     void checkStackAlignment();
 
     static void calculateAlignedStackPointer(void** stackPointer);
 
     // If source is a double, load it into dest. If source is int32,
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -375,17 +375,18 @@ class MacroAssemblerNone : public Assemb
     void convertDoubleToInt32(FloatRegister, Register, Label*, bool v = true) { MOZ_CRASH(); }
     void convertBoolToInt32(Register, Register) { MOZ_CRASH(); }
 
     void convertDoubleToFloat32(FloatRegister, FloatRegister) { MOZ_CRASH(); }
     void convertInt32ToFloat32(Register, FloatRegister) { MOZ_CRASH(); }
 
     template <typename T> void convertInt32ToDouble(T, FloatRegister) { MOZ_CRASH(); }
     void convertFloat32ToDouble(FloatRegister, FloatRegister) { MOZ_CRASH(); }
-    void convertUInt64ToDouble(Register64, Register, FloatRegister) { MOZ_CRASH(); }
+    static bool convertUInt64ToDoubleNeedsTemp() { MOZ_CRASH(); }
+    void convertUInt64ToDouble(Register64, FloatRegister, Register) { MOZ_CRASH(); }
 
     void boolValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
     void boolValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }
     void int32ValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
     void int32ValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }
 
     void loadConstantDouble(double, FloatRegister) { MOZ_CRASH(); }
     void loadConstantFloat32(float, FloatRegister) { MOZ_CRASH(); }
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -834,30 +834,30 @@ CodeGeneratorX64::visitWasmTruncateToInt
         else
             masm.wasmTruncateFloat32ToInt64(input, output, oolEntry, oolRejoin, temp);
     }
 }
 
 void
 CodeGeneratorX64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
 {
-    Register input = ToRegister(lir->input());
+    Register64 input = ToRegister64(lir->getInt64Operand(0));
     FloatRegister output = ToFloatRegister(lir->output());
 
     MIRType outputType = lir->mir()->type();
     MOZ_ASSERT(outputType == MIRType::Double || outputType == MIRType::Float32);
 
     if (outputType == MIRType::Double) {
         if (lir->mir()->isUnsigned())
-            masm.convertUInt64ToDouble(input, output);
+            masm.convertUInt64ToDouble(input, output, Register::Invalid());
         else
             masm.convertInt64ToDouble(input, output);
     } else {
         if (lir->mir()->isUnsigned())
-            masm.convertUInt64ToFloat32(input, output);
+            masm.convertUInt64ToFloat32(input, output, Register::Invalid());
         else
             masm.convertInt64ToFloat32(input, output);
     }
 }
 
 void
 CodeGeneratorX64::visitNotI64(LNotI64* lir)
 {
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -480,16 +480,16 @@ LIRGeneratorX64::visitWasmTruncateToInt6
 
 void
 LIRGeneratorX64::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
 {
     MDefinition* opd = ins->input();
     MOZ_ASSERT(opd->type() == MIRType::Int64);
     MOZ_ASSERT(IsFloatingPointType(ins->type()));
 
-    define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
+    define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd), LDefinition::BogusTemp()), ins);
 }
 
 void
 LIRGeneratorX64::visitExtendInt32ToInt64(MExtendInt32ToInt64* ins)
 {
     defineInt64(new(alloc()) LExtendInt32ToInt64(useAtStart(ins->input())), ins);
 }
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -80,79 +80,90 @@ MacroAssemblerX64::loadConstantSimd128Fl
     SimdData* val = getSimdData(v);
     if (!val)
         return;
     JmpSrc j = masm.vmovaps_ripr(dest.encoding());
     propagateOOM(val->uses.append(CodeOffset(j.offset())));
 }
 
 void
-MacroAssemblerX64::convertInt64ToDouble(Register input, FloatRegister output)
+MacroAssemblerX64::convertInt64ToDouble(Register64 input, FloatRegister output)
 {
     // Zero the output register to break dependencies, see convertInt32ToDouble.
     zeroDouble(output);
 
-    vcvtsq2sd(input, output, output);
+    vcvtsq2sd(input.reg, output, output);
 }
 
 void
-MacroAssemblerX64::convertInt64ToFloat32(Register input, FloatRegister output)
+MacroAssemblerX64::convertInt64ToFloat32(Register64 input, FloatRegister output)
 {
     // Zero the output register to break dependencies, see convertInt32ToDouble.
     zeroFloat32(output);
 
-    vcvtsq2ss(input, output, output);
+    vcvtsq2ss(input.reg, output, output);
 }
+
+bool
+MacroAssemblerX64::convertUInt64ToDoubleNeedsTemp()
+{
+    return false;
+}
+
 void
-MacroAssemblerX64::convertUInt64ToDouble(Register input, FloatRegister output)
+MacroAssemblerX64::convertUInt64ToDouble(Register64 input, FloatRegister output, Register temp)
 {
+    MOZ_ASSERT(temp == Register::Invalid());
+
     // Zero the output register to break dependencies, see convertInt32ToDouble.
     zeroDouble(output);
 
     // If the input's sign bit is not set we use vcvtsq2sd directly.
     // Else, we divide by 2, convert to double, and multiply the result by 2.
     Label done;
     Label isSigned;
 
-    testq(input, input);
+    testq(input.reg, input.reg);
     j(Assembler::Signed, &isSigned);
-    vcvtsq2sd(input, output, output);
+    vcvtsq2sd(input.reg, output, output);
     jump(&done);
 
     bind(&isSigned);
 
     ScratchRegisterScope scratch(asMasm());
-    mov(input, scratch);
+    mov(input.reg, scratch);
     shrq(Imm32(1), scratch);
     vcvtsq2sd(scratch, output, output);
     vaddsd(output, output, output);
 
     bind(&done);
 }
 
 void
-MacroAssemblerX64::convertUInt64ToFloat32(Register input, FloatRegister output)
+MacroAssemblerX64::convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp)
 {
+    MOZ_ASSERT(temp == Register::Invalid());
+
     // Zero the output register to break dependencies, see convertInt32ToDouble.
     zeroFloat32(output);
 
     // If the input's sign bit is not set we use vcvtsq2ss directly.
     // Else, we divide by 2, convert to float, and multiply the result by 2.
     Label done;
     Label isSigned;
 
-    testq(input, input);
+    testq(input.reg, input.reg);
     j(Assembler::Signed, &isSigned);
-    vcvtsq2ss(input, output, output);
+    vcvtsq2ss(input.reg, output, output);
     jump(&done);
 
     bind(&isSigned);
 
     ScratchRegisterScope scratch(asMasm());
-    mov(input, scratch);
+    mov(input.reg, scratch);
     shrq(Imm32(1), scratch);
     vcvtsq2ss(scratch, output, output);
     vaddss(output, output, output);
 
     bind(&done);
 }
 
 void
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -865,21 +865,21 @@ class MacroAssemblerX64 : public MacroAs
     void loadConstantDouble(double d, FloatRegister dest);
     void loadConstantFloat32(float f, FloatRegister dest);
     void loadConstantDouble(wasm::RawF64 d, FloatRegister dest);
     void loadConstantFloat32(wasm::RawF32 f, FloatRegister dest);
 
     void loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest);
     void loadConstantSimd128Float(const SimdConstant& v, FloatRegister dest);
 
-    void convertInt64ToDouble(Register input, FloatRegister output);
-    void convertInt64ToFloat32(Register input, FloatRegister output);
-
-    void convertUInt64ToDouble(Register input, FloatRegister output);
-    void convertUInt64ToFloat32(Register input, FloatRegister output);
+    void convertInt64ToDouble(Register64 input, FloatRegister output);
+    void convertInt64ToFloat32(Register64 input, FloatRegister output);
+    static bool convertUInt64ToDoubleNeedsTemp();
+    void convertUInt64ToDouble(Register64 input, FloatRegister output, Register temp);
+    void convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp);
 
     void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                    Label* oolRejoin, FloatRegister tempDouble);
     void wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                     Label* oolRejoin, FloatRegister tempDouble);
 
     void wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                     Label* oolRejoin, FloatRegister tempDouble);
@@ -938,25 +938,27 @@ class MacroAssemblerX64 : public MacroAs
         }
     }
 
     void loadInstructionPointerAfterCall(Register dest) {
         loadPtr(Address(StackPointer, 0x0), dest);
     }
 
     void convertUInt32ToDouble(Register src, FloatRegister dest) {
+        // Zero the output register to break dependencies, see convertInt32ToDouble.
+        zeroDouble(dest);
+
         vcvtsq2sd(src, dest, dest);
     }
 
     void convertUInt32ToFloat32(Register src, FloatRegister dest) {
-        vcvtsq2ss(src, dest, dest);
-    }
+        // Zero the output register to break dependencies, see convertInt32ToDouble.
+        zeroDouble(dest);
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest) {
-        vcvtsi2sdq(src.reg, dest);
+        vcvtsq2ss(src, dest, dest);
     }
 
     inline void incrementInt32Value(const Address& addr);
 
     inline void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
 
   public:
     void handleFailureWithHandlerTail(void* handler);
--- a/js/src/jit/x86-shared/LIR-x86-shared.h
+++ b/js/src/jit/x86-shared/LIR-x86-shared.h
@@ -380,26 +380,31 @@ class LSimdValueFloat32x4 : public LInst
         setTemp(0, copyY);
     }
 
     MSimdValueX4* mir() const {
         return mir_->toSimdValueX4();
     }
 };
 
-class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 0>
+class LInt64ToFloatingPoint : public LInstructionHelper<1, INT64_PIECES, 1>
 {
   public:
     LIR_HEADER(Int64ToFloatingPoint);
 
-    explicit LInt64ToFloatingPoint(const LInt64Allocation& in) {
+    explicit LInt64ToFloatingPoint(const LInt64Allocation& in, const LDefinition& temp) {
         setInt64Operand(0, in);
+        setTemp(0, temp);
     }
 
     MInt64ToFloatingPoint* mir() const {
         return mir_->toInt64ToFloatingPoint();
     }
+
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
 };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x86_shared_LIR_x86_shared_h */
--- a/js/src/jit/x86/CodeGenerator-x86.cpp
+++ b/js/src/jit/x86/CodeGenerator-x86.cpp
@@ -1274,28 +1274,29 @@ CodeGeneratorX86::visitWasmTruncateToInt
     }
 }
 
 void
 CodeGeneratorX86::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
 {
     Register64 input = ToRegister64(lir->getInt64Operand(0));
     FloatRegister output = ToFloatRegister(lir->output());
+    Register temp = lir->temp()->isBogusTemp() ? InvalidReg : ToRegister(lir->temp());
 
     MIRType outputType = lir->mir()->type();
     MOZ_ASSERT(outputType == MIRType::Double || outputType == MIRType::Float32);
 
     if (outputType == MIRType::Double) {
         if (lir->mir()->isUnsigned())
-            masm.convertUInt64ToFloat64(input, output);
+            masm.convertUInt64ToDouble(input, output, temp);
         else
-            masm.convertInt64ToFloat64(input, output);
+            masm.convertInt64ToDouble(input, output);
     } else {
         if (lir->mir()->isUnsigned())
-            masm.convertUInt64ToFloat32(input, output);
+            masm.convertUInt64ToFloat32(input, output, temp);
         else
             masm.convertInt64ToFloat32(input, output);
     }
 }
 
 void
 CodeGeneratorX86::visitTestI64AndBranch(LTestI64AndBranch* lir)
 {
--- a/js/src/jit/x86/Lowering-x86.cpp
+++ b/js/src/jit/x86/Lowering-x86.cpp
@@ -633,17 +633,20 @@ LIRGeneratorX86::visitWasmTruncateToInt6
 
 void
 LIRGeneratorX86::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
 {
     MDefinition* opd = ins->input();
     MOZ_ASSERT(opd->type() == MIRType::Int64);
     MOZ_ASSERT(IsFloatingPointType(ins->type()));
 
-    define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
+    LDefinition maybeTemp =
+        (ins->isUnsigned() && AssemblerX86Shared::HasSSE3()) ? temp() : LDefinition::BogusTemp();
+
+    define(new(alloc()) LInt64ToFloatingPoint(useInt64Register(opd), maybeTemp), ins);
 }
 
 void
 LIRGeneratorX86::visitExtendInt32ToInt64(MExtendInt32ToInt64* ins)
 {
     if (ins->isUnsigned()) {
         defineInt64(new(alloc()) LExtendInt32ToInt64(useRegisterAtStart(ins->input())), ins);
     } else {
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -27,27 +27,47 @@ MOZ_ALIGNED_DECL(static const uint64_t, 
     0x4530000043300000LL,
     0x0LL,
     0x4330000000000000LL,
     0x4530000000000000LL
 };
 
 static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
 
+bool
+MacroAssemblerX86::convertUInt64ToDoubleNeedsTemp()
+{
+    return HasSSE3();
+}
+
 void
-MacroAssemblerX86::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
+MacroAssemblerX86::convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp)
 {
     // SUBPD needs SSE2, HADDPD needs SSE3.
     if (!HasSSE3()) {
-        convertUInt32ToDouble(src.high, dest);
-        movePtr(ImmPtr(&TO_DOUBLE_HIGH_SCALE), temp);
-        loadDouble(Address(temp, 0), ScratchDoubleReg);
-        asMasm().mulDouble(ScratchDoubleReg, dest);
-        convertUInt32ToDouble(src.low, ScratchDoubleReg);
-        asMasm().addDouble(ScratchDoubleReg, dest);
+        MOZ_ASSERT(temp == Register::Invalid());
+
+        // Zero the dest register to break dependencies, see convertInt32ToDouble.
+        zeroDouble(dest);
+
+        asMasm().Push(src.high);
+        asMasm().Push(src.low);
+        fild(Operand(esp, 0));
+
+        Label notNegative;
+        asMasm().branch32(Assembler::NotSigned, src.high, Imm32(0), &notNegative);
+        double add_constant = 18446744073709551616.0; // 2^64
+        store64(Imm64(mozilla::BitwiseCast<uint64_t>(add_constant)), Address(esp, 0));
+        fld(Operand(esp, 0));
+        faddp();
+        bind(&notNegative);
+
+        fstp(Operand(esp, 0));
+        vmovsd(Address(esp, 0), dest);
+        asMasm().freeStack(2*sizeof(intptr_t));
         return;
     }
 
     // Following operation uses entire 128-bit of dest XMM register.
     // Currently higher 64-bit is free when we have access to lower 64-bit.
     MOZ_ASSERT(dest.size() == 8);
     FloatRegister dest128 = FloatRegister(dest.encoding(), FloatRegisters::Simd128);
 
@@ -65,17 +85,17 @@ MacroAssemblerX86::convertUInt64ToDouble
     vpunpckldq(ScratchSimd128Reg, dest128, dest128);
 
     // Unpack and interleave dest and a constant C1 to dest:
     //   C1       = 0x 00000000 00000000  45300000 43300000
     //   dest     = 0x 45300000 HHHHHHHH  43300000 LLLLLLLL
     // here, each 64-bit part of dest represents following double:
     //   HI(dest) = 0x 1.00000HHHHHHHH * 2**84 == 2**84 + 0x HHHHHHHH 00000000
     //   LO(dest) = 0x 1.00000LLLLLLLL * 2**52 == 2**52 + 0x 00000000 LLLLLLLL
-    movePtr(ImmPtr(TO_DOUBLE), temp);
+    movePtr(ImmWord((uintptr_t)TO_DOUBLE), temp);
     vpunpckldq(Operand(temp, 0), dest128, dest128);
 
     // Subtract a constant C2 from dest, for each 64-bit part:
     //   C2       = 0x 45300000 00000000  43300000 00000000
     // here, each 64-bit part of C2 represents following double:
     //   HI(C2)   = 0x 1.0000000000000 * 2**84 == 2**84
     //   LO(C2)   = 0x 1.0000000000000 * 2**52 == 2**52
     // after the operation each 64-bit part of dest represents following:
@@ -802,16 +822,45 @@ MacroAssembler::wasmTruncateFloat32ToUIn
     or32(Imm32(0x80000000), output);
 
     bind(&done);
 }
 
 //}}} check_macroassembler_style
 
 void
+MacroAssemblerX86::convertInt64ToDouble(Register64 input, FloatRegister output)
+{
+    // Zero the output register to break dependencies, see convertInt32ToDouble.
+    zeroDouble(output);
+
+    asMasm().Push(input.high);
+    asMasm().Push(input.low);
+    fild(Operand(esp, 0));
+
+    fstp(Operand(esp, 0));
+    vmovsd(Address(esp, 0), output);
+    asMasm().freeStack(2*sizeof(intptr_t));
+}
+
+void
+MacroAssemblerX86::convertInt64ToFloat32(Register64 input, FloatRegister output)
+{
+    convertInt64ToDouble(input, output);
+    convertDoubleToFloat32(output, output);
+}
+
+void
+MacroAssemblerX86::convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp)
+{
+    convertUInt64ToDouble(input, output.asDouble(), temp);
+    convertDoubleToFloat32(output, output);
+}
+
+void
 MacroAssemblerX86::wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                              Label* oolRejoin, FloatRegister tempReg)
 {
     Label fail, convert;
     Register temp = output.high;
 
     // Make sure input fits in (u)int64.
     asMasm().reserveStack(2 * sizeof(int32_t));
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -829,17 +829,21 @@ class MacroAssemblerX86 : public MacroAs
     }
 
     // Note: this function clobbers the source register.
     inline void convertUInt32ToDouble(Register src, FloatRegister dest);
 
     // Note: this function clobbers the source register.
     inline void convertUInt32ToFloat32(Register src, FloatRegister dest);
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
+    void convertUInt64ToFloat32(Register64 src, FloatRegister dest, Register temp);
+    void convertInt64ToFloat32(Register64 src, FloatRegister dest);
+    static bool convertUInt64ToDoubleNeedsTemp();
+    void convertUInt64ToDouble(Register64 src, FloatRegister dest, Register temp);
+    void convertInt64ToDouble(Register64 src, FloatRegister dest);
 
     void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                    Label* oolRejoin, FloatRegister tempDouble);
     void wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                     Label* oolRejoin, FloatRegister tempDouble);
     void wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output, Label* oolEntry,
                                     Label* oolRejoin, FloatRegister tempDouble);
     void wasmTruncateFloat32ToUInt64(FloatRegister input, Register64 output, Label* oolEntry,