Bug 1639113 part 2 - Move LRound/LRoundF code to the MacroAssembler. r=evilpie
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 19 May 2020 19:26:39 +0000
changeset 530977 bc823c0fd292a2fcf0d67f83dd8e44424309014d
parent 530976 180e48bc3c41023efa4be7773104c1d7699317eb
child 530978 c8cc2b35542280e7c20ec51309c343d609b5df8b
push id37435
push userapavel@mozilla.com
push dateWed, 20 May 2020 15:28:23 +0000
treeherdermozilla-central@5415da14ec9a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie
bugs1639113
milestone78.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 1639113 part 2 - Move LRound/LRoundF code to the MacroAssembler. r=evilpie Depends on D75955 Differential Revision: https://phabricator.services.mozilla.com/D75957
js/src/jit/CodeGenerator.cpp
js/src/jit/MacroAssembler.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm64/CodeGenerator-arm64.cpp
js/src/jit/arm64/MacroAssembler-arm64.cpp
js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8562,16 +8562,36 @@ void CodeGenerator::visitModD(LModD* ins
   } else {
     masm.setupUnalignedABICall(ToRegister(ins->temp()));
     masm.passABIArg(lhs, MoveOp::DOUBLE);
     masm.passABIArg(rhs, MoveOp::DOUBLE);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NumberMod), MoveOp::DOUBLE);
   }
 }
 
