tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit e716a6eaa68a7f2abef18e60df96722780f37433
parent c9c43eeaccd398e493a05ff34bbbf8e92b4f6f94
Author: André Bargull <andre.bargull@gmail.com>
Date:   Fri, 24 Oct 2025 14:58:54 +0000

Bug 1996083 - Part 5: Use at-start and don't reuse input for ALU operations on {mips,loong,riscv}64. r=spidermonkey-reviewers,jandem

Differential Revision: https://phabricator.services.mozilla.com/D269838

Diffstat:
Mjs/src/jit/LIROps.yaml | 2++
Mjs/src/jit/arm64/Lowering-arm64.cpp | 11+----------
Mjs/src/jit/loong64/Lowering-loong64.cpp | 61++++++++++++++++++++++++++-----------------------------------
Mjs/src/jit/mips-shared/Lowering-mips-shared.cpp | 61++++++++++++++++++++++++++-----------------------------------
Mjs/src/jit/riscv64/Lowering-riscv64.cpp | 61++++++++++++++++++++++++++-----------------------------------
5 files changed, 81 insertions(+), 115 deletions(-)

diff --git a/js/src/jit/LIROps.yaml b/js/src/jit/LIROps.yaml @@ -1344,7 +1344,9 @@ operands: lhs: Int64 rhs: Int64 +#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM) num_temps: 1 +#endif defer_init: true - name: MulIntPtr diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp @@ -139,13 +139,6 @@ void LIRGeneratorARM64::lowerForALUInt64( defineInt64(ins, mir); } -// These all currently have codegen that depends on reuse but only because the -// masm API depends on that. We need new three-address masm APIs, for both -// constant and variable rhs. -// -// MAdd => LAddI64 -// MSub => LSubI64 -// MBitAnd, MBitOr, MBitXor => LBitOpI64 void LIRGeneratorARM64::lowerForALUInt64( LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { @@ -156,9 +149,7 @@ void LIRGeneratorARM64::lowerForALUInt64( void LIRGeneratorARM64::lowerForMulInt64(LMulI64* ins, MMul* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs(useInt64RegisterOrConstantAtStart(rhs)); - defineInt64(ins, mir); + lowerForALUInt64(ins, mir, lhs, rhs); } template <class LInstr> diff --git a/js/src/jit/loong64/Lowering-loong64.cpp b/js/src/jit/loong64/Lowering-loong64.cpp @@ -31,9 +31,7 @@ LTableSwitchV* LIRGeneratorLOONG64::newLTableSwitchV(const LBoxAllocation& in) { void LIRGeneratorLOONG64::lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setOperand(0, useRegister(lhs)); - ins->setOperand(1, useRegisterOrConstant(rhs)); - define(ins, mir); + lowerForALU(ins, mir, lhs, rhs); } template <class LInstr> @@ -42,13 +40,12 @@ void LIRGeneratorLOONG64::lowerForShiftInt64(LInstr* ins, MDefinition* mir, MDefinition* rhs) { if constexpr (std::is_same_v<LInstr, LShiftI64>) { ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs(useRegisterOrConstant(rhs)); - defineInt64ReuseInput(ins, mir, LShiftI64::LhsIndex); + ins->setRhs(useRegisterOrConstantAtStart(rhs)); } else { ins->setInput(useInt64RegisterAtStart(lhs)); - ins->setCount(useRegisterOrConstant(rhs)); - defineInt64ReuseInput(ins, mir, LRotateI64::InputIndex); + ins->setCount(useRegisterOrConstantAtStart(rhs)); } + defineInt64(ins, mir); } template void LIRGeneratorLOONG64::lowerForShiftInt64(LShiftI64* ins, @@ -63,7 +60,9 @@ template void LIRGeneratorLOONG64::lowerForShiftInt64(LRotateI64* ins, // x = !y void LIRGeneratorLOONG64::lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input) { - ins->setOperand(0, useRegister(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); } @@ -71,8 +70,10 @@ void LIRGeneratorLOONG64::lowerForALU(LInstructionHelper<1, 1, 0>* ins, void LIRGeneratorLOONG64::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setOperand(0, useRegister(lhs)); - ins->setOperand(1, useRegisterOrConstant(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); } @@ -80,39 +81,20 @@ void LIRGeneratorLOONG64::lowerForALUInt64( LInstructionHelper<INT64_PIECES, INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* input) { ins->setInt64Operand(0, useInt64RegisterAtStart(input)); - defineInt64ReuseInput(ins, mir, 0); + defineInt64(ins, mir); } void LIRGeneratorLOONG64::lowerForALUInt64( LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { ins->setInt64Operand(0, useInt64RegisterAtStart(lhs)); - ins->setInt64Operand(INT64_PIECES, - willHaveDifferentLIRNodes(lhs, rhs) - ? useInt64RegisterOrConstant(rhs) - : useInt64RegisterOrConstantAtStart(rhs)); - defineInt64ReuseInput(ins, mir, 0); + ins->setInt64Operand(INT64_PIECES, useInt64RegisterOrConstantAtStart(rhs)); + defineInt64(ins, mir); } void LIRGeneratorLOONG64::lowerForMulInt64(LMulI64* ins, MMul* mir, MDefinition* lhs, MDefinition* rhs) { - bool needsTemp = false; - bool cannotAliasRhs = false; - bool reuseInput = true; - - ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs((willHaveDifferentLIRNodes(lhs, rhs) || cannotAliasRhs) - ? useInt64RegisterOrConstant(rhs) - : useInt64RegisterOrConstantAtStart(rhs)); - - if (needsTemp) { - ins->setTemp0(temp()); - } - if (reuseInput) { - defineInt64ReuseInput(ins, mir, 0); - } else { - defineInt64(ins, mir); - } + lowerForALUInt64(ins, mir, lhs, rhs); } void LIRGeneratorLOONG64::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, @@ -183,6 +165,15 @@ void LIRGeneratorLOONG64::lowerMulI(MMul* mul, MDefinition* lhs, 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); } @@ -326,8 +317,8 @@ void LIRGeneratorLOONG64::lowerUrshD(MUrsh* mir) { MOZ_ASSERT(lhs->type() == MIRType::Int32); MOZ_ASSERT(rhs->type() == MIRType::Int32); - LUrshD* lir = new (alloc()) - LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp()); + auto* lir = new (alloc()) LUrshD(useRegisterAtStart(lhs), + useRegisterOrConstantAtStart(rhs), temp()); define(lir, mir); } diff --git a/js/src/jit/mips-shared/Lowering-mips-shared.cpp b/js/src/jit/mips-shared/Lowering-mips-shared.cpp @@ -37,7 +37,9 @@ LDefinition LIRGeneratorMIPSShared::tempByteOpRegister() { return temp(); } // x = !y void LIRGeneratorMIPSShared::lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input) { - ins->setOperand(0, useRegister(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); } @@ -45,8 +47,10 @@ void LIRGeneratorMIPSShared::lowerForALU(LInstructionHelper<1, 1, 0>* ins, void LIRGeneratorMIPSShared::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setOperand(0, useRegister(lhs)); - ins->setOperand(1, useRegisterOrConstant(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); } @@ -54,40 +58,21 @@ void LIRGeneratorMIPSShared::lowerForALUInt64( LInstructionHelper<INT64_PIECES, INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* input) { ins->setInt64Operand(0, useInt64RegisterAtStart(input)); - defineInt64ReuseInput(ins, mir, 0); + defineInt64(ins, mir); } void LIRGeneratorMIPSShared::lowerForALUInt64( LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { ins->setInt64Operand(0, useInt64RegisterAtStart(lhs)); - ins->setInt64Operand(INT64_PIECES, - willHaveDifferentLIRNodes(lhs, rhs) - ? useInt64RegisterOrConstant(rhs) - : useInt64RegisterOrConstantAtStart(rhs)); - defineInt64ReuseInput(ins, mir, 0); + ins->setInt64Operand(INT64_PIECES, useInt64RegisterOrConstantAtStart(rhs)); + defineInt64(ins, mir); } void LIRGeneratorMIPSShared::lowerForMulInt64(LMulI64* ins, MMul* mir, MDefinition* lhs, MDefinition* rhs) { - bool needsTemp = false; - bool cannotAliasRhs = false; - bool reuseInput = true; - - ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs((willHaveDifferentLIRNodes(lhs, rhs) || cannotAliasRhs) - ? useInt64RegisterOrConstant(rhs) - : useInt64RegisterOrConstantAtStart(rhs)); - - if (needsTemp) { - ins->setTemp0(temp()); - } - if (reuseInput) { - defineInt64ReuseInput(ins, mir, 0); - } else { - defineInt64(ins, mir); - } + lowerForALUInt64(ins, mir, lhs, rhs); } template <class LInstr> @@ -96,13 +81,12 @@ void LIRGeneratorMIPSShared::lowerForShiftInt64(LInstr* ins, MDefinition* mir, MDefinition* rhs) { if constexpr (std::is_same_v<LInstr, LShiftI64>) { ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs(useRegisterOrConstant(rhs)); - defineInt64ReuseInput(ins, mir, LShiftI64::LhsIndex); + ins->setRhs(useRegisterOrConstantAtStart(rhs)); } else { ins->setInput(useInt64RegisterAtStart(lhs)); - ins->setCount(useRegisterOrConstant(rhs)); - defineInt64ReuseInput(ins, mir, LRotateI64::InputIndex); + ins->setCount(useRegisterOrConstantAtStart(rhs)); } + defineInt64(ins, mir); } template void LIRGeneratorMIPSShared::lowerForShiftInt64(LShiftI64* ins, @@ -150,9 +134,7 @@ void LIRGeneratorMIPSShared::lowerWasmBuiltinTruncateToInt32( void LIRGeneratorMIPSShared::lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setOperand(0, useRegister(lhs)); - ins->setOperand(1, useRegisterOrConstant(rhs)); - define(ins, mir); + lowerForALU(ins, mir, lhs, rhs); } void LIRGeneratorMIPSShared::lowerDivI(MDiv* div) { @@ -211,6 +193,15 @@ void LIRGeneratorMIPSShared::lowerMulI(MMul* mul, MDefinition* lhs, 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); } @@ -281,8 +272,8 @@ void LIRGeneratorMIPSShared::lowerUrshD(MUrsh* mir) { MOZ_ASSERT(lhs->type() == MIRType::Int32); MOZ_ASSERT(rhs->type() == MIRType::Int32); - LUrshD* lir = new (alloc()) - LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp()); + auto* lir = new (alloc()) LUrshD(useRegisterAtStart(lhs), + useRegisterOrConstantAtStart(rhs), temp()); define(lir, mir); } diff --git a/js/src/jit/riscv64/Lowering-riscv64.cpp b/js/src/jit/riscv64/Lowering-riscv64.cpp @@ -32,9 +32,7 @@ LTableSwitchV* LIRGeneratorRiscv64::newLTableSwitchV(const LBoxAllocation& in) { void LIRGeneratorRiscv64::lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setOperand(0, useRegister(lhs)); - ins->setOperand(1, useRegisterOrConstant(rhs)); - define(ins, mir); + lowerForALU(ins, mir, lhs, rhs); } template <class LInstr> @@ -43,13 +41,12 @@ void LIRGeneratorRiscv64::lowerForShiftInt64(LInstr* ins, MDefinition* mir, MDefinition* rhs) { if constexpr (std::is_same_v<LInstr, LShiftI64>) { ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs(useRegisterOrConstant(rhs)); - defineInt64ReuseInput(ins, mir, LShiftI64::LhsIndex); + ins->setRhs(useRegisterOrConstantAtStart(rhs)); } else { ins->setInput(useInt64RegisterAtStart(lhs)); - ins->setCount(useRegisterOrConstant(rhs)); - defineInt64ReuseInput(ins, mir, LRotateI64::InputIndex); + ins->setCount(useRegisterOrConstantAtStart(rhs)); } + defineInt64(ins, mir); } template void LIRGeneratorRiscv64::lowerForShiftInt64(LShiftI64* ins, @@ -64,7 +61,9 @@ template void LIRGeneratorRiscv64::lowerForShiftInt64(LRotateI64* ins, // x = !y void LIRGeneratorRiscv64::lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input) { - ins->setOperand(0, useRegister(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); } @@ -72,8 +71,10 @@ void LIRGeneratorRiscv64::lowerForALU(LInstructionHelper<1, 1, 0>* ins, void LIRGeneratorRiscv64::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { - ins->setOperand(0, useRegister(lhs)); - ins->setOperand(1, useRegisterOrConstant(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); } @@ -81,39 +82,20 @@ void LIRGeneratorRiscv64::lowerForALUInt64( LInstructionHelper<INT64_PIECES, INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* input) { ins->setInt64Operand(0, useInt64RegisterAtStart(input)); - defineInt64ReuseInput(ins, mir, 0); + defineInt64(ins, mir); } void LIRGeneratorRiscv64::lowerForALUInt64( LInstructionHelper<INT64_PIECES, 2 * INT64_PIECES, 0>* ins, MDefinition* mir, MDefinition* lhs, MDefinition* rhs) { ins->setInt64Operand(0, useInt64RegisterAtStart(lhs)); - ins->setInt64Operand(INT64_PIECES, - willHaveDifferentLIRNodes(lhs, rhs) - ? useInt64RegisterOrConstant(rhs) - : useInt64RegisterOrConstantAtStart(rhs)); - defineInt64ReuseInput(ins, mir, 0); + ins->setInt64Operand(INT64_PIECES, useInt64RegisterOrConstantAtStart(rhs)); + defineInt64(ins, mir); } void LIRGeneratorRiscv64::lowerForMulInt64(LMulI64* ins, MMul* mir, MDefinition* lhs, MDefinition* rhs) { - bool needsTemp = false; - bool cannotAliasRhs = false; - bool reuseInput = true; - - ins->setLhs(useInt64RegisterAtStart(lhs)); - ins->setRhs((willHaveDifferentLIRNodes(lhs, rhs) || cannotAliasRhs) - ? useInt64RegisterOrConstant(rhs) - : useInt64RegisterOrConstantAtStart(rhs)); - - if (needsTemp) { - ins->setTemp0(temp()); - } - if (reuseInput) { - defineInt64ReuseInput(ins, mir, 0); - } else { - defineInt64(ins, mir); - } + lowerForALUInt64(ins, mir, lhs, rhs); } void LIRGeneratorRiscv64::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, @@ -183,6 +165,15 @@ void LIRGeneratorRiscv64::lowerMulI(MMul* mul, MDefinition* lhs, 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); } @@ -326,8 +317,8 @@ void LIRGeneratorRiscv64::lowerUrshD(MUrsh* mir) { MOZ_ASSERT(lhs->type() == MIRType::Int32); MOZ_ASSERT(rhs->type() == MIRType::Int32); - LUrshD* lir = new (alloc()) - LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp()); + auto* lir = new (alloc()) LUrshD(useRegisterAtStart(lhs), + useRegisterOrConstantAtStart(rhs), temp()); define(lir, mir); }