commit dae7db185717d82df2e2bc88f51516a521785bc3
parent ea235975dec5afa224a49d9075948f2400ddb819
Author: André Bargull <andre.bargull@gmail.com>
Date: Fri, 17 Oct 2025 11:25:44 +0000
Bug 1994190 - Part 3: Simplify rounding instructions for loong64. r=spidermonkey-reviewers,iain
Perform the same changes for loong64.
This also ensures we don't bail for code like `Math.floor(0x7fff_ffff)` or
`Math.floor(-0x8000_0000)`. (Similar for other rounding instructions.)
Differential Revision: https://phabricator.services.mozilla.com/D268548
Diffstat:
2 files changed, 170 insertions(+), 221 deletions(-)
diff --git a/js/src/jit/loong64/MacroAssembler-loong64.cpp b/js/src/jit/loong64/MacroAssembler-loong64.cpp
@@ -4653,319 +4653,275 @@ void MacroAssembler::speculationBarrier() { MOZ_CRASH(); }
void MacroAssembler::floorFloat32ToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchFloat32Scope fpscratch(asMasm());
- FloatRegister scratch = fpscratch;
- Label skipCheck, done;
- // If Nan, 0 or -0 check for bailout
- loadConstantFloat32(0.0f, scratch);
- ma_bc_s(src, scratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
+ // Round toward negative infinity.
+ as_ftintrm_l_s(fpscratch, src);
+ moveFromDouble(fpscratch, dest);
- // If high part is not zero, it is NaN or -0, so we bail.
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
{
- UseScratchRegisterScope temps(asMasm());
+ UseScratchRegisterScope temps(*this);
Register scratch = temps.Acquire();
- moveFromDoubleLo(src, scratch);
- branch32(Assembler::NotEqual, scratch, zero, fail);
- }
-
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
- bind(&skipCheck);
- as_ftintrm_w_s(scratch, src);
- moveFromDoubleLo(scratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for -0 and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is -0 or NaN.
+ moveFromFloat32(src, dest);
+ as_srli_w(dest, dest, 30);
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::floorDoubleToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchDoubleScope fpscratch(asMasm());
- FloatRegister scratch = fpscratch;
- Label skipCheck, done;
- // If Nan, 0 or -0 check for bailout
- loadConstantDouble(0.0, scratch);
- ma_bc_d(src, scratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
+ // Round toward negative infinity.
+ as_ftintrm_l_d(fpscratch, src);
+ moveFromDouble(fpscratch, dest);
- // If high part is not zero, it is NaN or -0, so we bail.
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
{
- UseScratchRegisterScope temps(asMasm());
+ UseScratchRegisterScope temps(*this);
Register scratch = temps.Acquire();
- moveFromDoubleHi(src, scratch);
- branch32(Assembler::NotEqual, scratch, zero, fail);
- }
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
-
- bind(&skipCheck);
- as_ftintrm_w_d(scratch, src);
- moveFromDoubleLo(scratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for -0 and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is negative or NaN.
+ moveFromDouble(src, dest);
+ as_srli_d(dest, dest, 62);
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::ceilFloat32ToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchFloat32Scope fpscratch(asMasm());
- FloatRegister scratch = fpscratch;
- Label performCeil, done;
- // If x < -1 or x > 0 then perform ceil.
- loadConstantFloat32(0.0f, scratch);
- branchFloat(Assembler::DoubleGreaterThan, src, scratch, &performCeil);
- loadConstantFloat32(-1.0f, scratch);
- branchFloat(Assembler::DoubleLessThanOrEqual, src, scratch, &performCeil);
+ // Round toward positive infinity.
+ as_ftintrp_l_s(fpscratch, src);
+ moveFromDouble(fpscratch, dest);
- // If binary value is not zero, the input was not 0, so we bail.
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
{
- UseScratchRegisterScope temps(asMasm());
+ UseScratchRegisterScope temps(*this);
Register scratch = temps.Acquire();
- moveFromFloat32(src, scratch);
- branch32(Assembler::NotEqual, scratch, zero, fail);
- }
-
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
- bind(&performCeil);
- as_ftintrp_w_s(scratch, src);
- moveFromFloat32(scratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for (-1, -0] and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If binary value is not zero, the input was not 0, so we bail.
+ moveFromFloat32(src, dest);
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::ceilDoubleToInt32(FloatRegister src, Register dest,
Label* fail) {
ScratchDoubleScope fpscratch(asMasm());
- FloatRegister scratch = fpscratch;
- Label performCeil, done;
- // If x < -1 or x > 0 then perform ceil.
- loadConstantDouble(0, scratch);
- branchDouble(Assembler::DoubleGreaterThan, src, scratch, &performCeil);
- loadConstantDouble(-1.0, scratch);
- branchDouble(Assembler::DoubleLessThanOrEqual, src, scratch, &performCeil);
+ // Round toward positive infinity.
+ as_ftintrp_l_d(fpscratch, src);
+ moveFromDouble(fpscratch, dest);
- // If binary value is not zero, the input was not 0, so we bail.
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
{
- UseScratchRegisterScope temps(asMasm());
+ UseScratchRegisterScope temps(*this);
Register scratch = temps.Acquire();
- moveFromDoubleHi(src, scratch);
- branch32(Assembler::NotEqual, scratch, zero, fail);
- }
-
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&done, ShortJump);
-
- bind(&performCeil);
- as_ftintrp_w_d(scratch, src);
- moveFromDoubleLo(scratch, dest);
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
- bind(&done);
+ // We have to check for (-1, -0] and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If binary value is not zero, the input was not 0, so we bail.
+ moveFromDouble(src, dest);
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ }
+ bind(¬Zero);
}
void MacroAssembler::roundFloat32ToInt32(FloatRegister src, Register dest,
FloatRegister temp, Label* fail) {
ScratchFloat32Scope fpscratch(*this);
- Label negative, end, skipCheck;
+ Label negative, end, performRound;
- // Load biggest number less than 0.5 in the temp register.
- loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
-
- // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
+ // Branch for negative inputs. Doesn't catch NaN or -0.
loadConstantFloat32(0.0f, fpscratch);
ma_bc_s(src, fpscratch, &negative, Assembler::DoubleLessThan, ShortJump);
- // If Nan, 0 or -0 check for bailout
- ma_bc_s(src, fpscratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
-
- // If binary value is not zero, it is NaN or -0, so we bail.
+ // If non-negative check for bailout.
+ ma_bc_s(src, fpscratch, &performRound, Assembler::DoubleNotEqual, ShortJump);
{
- UseScratchRegisterScope temps(asMasm());
- Register scratch = temps.Acquire();
- moveFromFloat32(src, scratch);
- branch32(Assembler::NotEqual, scratch, zero, fail);
+ // If binary value is not zero, it is NaN or -0, so we bail.
+ moveFromFloat32(src, dest);
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ ma_b(&end, ShortJump);
}
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&end, ShortJump);
-
- bind(&skipCheck);
- as_fadd_s(fpscratch, src, temp);
- as_ftintrm_w_s(fpscratch, fpscratch);
-
- moveFromFloat32(fpscratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
-
- jump(&end);
-
// Input is negative, but isn't -0.
bind(&negative);
+ {
+ // Inputs in [-0.5, 0) are rounded to -0. Fail.
+ loadConstantFloat32(-0.5f, fpscratch);
+ branchFloat(Assembler::DoubleGreaterThanOrEqual, src, fpscratch, fail);
+ }
- // 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, fpscratch);
- branchFloat(Assembler::DoubleLessThan, src, fpscratch, &loadJoin);
- loadConstantFloat32(0.5f, temp);
- bind(&loadJoin);
-
- as_fadd_s(temp, src, temp);
+ bind(&performRound);
+ {
+ // Load biggest number less than 0.5 in the temp register.
+ loadConstantFloat32(GetBiggestNumberLessThan(0.5f), temp);
- // If input + 0.5 >= 0, input is a negative number >= -0.5 and the
- // result is -0.
- branchFloat(Assembler::DoubleGreaterThanOrEqual, temp, fpscratch, fail);
+ // Other inputs need the biggest float less than 0.5 added.
+ as_fadd_s(fpscratch, src, temp);
- // Truncate and round toward zero.
- // This is off-by-one for everything but integer-valued inputs.
- as_ftintrm_w_s(fpscratch, temp);
- moveFromFloat32(fpscratch, dest);
+ // Round toward negative infinity.
+ as_ftintrm_l_s(fpscratch, fpscratch);
+ moveFromDouble(fpscratch, dest);
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
+ }
bind(&end);
}
void MacroAssembler::roundDoubleToInt32(FloatRegister src, Register dest,
FloatRegister temp, Label* fail) {
- ScratchDoubleScope scratch(*this);
-
- Label negative, end, skipCheck;
-
- // Load biggest number less than 0.5 in the temp register.
- loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
+ ScratchDoubleScope fpscratch(*this);
- // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
- loadConstantDouble(0.0, scratch);
- ma_bc_d(src, scratch, &negative, Assembler::DoubleLessThan, ShortJump);
+ Label negative, end, performRound;
- // If Nan, 0 or -0 check for bailout
- ma_bc_d(src, scratch, &skipCheck, Assembler::DoubleNotEqual, ShortJump);
+ // Branch for negative inputs. Doesn't catch NaN or -0.
+ loadConstantDouble(0.0, fpscratch);
+ ma_bc_d(src, fpscratch, &negative, Assembler::DoubleLessThan, ShortJump);
- // If high part is not zero, it is NaN or -0, so we bail.
+ // If non-negative check for bailout.
+ ma_bc_d(src, fpscratch, &performRound, Assembler::DoubleNotEqual, ShortJump);
{
- UseScratchRegisterScope temps(asMasm());
- Register scratch = temps.Acquire();
- moveFromDoubleHi(src, scratch);
- branch32(Assembler::NotEqual, scratch, zero, fail);
+ // If binary value is not zero, it is NaN or -0, so we bail.
+ moveFromDouble(src, dest);
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ ma_b(&end, ShortJump);
}
- // Input was zero, so return zero.
- move32(Imm32(0), dest);
- ma_b(&end, ShortJump);
-
- bind(&skipCheck);
- as_fadd_d(scratch, src, temp);
- as_ftintrm_w_d(scratch, scratch);
-
- moveFromDoubleLo(scratch, dest);
-
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
- branch32(Assembler::Equal, dest, Imm32(INT_MAX), fail);
-
- jump(&end);
-
// Input is negative, but isn't -0.
bind(&negative);
+ {
+ // Inputs in [-0.5, 0) are rounded to -0. Fail.
+ loadConstantDouble(-0.5, fpscratch);
+ branchDouble(Assembler::DoubleGreaterThanOrEqual, src, fpscratch, fail);
+ }
- // 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);
-
- addDouble(src, temp);
+ bind(&performRound);
+ {
+ // Load biggest number less than 0.5 in the temp register.
+ loadConstantDouble(GetBiggestNumberLessThan(0.5), temp);
- // If input + 0.5 >= 0, input is a negative number >= -0.5 and the
- // result is -0.
- branchDouble(Assembler::DoubleGreaterThanOrEqual, temp, scratch, fail);
+ // Other inputs need the biggest double less than 0.5 added.
+ as_fadd_d(fpscratch, src, temp);
- // Truncate and round toward zero.
- // This is off-by-one for everything but integer-valued inputs.
- as_ftintrm_w_d(scratch, temp);
- moveFromDoubleLo(scratch, dest);
+ // Round toward negative infinity.
+ as_ftintrm_l_d(fpscratch, fpscratch);
+ moveFromDouble(fpscratch, dest);
- branch32(Assembler::Equal, dest, Imm32(INT_MIN), fail);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
+ {
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
+ }
+ }
bind(&end);
}
void MacroAssembler::truncFloat32ToInt32(FloatRegister src, Register dest,
Label* fail) {
- UseScratchRegisterScope temps(asMasm());
- Register scratch = temps.Acquire();
ScratchFloat32Scope fpscratch(asMasm());
- Label notZero;
- as_ftintrz_w_s(fpscratch, src);
- as_movfcsr2gr(scratch);
- moveFromFloat32(fpscratch, dest);
- as_bstrpick_w(scratch, scratch, Assembler::CauseV, Assembler::CauseV);
- ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ // Round toward zero.
+ as_ftintrz_l_s(fpscratch, src);
+ moveFromDouble(fpscratch, dest);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
{
- // dest == zero
- UseScratchRegisterScope temps2(asMasm());
- Register scratch2 = temps2.Acquire();
- moveFromFloat32(src, scratch2);
- // Check if input is in ]-1; -0] range by checking the sign bit.
- as_slt(scratch2, scratch2, zero);
- as_add_d(scratch, scratch, scratch2);
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
}
+ // We have to check for (-1, -0] and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is negative or NaN.
+ moveFromFloat32(src, dest);
+ as_srli_w(dest, dest, 30);
+ branch32(Assembler::NotEqual, dest, zero, fail);
+ }
bind(¬Zero);
- branch32(Assembler::NotEqual, Register(scratch), zero, fail);
}
void MacroAssembler::truncDoubleToInt32(FloatRegister src, Register dest,
Label* fail) {
- UseScratchRegisterScope temps(asMasm());
- Register scratch = temps.Acquire();
- ScratchFloat32Scope fpscratch(asMasm());
+ ScratchDoubleScope fpscratch(asMasm());
- Label notZero;
- as_ftintrz_w_d(fpscratch, src);
- as_movfcsr2gr(scratch);
- moveFromFloat32(fpscratch, dest);
- as_bstrpick_w(scratch, scratch, Assembler::CauseV, Assembler::CauseV);
- ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ // Round toward zero.
+ as_ftintrz_l_d(fpscratch, src);
+ moveFromDouble(fpscratch, dest);
+ // Sign extend lower 32 bits to test if the result isn't an Int32.
{
- // dest == zero
- UseScratchRegisterScope temps2(asMasm());
- Register scratch2 = temps2.Acquire();
- moveFromDoubleHi(src, scratch2);
- // Check if input is in ]-1; -0] range by checking the sign bit.
- as_slt(scratch2, scratch2, zero);
- as_add_d(scratch, scratch, scratch2);
+ UseScratchRegisterScope temps(*this);
+ Register scratch = temps.Acquire();
+
+ move32SignExtendToPtr(dest, scratch);
+ branchPtr(Assembler::NotEqual, dest, scratch, fail);
}
+ // We have to check for (-1, -0] and NaN when the result is zero.
+ Label notZero;
+ ma_b(dest, zero, ¬Zero, Assembler::NotEqual, ShortJump);
+ {
+ // If any of the two most significant bits is set, |src| is negative or NaN.
+ moveFromDouble(src, dest);
+ as_srli_d(dest, dest, 62);
+ branchPtr(Assembler::NotEqual, dest, zero, fail);
+ }
bind(¬Zero);
- branch32(Assembler::NotEqual, Register(scratch), zero, fail);
}
void MacroAssembler::nearbyIntDouble(RoundingMode mode, FloatRegister src,
diff --git a/js/src/jit/loong64/MacroAssembler-loong64.h b/js/src/jit/loong64/MacroAssembler-loong64.h
@@ -371,13 +371,6 @@ class MacroAssemblerLOONG64 : public Assembler {
void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c);
- void moveToDoubleLo(Register src, FloatRegister dest) {
- as_movgr2fr_w(dest, src);
- }
- void moveFromDoubleLo(FloatRegister src, Register dest) {
- as_movfr2gr_s(dest, src);
- }
-
void moveToFloat32(Register src, FloatRegister dest) {
as_movgr2fr_w(dest, src);
}