+void CodeGenerator::visitRound(LRound* lir) {
+  FloatRegister input = ToFloatRegister(lir->input());
+  FloatRegister temp = ToFloatRegister(lir->temp());
+  Register output = ToRegister(lir->output());
+
+  Label bail;
+  masm.roundDoubleToInt32(input, output, temp, &bail);
+  bailoutFrom(&bail, lir->snapshot());
+}
+
+void CodeGenerator::visitRoundF(LRoundF* lir) {
+  FloatRegister input = ToFloatRegister(lir->input());
+  FloatRegister temp = ToFloatRegister(lir->temp());
+  Register output = ToRegister(lir->output());
+
+  Label bail;
+  masm.roundFloat32ToInt32(input, output, temp, &bail);
+  bailoutFrom(&bail, lir->snapshot());
+}
+
 void CodeGenerator::emitCompareS(LInstruction* lir, JSOp op, Register left,
                                  Register right, Register output) {
   MOZ_ASSERT(lir->isCompareS() || lir->isCompareStrictS());
 
   OutOfLineCode* ool = nullptr;
 
   using Fn = bool (*)(JSContext*, HandleString, HandleString, bool*);
   if (op == JSOp::Eq || op == JSOp::StrictEq) {
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1003,16 +1003,21 @@ class MacroAssembler : public MacroAssem
 
   inline void absFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
   inline void absDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
   inline void sqrtFloat32(FloatRegister src,
                           FloatRegister dest) PER_SHARED_ARCH;
   inline void sqrtDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
+  void roundFloat32ToInt32(FloatRegister src, Register dest, FloatRegister temp,
+                           Label* fail) PER_SHARED_ARCH;
+  void roundDoubleToInt32(FloatRegister src, Register dest, FloatRegister temp,
+                          Label* fail) PER_SHARED_ARCH;
+
   // srcDest = {min,max}{Float32,Double}(srcDest, other)
   // For min and max, handle NaN specially if handleNaN is true.
 
   inline void minFloat32(FloatRegister other, FloatRegister srcDest,
                          bool handleNaN) PER_SHARED_ARCH;
   inline void minDouble(FloatRegister other, FloatRegister srcDest,
                         bool handleNaN) PER_SHARED_ARCH;
 
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1216,38 +1216,16 @@ void CodeGenerator::visitCeil(LCeil* lir
 void CodeGenerator::visitCeilF(LCeilF* lir) {
   FloatRegister input = ToFloatRegister(lir->input());
   Register output = ToRegister(lir->output());
   Label bail;
   masm.ceilf(input, output, &bail);
   bailoutFrom(&bail, lir->snapshot());
 }
 
-void CodeGenerator::visitRound(LRound* lir) {
-  FloatRegister input = ToFloatRegister(lir->input());
-  Register output = ToRegister(lir->output());
-  FloatRegister tmp = ToFloatRegister(lir->temp());
-  Label bail;
-  // Output is either correct, or clamped. All -0 cases have been translated
-  // to a clamped case.
-  masm.round(input, output, &bail, tmp);
-  bailoutFrom(&bail, lir->snapshot());
-}
-
-void CodeGenerator::visitRoundF(LRoundF* lir) {
-  FloatRegister input = ToFloatRegister(lir->input());
-  Register output = ToRegister(lir->output());
-  FloatRegister tmp = ToFloatRegister(lir->temp());
-  Label bail;
-  // Output is either correct, or clamped. All -0 cases have been translated
-  // to a clamped case.
-  masm.roundf(input, output, &bail, tmp);
-  bailoutFrom(&bail, lir->snapshot());
-}
-
 void CodeGenerator::visitTrunc(LTrunc* lir) {
   FloatRegister input = ToFloatRegister(lir->input());
   Register output = ToRegister(lir->output());
   Label bail;
   masm.trunc(input, output, &bail);
   bailoutFrom(&bail, lir->snapshot());
 }
 
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -5760,16 +5760,26 @@ void MacroAssembler::patchNearAddressMov
 // Spectre Mitigations.
 
 void MacroAssembler::speculationBarrier() {
   // Spectre mitigation recommended by ARM for cases where csel/cmov cannot be
   // used.
   as_csdb();
 }
 
+void MacroAssembler::roundFloat32ToInt32(FloatRegister src, Register dest,
+                                         FloatRegister temp, Label* fail) {
+  roundf(src, dest, fail, temp);
+}
+
+void MacroAssembler::roundDoubleToInt32(FloatRegister src, Register dest,
+                                        FloatRegister temp, Label* fail) {
+  round(src, dest, fail, temp);
+}
+
 //}}} check_macroassembler_style
 
 void MacroAssemblerARM::wasmTruncateToInt32(FloatRegister input,
                                             Register output, MIRType fromType,
                                             bool isUnsigned, bool isSaturating,
                                             Label* oolEntry) {
   ScratchDoubleScope scratchScope(asMasm());
   ScratchRegisterScope scratchReg(asMasm());
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -1176,170 +1176,16 @@ void CodeGenerator::visitCeilF(LCeilF* l
   FloatRegister input = ToFloatRegister(lir->input());
   Register output = ToRegister(lir->output());
 
   Label bailout;
   masm.ceilf(input, output, &bailout);
   bailoutFrom(&bailout, lir->snapshot());
 }
 
-void CodeGenerator::visitRound(LRound* lir) {
-  const FloatRegister input = ToFloatRegister(lir->input());
-  const ARMFPRegister input64(input, 64);
-  const FloatRegister temp = ToFloatRegister(lir->temp());
-  const Register output = ToRegister(lir->output());
-  ScratchDoubleScope scratch(masm);
-
-  Label negative, done;
-
-  // Branch to a slow path if input < 0.0 due to complicated rounding rules.
-  // Note that Fcmp with NaN unsets the negative flag.
-  masm.Fcmp(input64, 0.0);
-  masm.B(&negative, Assembler::Condition::lo);
-
-  // Handle the simple case of a positive input, and also -0 and NaN.
-  // Rounding proceeds with consideration of the fractional part of the input:
-  // 1. If > 0.5, round to integer with higher absolute value (so, up).
-  // 2. If < 0.5, round to integer with lower absolute value (so, down).
-  // 3. If = 0.5, round to +Infinity (so, up).
-  {
-    // Convert to signed 32-bit integer, rounding halfway cases away from zero.
-    // In the case of overflow, the output is saturated.
-    // In the case of NaN and -0, the output is zero.
-    masm.Fcvtas(ARMRegister(output, 32), input64);
-    // If the output potentially saturated, take a bailout.
-    bailoutCmp32(Assembler::Equal, output, Imm32(INT_MAX), lir->snapshot());
-
-    // If the result of the rounding was non-zero, return the output.
-    // In the case of zero, the input may have been NaN or -0, which must bail.
-    masm.branch32(Assembler::NotEqual, output, Imm32(0), &done);
-    {
-      // If input is NaN, comparisons set the C and V bits of the NZCV flags.
-      masm.Fcmp(input64, 0.0);
-      bailoutIf(Assembler::Overflow, lir->snapshot());
-
-      // Move all 64 bits of the input into a scratch register to check for -0.
-      vixl::UseScratchRegisterScope temps(&masm.asVIXL());
-      const ARMRegister scratchGPR64 = temps.AcquireX();
-      masm.Fmov(scratchGPR64, input64);
-      masm.Cmp(scratchGPR64, vixl::Operand(uint64_t(0x8000000000000000)));
-      bailoutIf(Assembler::Equal, lir->snapshot());
-    }
-
-    masm.jump(&done);
-  }
-
-  // Handle the complicated case of a negative input.
-  // Rounding proceeds with consideration of the fractional part of the input:
-  // 1. If > 0.5, round to integer with higher absolute value (so, down).
-  // 2. If < 0.5, round to integer with lower absolute value (so, up).
-  // 3. If = 0.5, round to +Infinity (so, up).
-  masm.bind(&negative);
-  {
-    // Inputs in [-0.5, 0) need 0.5 added; other negative inputs need
-    // the biggest double less than 0.5.
-    Label join;
-    masm.loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
-    masm.loadConstantDouble(-0.5, scratch);
-    masm.branchDouble(Assembler::DoubleLessThan, input, scratch, &join);
-    masm.loadConstantDouble(0.5, temp);
-    masm.bind(&join);
-
-    masm.addDouble(input, temp);
-    // Round all values toward -Infinity.
-    // In the case of overflow, the output is saturated.
-    // NaN and -0 are already handled by the "positive number" path above.
-    masm.Fcvtms(ARMRegister(output, 32), temp);
-    // If the output potentially saturated, take a bailout.
-    bailoutCmp32(Assembler::Equal, output, Imm32(INT_MIN), lir->snapshot());
-
-    // If output is zero, then the actual result is -0. Bail.
-    bailoutTest32(Assembler::Zero, output, output, lir->snapshot());
-  }
-
-  masm.bind(&done);
-}
-
-void CodeGenerator::visitRoundF(LRoundF* lir) {
-  const FloatRegister input = ToFloatRegister(lir->input());
-  const ARMFPRegister input32(input, 32);
-  const FloatRegister temp = ToFloatRegister(lir->temp());
-  const Register output = ToRegister(lir->output());
-  ScratchFloat32Scope scratch(masm);
-
-  Label negative, done;
-
-  // Branch to a slow path if input < 0.0 due to complicated rounding rules.
-  // Note that Fcmp with NaN unsets the negative flag.
-  masm.Fcmp(input32, 0.0);
-  masm.B(&negative, Assembler::Condition::lo);
-
-  // Handle the simple case of a positive input, and also -0 and NaN.
-  // Rounding proceeds with consideration of the fractional part of the input:
-  // 1. If > 0.5, round to integer with higher absolute value (so, up).
-  // 2. If < 0.5, round to integer with lower absolute value (so, down).
-  // 3. If = 0.5, round to +Infinity (so, up).
-  {
-    // Convert to signed 32-bit integer, rounding halfway cases away from zero.
-    // In the case of overflow, the output is saturated.
-    // In the case of NaN and -0, the output is zero.
-    masm.Fcvtas(ARMRegister(output, 32), input32);
-    // If the output potentially saturated, take a bailout.
-    bailoutCmp32(Assembler::Equal, output, Imm32(INT_MAX), lir->snapshot());
-
-    // If the result of the rounding was non-zero, return the output.
-    // In the case of zero, the input may have been NaN or -0, which must bail.
-    masm.branch32(Assembler::NotEqual, output, Imm32(0), &done);
-    {
-      // If input is NaN, comparisons set the C and V bits of the NZCV flags.
-      masm.Fcmp(input32, 0.0f);
-      bailoutIf(Assembler::Overflow, lir->snapshot());
-
-      // Move all 32 bits of the input into a scratch register to check for -0.
-      vixl::UseScratchRegisterScope temps(&masm.asVIXL());
-      const ARMRegister scratchGPR32 = temps.AcquireW();
-      masm.Fmov(scratchGPR32, input32);
-      masm.Cmp(scratchGPR32, vixl::Operand(uint32_t(0x80000000)));
-      bailoutIf(Assembler::Equal, lir->snapshot());
-    }
-
-    masm.jump(&done);
-  }
-
-  // Handle the complicated case of a negative input.
-  // Rounding proceeds with consideration of the fractional part of the input:
-  // 1. If > 0.5, round to integer with higher absolute value (so, down).
-  // 2. If < 0.5, round to integer with lower absolute value (so, up).
-  // 3. If = 0.5, round to +Infinity (so, up).
-  masm.bind(&negative);
-  {
-    // Inputs in [-0.5, 0) need 0.5 added; other negative inputs need
-    // the biggest double less than 0.5.
-    Label join;
-    masm.loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
-    masm.loadConstantFloat32(-0.5f, scratch);
-    masm.branchFloat(Assembler::DoubleLessThan, input, scratch, &join);
-    masm.loadConstantFloat32(0.5f, temp);
-    masm.bind(&join);
-
-    masm.addFloat32(input, temp);
-    // Round all values toward -Infinity.
-    // In the case of overflow, the output is saturated.
-    // NaN and -0 are already handled by the "positive number" path above.
-    masm.Fcvtms(ARMRegister(output, 32), temp);
-    // If the output potentially saturated, take a bailout.
-    bailoutCmp32(Assembler::Equal, output, Imm32(INT_MIN), lir->snapshot());
-
-    // If output is zero, then the actual result is -0. Bail.
-    bailoutTest32(Assembler::Zero, output, output, lir->snapshot());
-  }
-
-  masm.bind(&done);
-}
-
 void CodeGenerator::visitTrunc(LTrunc* lir) {
   const FloatRegister input = ToFloatRegister(lir->input());
   const ARMFPRegister input64(input, 64);
   const Register output = ToRegister(lir->output());
   const ARMRegister output32(output, 32);
   const ARMRegister output64(output, 64);
 
   Label done, zeroCase;
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -2038,12 +2038,162 @@ void MacroAssembler::patchNearAddressMov
 // ========================================================================
 // Spectre Mitigations.
 
 void MacroAssembler::speculationBarrier() {
   // Conditional speculation barrier.
   csdb();
 }
 
+void MacroAssembler::roundFloat32ToInt32(FloatRegister src, Register dest,
+                                         FloatRegister temp, Label* fail) {
+  const ARMFPRegister src32(src, 32);
+  ScratchFloat32Scope scratch(*this);
+
+  Label negative, done;
+
+  // Branch to a slow path if input < 0.0 due to complicated rounding rules.
+  // Note that Fcmp with NaN unsets the negative flag.
+  Fcmp(src32, 0.0);
+  B(&negative, Assembler::Condition::lo);
+
+  // Handle the simple case of a positive input, and also -0 and NaN.
+  // Rounding proceeds with consideration of the fractional part of the input:
+  // 1. If > 0.5, round to integer with higher absolute value (so, up).
+  // 2. If < 0.5, round to integer with lower absolute value (so, down).
+  // 3. If = 0.5, round to +Infinity (so, up).
+  {
+    // Convert to signed 32-bit integer, rounding halfway cases away from zero.
+    // In the case of overflow, the output is saturated.
+    // In the case of NaN and -0, the output is zero.
+    Fcvtas(ARMRegister(dest, 32), src32);
+    // If the output potentially saturated, fail.
+    branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+
+    // If the result of the rounding was non-zero, return the output.
+    // In the case of zero, the input may have been NaN or -0, which must bail.
+    branch32(Assembler::NotEqual, dest, Imm32(0), &done);
+    {
+      // If input is NaN, comparisons set the C and V bits of the NZCV flags.
+      Fcmp(src32, 0.0f);
+      B(fail, Assembler::Overflow);
+
+      // Move all 32 bits of the input into a scratch register to check for -0.
+      vixl::UseScratchRegisterScope temps(this);
+      const ARMRegister scratchGPR32 = temps.AcquireW();
+      Fmov(scratchGPR32, src32);
+      Cmp(scratchGPR32, vixl::Operand(uint32_t(0x80000000)));
+      B(fail, Assembler::Equal);
+    }
+
+    jump(&done);
+  }
+
+  // Handle the complicated case of a negative input.
+  // Rounding proceeds with consideration of the fractional part of the input:
+  // 1. If > 0.5, round to integer with higher absolute value (so, down).
+  // 2. If < 0.5, round to integer with lower absolute value (so, up).
+  // 3. If = 0.5, round to +Infinity (so, up).
+  bind(&negative);
+  {
+    // Inputs in [-0.5, 0) need 0.5 added; other negative inputs need
+    // the biggest double less than 0.5.
+    Label join;
+    loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
+    loadConstantFloat32(-0.5f, scratch);
+    branchFloat(Assembler::DoubleLessThan, src, scratch, &join);
+    loadConstantFloat32(0.5f, temp);
+    bind(&join);
+
+    addFloat32(src, temp);
+    // Round all values toward -Infinity.
+    // In the case of overflow, the output is saturated.
+    // NaN and -0 are already handled by the "positive number" path above.
+    Fcvtms(ARMRegister(dest, 32), temp);
+    // If the output potentially saturated, fail.
+    branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
+
+    // If output is zero, then the actual result is -0. Fail.
+    branchTest32(Assembler::Zero, dest, dest, fail);
+  }
+
+  bind(&done);
+}
+
+void MacroAssembler::roundDoubleToInt32(FloatRegister src, Register dest,
+                                        FloatRegister temp, Label* fail) {
+  const ARMFPRegister src64(src, 64);
+  ScratchDoubleScope scratch(*this);
+
+  Label negative, done;
+
+  // Branch to a slow path if input < 0.0 due to complicated rounding rules.
+  // Note that Fcmp with NaN unsets the negative flag.
+  Fcmp(src64, 0.0);
+  B(&negative, Assembler::Condition::lo);
+
+  // Handle the simple case of a positive input, and also -0 and NaN.
+  // Rounding proceeds with consideration of the fractional part of the input:
+  // 1. If > 0.5, round to integer with higher absolute value (so, up).
+  // 2. If < 0.5, round to integer with lower absolute value (so, down).
+  // 3. If = 0.5, round to +Infinity (so, up).
+  {
+    // Convert to signed 32-bit integer, rounding halfway cases away from zero.
+    // In the case of overflow, the output is saturated.
+    // In the case of NaN and -0, the output is zero.
+    Fcvtas(ARMRegister(dest, 32), src64);
+    // If the output potentially saturated, fail.
+    branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+
+    // If the result of the rounding was non-zero, return the output.
+    // In the case of zero, the input may have been NaN or -0, which must bail.
+    branch32(Assembler::NotEqual, dest, Imm32(0), &done);
+    {
+      // If input is NaN, comparisons set the C and V bits of the NZCV flags.
+      Fcmp(src64, 0.0);
+      B(fail, Assembler::Overflow);
+
+      // Move all 64 bits of the input into a scratch register to check for -0.
+      vixl::UseScratchRegisterScope temps(this);
+      const ARMRegister scratchGPR64 = temps.AcquireX();
+      Fmov(scratchGPR64, src64);
+      Cmp(scratchGPR64, vixl::Operand(uint64_t(0x8000000000000000)));
+      B(fail, Assembler::Equal);
+    }
+
+    jump(&done);
+  }
+
+  // Handle the complicated case of a negative input.
+  // Rounding proceeds with consideration of the fractional part of the input:
+  // 1. If > 0.5, round to integer with higher absolute value (so, down).
+  // 2. If < 0.5, round to integer with lower absolute value (so, up).
+  // 3. If = 0.5, round to +Infinity (so, up).
+  bind(&negative);
+  {
+    // Inputs in [-0.5, 0) need 0.5 added; other negative inputs need
+    // the biggest double less than 0.5.
+    Label join;
+    loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
+    loadConstantDouble(-0.5, scratch);
+    branchDouble(Assembler::DoubleLessThan, src, scratch, &join);
+    loadConstantDouble(0.5, temp);
+    bind(&join);
+
+    addDouble(src, temp);
+    // Round all values toward -Infinity.
+    // In the case of overflow, the output is saturated.
+    // NaN and -0 are already handled by the "positive number" path above.
+    Fcvtms(ARMRegister(dest, 32), temp);
+    // If the output potentially saturated, fail.
+    branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
+
+    // If output is zero, then the actual result is -0. Fail.
+    branchTest32(Assembler::Zero, dest, dest, fail);
+  }
+
+  bind(&done);
+}
+
 //}}} check_macroassembler_style
 
 }  // namespace jit
 }  // namespace js
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -2848,9 +2848,20 @@ void MacroAssembler::patchNearAddressMov
                                           CodeLocationLabel target) {
   PatchDataWithValueCheck(loc, ImmPtr(target.raw()), ImmPtr(nullptr));
 }
 
 // ========================================================================
 // Spectre Mitigations.
 
 void MacroAssembler::speculationBarrier() { MOZ_CRASH(); }
+
+void MacroAssembler::roundFloat32ToInt32(FloatRegister src, Register dest,
+                                         FloatRegister temp, Label* fail) {
+  MOZ_CRASH("Port CodeGenerator::visitRoundF code");
+}
+
+void MacroAssembler::roundDoubleToInt32(FloatRegister src, Register dest,
+                                        FloatRegister temp, Label* fail) {
+  MOZ_CRASH("Port CodeGenerator::visitRound code");
+}
+
 //}}} check_macroassembler_style
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -2138,196 +2138,16 @@ void CodeGenerator::visitCeilF(LCeilF* l
 
   // x <= -1, truncation is the way to go.
   masm.bind(&lessThanMinusOne);
   bailoutCvttss2si(input, output, lir->snapshot());
 
   masm.bind(&end);
 }
 
-void CodeGenerator::visitRound(LRound* lir) {
-  FloatRegister input = ToFloatRegister(lir->input());
-  FloatRegister temp = ToFloatRegister(lir->temp());
-  ScratchDoubleScope scratch(masm);
-  Register output = ToRegister(lir->output());
-
-  Label negativeOrZero, negative, end, bailout;
-
-  // Branch to a slow path for non-positive inputs. Doesn't catch NaN.
-  masm.zeroDouble(scratch);
-  masm.loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
-  masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, scratch,
-                    &negativeOrZero);
-
-  // Input is positive. Add the biggest double less than 0.5 and
-  // truncate, rounding down (because if the input is the biggest double less
-  // than 0.5, adding 0.5 would undesirably round up to 1). Note that we have
-  // to add the input to the temp register because we're not allowed to
-  // modify the input register.
-  masm.addDouble(input, temp);
-  bailoutCvttsd2si(temp, output, lir->snapshot());
-
-  masm.jump(&end);
-
-  // Input is negative, +0 or -0.
-  masm.bind(&negativeOrZero);
-  // Branch on negative input.
-  masm.j(Assembler::NotEqual, &negative);
-
-  // Bail on negative-zero.
-  masm.branchNegativeZero(input, output, &bailout, /* maybeNonZero = */ false);
-  bailoutFrom(&bailout, lir->snapshot());
-
-  // Input is +0
-  masm.xor32(output, output);
-  masm.jump(&end);
-
-  // Input is negative.
-  masm.bind(&negative);
-
-  // Inputs in ]-0.5; 0] need to be added 0.5, other negative inputs need to
-  // be added the biggest double less than 0.5.
-  Label loadJoin;
-  masm.loadConstantDouble(-0.5, scratch);
-  masm.branchDouble(Assembler::DoubleLessThan, input, scratch, &loadJoin);
-  masm.loadConstantDouble(0.5, temp);
-  masm.bind(&loadJoin);
-
-  if (AssemblerX86Shared::HasSSE41()) {
-    // Add 0.5 and round toward -Infinity. The result is stored in the temp
-    // register (currently contains 0.5).
-    masm.addDouble(input, temp);
-    masm.vroundsd(X86Encoding::RoundDown, temp, scratch, scratch);
-
-    // Truncate.
-    bailoutCvttsd2si(scratch, output, lir->snapshot());
-
-    // If the result is positive zero, then the actual result is -0. Bail.
-    // Otherwise, the truncation will have produced the correct negative
-    // integer.
-    masm.test32(output, output);
-    bailoutIf(Assembler::Zero, lir->snapshot());
-  } else {
-    masm.addDouble(input, temp);
-
-    // Round toward -Infinity without the benefit of ROUNDSD.
-    {
-      // If input + 0.5 >= 0, input is a negative number >= -0.5 and the result
-      // is -0.
-      masm.compareDouble(Assembler::DoubleGreaterThanOrEqual, temp, scratch);
-      bailoutIf(Assembler::DoubleGreaterThanOrEqual, lir->snapshot());
-
-      // Truncate and round toward zero.
-      // This is off-by-one for everything but integer-valued inputs.
-      bailoutCvttsd2si(temp, output, lir->snapshot());
-
-      // Test whether the truncated double was integer-valued.
-      masm.convertInt32ToDouble(output, scratch);
-      masm.branchDouble(Assembler::DoubleEqualOrUnordered, temp, scratch, &end);
-
-      // Input is not integer-valued, so we rounded off-by-one in the
-      // wrong direction. Correct by subtraction.
-      masm.subl(Imm32(1), output);
-      // Cannot overflow: output was already checked against INT_MIN.
-    }
-  }
-
-  masm.bind(&end);
-}
-
-void CodeGenerator::visitRoundF(LRoundF* lir) {
-  FloatRegister input = ToFloatRegister(lir->input());
-  FloatRegister temp = ToFloatRegister(lir->temp());
-  ScratchFloat32Scope scratch(masm);
-  Register output = ToRegister(lir->output());
-
-  Label negativeOrZero, negative, end, bailout;
-
-  // Branch to a slow path for non-positive inputs. Doesn't catch NaN.
-  masm.zeroFloat32(scratch);
-  masm.loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
-  masm.branchFloat(Assembler::DoubleLessThanOrEqual, input, scratch,
-                   &negativeOrZero);
-
-  // Input is non-negative. Add the biggest float less than 0.5 and truncate,
-  // rounding down (because if the input is the biggest float less than 0.5,
-  // adding 0.5 would undesirably round up to 1). Note that we have to add
-  // the input to the temp register because we're not allowed to modify the
-  // input register.
-  masm.addFloat32(input, temp);
-
-  bailoutCvttss2si(temp, output, lir->snapshot());
-
-  masm.jump(&end);
-
-  // Input is negative, +0 or -0.
-  masm.bind(&negativeOrZero);
-  // Branch on negative input.
-  masm.j(Assembler::NotEqual, &negative);
-
-  // Bail on negative-zero.
-  masm.branchNegativeZeroFloat32(input, output, &bailout);
-  bailoutFrom(&bailout, lir->snapshot());
-
-  // Input is +0.
-  masm.xor32(output, output);
-  masm.jump(&end);
-
-  // Input is negative.
-  masm.bind(&negative);
-
-  // Inputs in ]-0.5; 0] need to be added 0.5, other negative inputs need to
-  // be added the biggest double less than 0.5.
-  Label loadJoin;
-  masm.loadConstantFloat32(-0.5f, scratch);
-  masm.branchFloat(Assembler::DoubleLessThan, input, scratch, &loadJoin);
-  masm.loadConstantFloat32(0.5f, temp);
-  masm.bind(&loadJoin);
-
-  if (AssemblerX86Shared::HasSSE41()) {
-    // Add 0.5 and round toward -Infinity. The result is stored in the temp
-    // register (currently contains 0.5).
-    masm.addFloat32(input, temp);
-    masm.vroundss(X86Encoding::RoundDown, temp, scratch, scratch);
-
-    // Truncate.
-    bailoutCvttss2si(scratch, output, lir->snapshot());
-
-    // If the result is positive zero, then the actual result is -0. Bail.
-    // Otherwise, the truncation will have produced the correct negative
-    // integer.
-    masm.test32(output, output);
-    bailoutIf(Assembler::Zero, lir->snapshot());
-  } else {
-    masm.addFloat32(input, temp);
-    // Round toward -Infinity without the benefit of ROUNDSS.
-    {
-      // If input + 0.5 >= 0, input is a negative number >= -0.5 and the result
-      // is -0.
-      masm.compareFloat(Assembler::DoubleGreaterThanOrEqual, temp, scratch);
-      bailoutIf(Assembler::DoubleGreaterThanOrEqual, lir->snapshot());
-
-      // Truncate and round toward zero.
-      // This is off-by-one for everything but integer-valued inputs.
-      bailoutCvttss2si(temp, output, lir->snapshot());
-
-      // Test whether the truncated double was integer-valued.
-      masm.convertInt32ToFloat32(output, scratch);
-      masm.branchFloat(Assembler::DoubleEqualOrUnordered, temp, scratch, &end);
-
-      // Input is not integer-valued, so we rounded off-by-one in the
-      // wrong direction. Correct by subtraction.
-      masm.subl(Imm32(1), output);
-      // Cannot overflow: output was already checked against INT_MIN.
-    }
-  }
-
-  masm.bind(&end);
-}
-
 void CodeGenerator::visitTrunc(LTrunc* lir) {
   FloatRegister input = ToFloatRegister(lir->input());
   Register output = ToRegister(lir->output());
 
   Label bailout, lessThanMinusOne;
 
   // Bail on ]-1; -0] range
   {
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -1532,9 +1532,181 @@ void MacroAssembler::atomicFetchOpJS(Sca
 
 void MacroAssembler::speculationBarrier() {
   // Spectre mitigation recommended by Intel and AMD suggest to use lfence as
   // a way to force all speculative execution of instructions to end.
   MOZ_ASSERT(HasSSE2());
   masm.lfence();
 }
 
+void MacroAssembler::roundFloat32ToInt32(FloatRegister src, Register dest,
+                                         FloatRegister temp, Label* fail) {
+  ScratchFloat32Scope scratch(*this);
+
+  Label negativeOrZero, negative, end;
+
+  // Branch to a slow path for non-positive inputs. Doesn't catch NaN.
+  zeroFloat32(scratch);
+  loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
+  branchFloat(Assembler::DoubleLessThanOrEqual, src, scratch, &negativeOrZero);
+  {
+    // Input is non-negative. Add the biggest float less than 0.5 and truncate,
+    // rounding down (because if the input is the biggest float less than 0.5,
+    // adding 0.5 would undesirably round up to 1). Note that we have to add the
+    // input to the temp register because we're not allowed to modify the input
+    // register.
+    addFloat32(src, temp);
+    truncateFloat32ToInt32(temp, dest, fail);
+    jump(&end);
+  }
+
+  // Input is negative, +0 or -0.
+  bind(&negativeOrZero);
+  {
+    // Branch on negative input.
+    j(Assembler::NotEqual, &negative);
+
+    // Fail on negative-zero.
+    branchNegativeZeroFloat32(src, dest, fail);
+
+    // Input is +0.
+    xor32(dest, dest);
+    jump(&end);
+  }
+
+  // Input is negative.
+  bind(&negative);
+  {
+    // Inputs in ]-0.5; 0] need to be added 0.5, other negative inputs need to
+    // be added the biggest double less than 0.5.
+    Label loadJoin;
+    loadConstantFloat32(-0.5f, scratch);
+    branchFloat(Assembler::DoubleLessThan, src, scratch, &loadJoin);
+    loadConstantFloat32(0.5f, temp);
+    bind(&loadJoin);
+
+    if (HasSSE41()) {
+      // Add 0.5 and round toward -Infinity. The result is stored in the temp
+      // register (currently contains 0.5).
+      addFloat32(src, temp);
+      vroundss(X86Encoding::RoundDown, temp, scratch, scratch);
+
+      // Truncate.
+      truncateFloat32ToInt32(scratch, dest, fail);
+
+      // If the result is positive zero, then the actual result is -0. Fail.
+      // Otherwise, the truncation will have produced the correct negative
+      // integer.
+      branchTest32(Assembler::Zero, dest, dest, fail);
+    } else {
+      addFloat32(src, temp);
+      // Round toward -Infinity without the benefit of ROUNDSS.
+      {
+        // If input + 0.5 >= 0, input is a negative number >= -0.5 and the
+        // result is -0.
+        branchFloat(Assembler::DoubleGreaterThanOrEqual, temp, scratch, fail);
+
+        // Truncate and round toward zero.
+        // This is off-by-one for everything but integer-valued inputs.
+        truncateFloat32ToInt32(temp, dest, fail);
+
+        // Test whether the truncated double was integer-valued.
+        convertInt32ToFloat32(dest, scratch);
+        branchFloat(Assembler::DoubleEqualOrUnordered, temp, scratch, &end);
+
+        // Input is not integer-valued, so we rounded off-by-one in the
+        // wrong direction. Correct by subtraction.
+        subl(Imm32(1), dest);
+        // Cannot overflow: output was already checked against INT_MIN.
+      }
+    }
+  }
+
+  bind(&end);
+}
+
+void MacroAssembler::roundDoubleToInt32(FloatRegister src, Register dest,
+                                        FloatRegister temp, Label* fail) {
+  ScratchDoubleScope scratch(*this);
+
+  Label negativeOrZero, negative, end;
+
+  // Branch to a slow path for non-positive inputs. Doesn't catch NaN.
+  zeroDouble(scratch);
+  loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
+  branchDouble(Assembler::DoubleLessThanOrEqual, src, scratch, &negativeOrZero);
+  {
+    // Input is positive. Add the biggest double less than 0.5 and truncate,
+    // rounding down (because if the input is the biggest double less than 0.5,
+    // adding 0.5 would undesirably round up to 1). Note that we have to add the
+    // input to the temp register because we're not allowed to modify the input
+    // register.
+    addDouble(src, temp);
+    truncateDoubleToInt32(temp, dest, fail);
+    jump(&end);
+  }
+
+  // Input is negative, +0 or -0.
+  bind(&negativeOrZero);
+  {
+    // Branch on negative input.
+    j(Assembler::NotEqual, &negative);
+
+    // Fail on negative-zero.
+    branchNegativeZero(src, dest, fail, /* maybeNonZero = */ false);
+
+    // Input is +0
+    xor32(dest, dest);
+    jump(&end);
+  }
+
+  // Input is negative.
+  bind(&negative);
+  {
+    // Inputs in ]-0.5; 0] need to be added 0.5, other negative inputs need to
+    // be added the biggest double less than 0.5.
+    Label loadJoin;
+    loadConstantDouble(-0.5, scratch);
+    branchDouble(Assembler::DoubleLessThan, src, scratch, &loadJoin);
+    loadConstantDouble(0.5, temp);
+    bind(&loadJoin);
+
+    if (HasSSE41()) {
+      // Add 0.5 and round toward -Infinity. The result is stored in the temp
+      // register (currently contains 0.5).
+      addDouble(src, temp);
+      vroundsd(X86Encoding::RoundDown, temp, scratch, scratch);
+
+      // Truncate.
+      truncateDoubleToInt32(scratch, dest, fail);
+
+      // If the result is positive zero, then the actual result is -0. Fail.
+      // Otherwise, the truncation will have produced the correct negative
+      // integer.
+      branchTest32(Assembler::Zero, dest, dest, fail);
+    } else {
+      addDouble(src, temp);
+      // Round toward -Infinity without the benefit of ROUNDSD.
+      {
+        // If input + 0.5 >= 0, input is a negative number >= -0.5 and the
+        // result is -0.
+        branchDouble(Assembler::DoubleGreaterThanOrEqual, temp, scratch, fail);
+
+        // Truncate and round toward zero.
+        // This is off-by-one for everything but integer-valued inputs.
+        truncateDoubleToInt32(temp, dest, fail);
+
+        // Test whether the truncated double was integer-valued.
+        convertInt32ToDouble(dest, scratch);
+        branchDouble(Assembler::DoubleEqualOrUnordered, temp, scratch, &end);
+
+        // Input is not integer-valued, so we rounded off-by-one in the
+        // wrong direction. Correct by subtraction.
+        subl(Imm32(1), dest);
+        // Cannot overflow: output was already checked against INT_MIN.
+      }
+    }
+  }
+
+  bind(&end);
+}
+
 //}}} check_macroassembler_style