commit 3c5ab0e82dccef9f3ccb8f726ab514ce5181c4a6
parent 6e9c5451caf2a02acd98cbe935e729246535f0f0
Author: André Bargull <andre.bargull@gmail.com>
Date: Thu, 23 Oct 2025 12:23:34 +0000
Bug 1995707 - Part 1: Use at-start for fallible ALU operations except LMulI on arm32/arm64. r=spidermonkey-reviewers,jandem
Differential Revision: https://phabricator.services.mozilla.com/D269551
Diffstat:
3 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/js/src/jit/arm/Lowering-arm.cpp b/js/src/jit/arm/Lowering-arm.cpp
@@ -162,8 +162,9 @@ void LIRGeneratorARM::lowerInt64PhiInput(MPhi* phi, uint32_t inputPosition,
// x = !y
void LIRGeneratorARM::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
MDefinition* mir, MDefinition* input) {
- ins->setOperand(
- 0, ins->snapshot() ? useRegister(input) : useRegisterAtStart(input));
+ // Unary ALU operations don't read the input after writing to the output, even
+ // for fallible operations, so we can use at-start allocations.
+ ins->setOperand(0, useRegisterAtStart(input));
define(ins, mir);
}
@@ -171,12 +172,10 @@ void LIRGeneratorARM::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
void LIRGeneratorARM::lowerForALU(LInstructionHelper<1, 2, 0>* ins,
MDefinition* mir, MDefinition* lhs,
MDefinition* rhs) {
- // Some operations depend on checking inputs after writing the result, e.g.
- // MulI, but only for bail out paths so useAtStart when no bailouts.
- ins->setOperand(0,
- ins->snapshot() ? useRegister(lhs) : useRegisterAtStart(lhs));
- ins->setOperand(1, ins->snapshot() ? useRegisterOrConstant(rhs)
- : useRegisterOrConstantAtStart(rhs));
+ // Binary ALU operations don't read any input after writing to the output,
+ // even for fallible operations, so we can use at-start allocations.
+ ins->setOperand(0, useRegisterAtStart(lhs));
+ ins->setOperand(1, useRegisterOrConstantAtStart(rhs));
define(ins, mir);
}
@@ -376,6 +375,16 @@ void LIRGeneratorARM::lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs) {
if (mul->fallible()) {
assignSnapshot(lir, mul->bailoutKind());
}
+
+ // Negative zero check reads |lhs| and |rhs| after writing to the output, so
+ // we can't use at-start allocations.
+ if (mul->canBeNegativeZero() && !rhs->isConstant()) {
+ lir->setOperand(0, useRegister(lhs));
+ lir->setOperand(1, useRegister(rhs));
+ define(lir, mul);
+ return;
+ }
+
lowerForALU(lir, mul, lhs, rhs);
}
diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -265,7 +265,6 @@ void CodeGenerator::visitMulI(LMulI* ins) {
masm.mul32(lhsreg, scratch, destreg, onOverflow);
if (onOverflow) {
- MOZ_ASSERT(lhsreg != destreg);
bailoutFrom(&bailout, ins->snapshot());
}
return;
diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -101,8 +101,9 @@ void LIRGenerator::visitReturnImpl(MDefinition* opd, bool isGenerator) {
// x = !y
void LIRGeneratorARM64::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
MDefinition* mir, MDefinition* input) {
- ins->setOperand(
- 0, ins->snapshot() ? useRegister(input) : useRegisterAtStart(input));
+ // Unary ALU operations don't read the input after writing to the output, even
+ // for fallible operations, so we can use at-start allocations.
+ ins->setOperand(0, useRegisterAtStart(input));
define(ins, mir);
}
@@ -110,10 +111,10 @@ void LIRGeneratorARM64::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
void LIRGeneratorARM64::lowerForALU(LInstructionHelper<1, 2, 0>* ins,
MDefinition* mir, MDefinition* lhs,
MDefinition* rhs) {
- ins->setOperand(0,
- ins->snapshot() ? useRegister(lhs) : useRegisterAtStart(lhs));
- ins->setOperand(1, ins->snapshot() ? useRegisterOrConstant(rhs)
- : useRegisterOrConstantAtStart(rhs));
+ // Binary ALU operations don't read any input after writing to the output,
+ // even for fallible operations, so we can use at-start allocations.
+ ins->setOperand(0, useRegisterAtStart(lhs));
+ ins->setOperand(1, useRegisterOrConstantAtStart(rhs));
define(ins, mir);
}
@@ -264,6 +265,16 @@ void LIRGeneratorARM64::lowerMulI(MMul* mul, MDefinition* lhs,
if (mul->fallible()) {
assignSnapshot(lir, mul->bailoutKind());
}
+
+ // Negative zero check reads |lhs| and |rhs| after writing to the output, so
+ // we can't use at-start allocations.
+ if (mul->canBeNegativeZero() && !rhs->isConstant()) {
+ lir->setOperand(0, useRegister(lhs));
+ lir->setOperand(1, useRegister(rhs));
+ define(lir, mul);
+ return;
+ }
+
lowerForALU(lir, mul, lhs, rhs);
}