commit 56c5cc20609ed6ff5c4c3af310755770b42ee6fc
parent da494342cf7c537190eeea74b7a82ec37de89468
Author: André Bargull <andre.bargull@gmail.com>
Date: Mon, 20 Oct 2025 08:20:22 +0000
Bug 1993951 - Part 1: Implement MacroAssembler::copySign{Float32,Double} for ARM. r=spidermonkey-reviewers,iain
GCC emits this instruction sequence for `std::copysign`. It needs fewer instructions
and registers, which helps to move `LCopySign` into the shared code generator.
Differential Revision: https://phabricator.services.mozilla.com/D268366
Diffstat:
4 files changed, 30 insertions(+), 47 deletions(-)
diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
@@ -1328,7 +1328,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
void copySignDouble(FloatRegister lhs, FloatRegister rhs,
FloatRegister output) PER_SHARED_ARCH;
void copySignFloat32(FloatRegister lhs, FloatRegister rhs,
- FloatRegister output) DEFINED_ON(x86_shared, arm64);
+ FloatRegister output) DEFINED_ON(arm, arm64, x86_shared);
// Returns a random double in range [0, 1) in |dest|. The |rng| register must
// hold a pointer to a mozilla::non_crypto::XorShift128PlusRNG.
diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -2366,24 +2366,7 @@ void CodeGenerator::visitCopySignF(LCopySignF* ins) {
FloatRegister rhs = ToFloatRegister(ins->rhs());
FloatRegister output = ToFloatRegister(ins->output());
- Register lhsi = ToRegister(ins->temp0());
- Register rhsi = ToRegister(ins->temp1());
-
- masm.ma_vxfer(lhs, lhsi);
- masm.ma_vxfer(rhs, rhsi);
-
- ScratchRegisterScope scratch(masm);
-
- // Clear lhs's sign.
- masm.ma_and(Imm32(INT32_MAX), lhsi, lhsi, scratch);
-
- // Keep rhs's sign.
- masm.ma_and(Imm32(INT32_MIN), rhsi, rhsi, scratch);
-
- // Combine.
- masm.ma_orr(lhsi, rhsi, rhsi);
-
- masm.ma_vxfer(rhsi, output);
+ masm.copySignFloat32(lhs, rhs, output);
}
void CodeGenerator::visitCopySignD(LCopySignD* ins) {
@@ -2391,30 +2374,7 @@ void CodeGenerator::visitCopySignD(LCopySignD* ins) {
FloatRegister rhs = ToFloatRegister(ins->rhs());
FloatRegister output = ToFloatRegister(ins->output());
- Register lhsi = ToRegister(ins->temp0());
- Register rhsi = ToRegister(ins->temp1());
-
- // Manipulate high words of double inputs.
- masm.as_vxfer(lhsi, InvalidReg, lhs, Assembler::FloatToCore,
- Assembler::Always, 1);
- masm.as_vxfer(rhsi, InvalidReg, rhs, Assembler::FloatToCore,
- Assembler::Always, 1);
-
- ScratchRegisterScope scratch(masm);
-
- // Clear lhs's sign.
- masm.ma_and(Imm32(INT32_MAX), lhsi, lhsi, scratch);
-
- // Keep rhs's sign.
- masm.ma_and(Imm32(INT32_MIN), rhsi, rhsi, scratch);
-
- // Combine.
- masm.ma_orr(lhsi, rhsi, rhsi);
-
- // Reconstruct the output.
- masm.as_vxfer(lhsi, InvalidReg, lhs, Assembler::FloatToCore,
- Assembler::Always, 0);
- masm.ma_vxfer(lhsi, rhsi, output);
+ masm.copySignDouble(lhs, rhs, output);
}
void CodeGenerator::visitWrapInt64ToInt32(LWrapInt64ToInt32* lir) {
diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp
@@ -1145,9 +1145,6 @@ void LIRGenerator::visitCopySign(MCopySign* ins) {
lir = new (alloc()) LCopySignF();
}
- lir->setTemp(0, temp());
- lir->setTemp(1, temp());
-
lowerForFPU(lir, ins, lhs, rhs);
}
diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -6188,7 +6188,33 @@ void MacroAssembler::nearbyIntFloat32(RoundingMode mode, FloatRegister src,
void MacroAssembler::copySignDouble(FloatRegister lhs, FloatRegister rhs,
FloatRegister output) {
- MOZ_CRASH("not supported on this platform");
+ ScratchRegisterScope scratch(*this);
+
+ // Transfer top word of |rhs| into GPR.
+ as_vxfer(scratch, InvalidReg, rhs, Assembler::FloatToCore, Assembler::Always,
+ 1);
+
+ // Move |lhs| with sign-bit cleared into |output|.
+ ma_vabs(lhs, output);
+
+ // Negate |output| if sign bit of |rhs| is set.
+ as_cmp(scratch, Imm8(0));
+ ma_vneg(output, output, Assembler::LessThan);
+}
+
+void MacroAssembler::copySignFloat32(FloatRegister lhs, FloatRegister rhs,
+ FloatRegister output) {
+ ScratchRegisterScope scratch(*this);
+
+ // Transfer |rhs| into GPR.
+ ma_vxfer(rhs, scratch);
+
+ // Move |lhs| with sign-bit cleared into |output|.
+ ma_vabs_f32(lhs, output);
+
+ // Negate |output| if sign bit of |rhs| is set.
+ as_cmp(scratch, Imm8(0));
+ ma_vneg_f32(output, output, Assembler::LessThan);
}
void MacroAssembler::shiftIndex32AndAdd(Register indexTemp32, int shift,