commit fb96cba7f3ea28abac1fb671fa23c0452285e70a
parent c6f2c7e54a4ab1229d9c37801c473610becc33ea
Author: André Bargull <andre.bargull@gmail.com>
Date: Fri, 24 Oct 2025 14:58:55 +0000
Bug 1996085 - Part 3: Call lowerForFPU for Neg{D,F}. r=spidermonkey-reviewers,jandem
Lowering for `MWasmNeg` now no longer needs to be duplicated for each architecture.
This also saves a move instruction on all architectures except x86-shared.
```js
function f(x) {
return -x + x;
}
```
Was compiled to (ARM64):
```asm
[Codegen] # LIR=Double
[Codegen] [e] 000028 1e7e1001 fmov d1, #0xf0 (-1,0000)
[Codegen] # LIR=MoveGroup
[Codegen] [e] 00002c 1e604001 fmov d1, d0
[Codegen] # LIR=NegD
[Codegen] [e] 000030 1e614021 fneg d1, d1
[Codegen] # LIR=MathD:Add
[Codegen] [e] 000034 1e602820 fadd d0, d1, d0
```
And is now:
```asm
[Codegen] # LIR=Double
[Codegen] [e] 000028 1e7e1001 fmov d1, #0xf0 (-1,0000)
[Codegen] # LIR=NegD
[Codegen] [e] 00002c 1e614001 fneg d1, d0
[Codegen] # LIR=MathD:Add
[Codegen] [e] 000030 1e602820 fadd d0, d1, d0
```
(The unnecessary `fmov` is tracked in bug 1986976.)
Differential Revision: https://phabricator.services.mozilla.com/D269842
Diffstat:
9 files changed, 29 insertions(+), 80 deletions(-)
diff --git a/js/src/jit/LIROps.yaml b/js/src/jit/LIROps.yaml
@@ -1126,12 +1126,14 @@
result_type: WordSized
operands:
input: WordSized
+ defer_init: true
# Negative of float32
- name: NegF
result_type: WordSized
operands:
input: WordSized
+ defer_init: true
# Absolute value of an integer.
- name: AbsI
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
@@ -2405,7 +2405,7 @@ void LIRGenerator::visitMul(MMul* ins) {
// If our RHS is a constant -1.0, we can optimize to an LNegD.
if (!ins->mustPreserveNaN() && rhs->isConstant() &&
rhs->toConstant()->toDouble() == -1.0) {
- defineReuseInput(new (alloc()) LNegD(useRegisterAtStart(lhs)), ins, 0);
+ lowerForFPU(new (alloc()) LNegD, ins, lhs);
return;
}
@@ -2420,7 +2420,7 @@ void LIRGenerator::visitMul(MMul* ins) {
// We apply the same optimizations as for doubles
if (!ins->mustPreserveNaN() && rhs->isConstant() &&
rhs->toConstant()->toFloat32() == -1.0f) {
- defineReuseInput(new (alloc()) LNegF(useRegisterAtStart(lhs)), ins, 0);
+ lowerForFPU(new (alloc()) LNegF, ins, lhs);
return;
}
@@ -2431,6 +2431,22 @@ void LIRGenerator::visitMul(MMul* ins) {
MOZ_CRASH("Unhandled number specialization");
}
+void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
+ switch (ins->type()) {
+ case MIRType::Int32:
+ lowerForALU(new (alloc()) LNegI, ins, ins->input());
+ break;
+ case MIRType::Float32:
+ lowerForFPU(new (alloc()) LNegF, ins, ins->input());
+ break;
+ case MIRType::Double:
+ lowerForFPU(new (alloc()) LNegD, ins, ins->input());
+ break;
+ default:
+ MOZ_CRASH();
+ }
+}
+
void LIRGenerator::visitDiv(MDiv* ins) {
MDefinition* lhs = ins->lhs();
MDefinition* rhs = ins->rhs();
diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp
@@ -575,17 +575,6 @@ void LIRGeneratorARM::lowerBigIntPtrMod(MBigIntPtrMod* ins) {
}
}
-void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
- if (ins->type() == MIRType::Int32) {
- lowerForALU(new (alloc()) LNegI, ins, ins->input());
- } else if (ins->type() == MIRType::Float32) {
- define(new (alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
- } else {
- MOZ_ASSERT(ins->type() == MIRType::Double);
- define(new (alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
- }
-}
-
void LIRGeneratorARM::lowerUDiv(MDiv* div) {
MDefinition* lhs = div->getOperand(0);
MDefinition* rhs = div->getOperand(1);
diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -507,22 +507,6 @@ bool LIRGeneratorARM64::canEmitWasmReduceSimd128AtUses(
#endif
-void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
- switch (ins->type()) {
- case MIRType::Int32:
- lowerForALU(new (alloc()) LNegI, ins, ins->input());
- break;
- case MIRType::Float32:
- define(new (alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
- break;
- case MIRType::Double:
- define(new (alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
- break;
- default:
- MOZ_CRASH("unexpected type");
- }
-}
-
void LIRGeneratorARM64::lowerUDiv(MDiv* div) {
LAllocation lhs = useRegister(div->lhs());
if (div->rhs()->isConstant()) {
diff --git a/js/src/jit/loong64/Lowering-loong64.cpp b/js/src/jit/loong64/Lowering-loong64.cpp
@@ -823,17 +823,6 @@ void LIRGenerator::visitWasmStore(MWasmStore* ins) {
add(lir, ins);
}
-void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
- if (ins->type() == MIRType::Int32) {
- lowerForALU(new (alloc()) LNegI, ins, ins->input());
- } else if (ins->type() == MIRType::Float32) {
- define(new (alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
- } else {
- MOZ_ASSERT(ins->type() == MIRType::Double);
- define(new (alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
- }
-}
-
void LIRGenerator::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins) {
MDefinition* opd = ins->input();
MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
diff --git a/js/src/jit/mips-shared/Lowering-mips-shared.cpp b/js/src/jit/mips-shared/Lowering-mips-shared.cpp
@@ -308,17 +308,6 @@ void LIRGeneratorMIPSShared::lowerBigIntPtrMod(MBigIntPtrMod* ins) {
define(lir, ins);
}
-void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
- if (ins->type() == MIRType::Int32) {
- lowerForALU(new (alloc()) LNegI, ins, ins->input());
- } else if (ins->type() == MIRType::Float32) {
- define(new (alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
- } else {
- MOZ_ASSERT(ins->type() == MIRType::Double);
- define(new (alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
- }
-}
-
void LIRGenerator::visitWasmLoad(MWasmLoad* ins) {
MDefinition* base = ins->base();
// 'base' is a GPR but may be of either type. If it is 32-bit, it is
diff --git a/js/src/jit/riscv64/Lowering-riscv64.cpp b/js/src/jit/riscv64/Lowering-riscv64.cpp
@@ -824,17 +824,6 @@ void LIRGenerator::visitWasmStore(MWasmStore* ins) {
add(lir, ins);
}
-void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
- if (ins->type() == MIRType::Int32) {
- lowerForALU(new (alloc()) LNegI, ins, ins->input());
- } else if (ins->type() == MIRType::Float32) {
- define(new (alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
- } else {
- MOZ_ASSERT(ins->type() == MIRType::Double);
- define(new (alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
- }
-}
-
void LIRGenerator::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins) {
MDefinition* opd = ins->input();
MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
diff --git a/js/src/jit/x86-shared/Lowering-x86-shared.cpp b/js/src/jit/x86-shared/Lowering-x86-shared.cpp
@@ -151,6 +151,12 @@ void LIRGeneratorX86Shared::lowerForALU(LInstructionHelper<1, 2, 0>* ins,
defineReuseInput(ins, mir, 0);
}
+void LIRGeneratorX86Shared::lowerForFPU(LInstructionHelper<1, 1, 0>* ins,
+ MDefinition* mir, MDefinition* input) {
+ ins->setOperand(0, useRegisterAtStart(input));
+ defineReuseInput(ins, mir, 0);
+}
+
void LIRGeneratorX86Shared::lowerForFPU(LInstructionHelper<1, 2, 0>* ins,
MDefinition* mir, MDefinition* lhs,
MDefinition* rhs) {
@@ -281,24 +287,6 @@ void LIRGeneratorX86Shared::lowerModI(MMod* mod) {
defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
}
-void LIRGenerator::visitWasmNeg(MWasmNeg* ins) {
- switch (ins->type()) {
- case MIRType::Int32:
- lowerForALU(new (alloc()) LNegI, ins, ins->input());
- break;
- case MIRType::Float32:
- defineReuseInput(new (alloc()) LNegF(useRegisterAtStart(ins->input())),
- ins, 0);
- break;
- case MIRType::Double:
- defineReuseInput(new (alloc()) LNegD(useRegisterAtStart(ins->input())),
- ins, 0);
- break;
- default:
- MOZ_CRASH();
- }
-}
-
void LIRGeneratorX86Shared::lowerWasmSelectI(MWasmSelect* select) {
auto* lir = new (alloc())
LWasmSelect(useRegisterAtStart(select->trueExpr()),
diff --git a/js/src/jit/x86-shared/Lowering-x86-shared.h b/js/src/jit/x86-shared/Lowering-x86-shared.h
@@ -36,8 +36,11 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared {
void lowerForShiftInt64(LInstr* ins, MDefinition* mir, MDefinition* lhs,
MDefinition* rhs);
+ void lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
+ MDefinition* input);
void lowerForFPU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
MDefinition* lhs, MDefinition* rhs);
+
void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs);
void lowerDivI(MDiv* div);
void lowerModI(MMod* mod);