tor-browser

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

commit 897281b10610d7f70362971d8e1ddeb658e5ae9a
parent bbd8cdc9597195f9ee8361ae82a370879d61b3e9
Author: André Bargull <andre.bargull@gmail.com>
Date:   Mon, 27 Oct 2025 15:22:13 +0000

Bug 1996346 - Part 1: Don't reuse input for shift instructions when BMI2 is available. r=spidermonkey-reviewers,iain

Improves codegen for:
```js
function f(x, y) {
  return ((x << y) + x)|0;
}
```

From:
```asm
movl       %eax, %ecx
shlxl      %eax, %edx, %eax
addl       %ecx, %eax
```

To:
```asm
shlxl      %eax, %ecx, %ecx
addl       %eax, %ecx
```

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

Diffstat:
Mjs/src/jit/x64/CodeGenerator-x64.cpp | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mjs/src/jit/x86-shared/CodeGenerator-x86-shared.cpp | 73+++++++++++++++++++++----------------------------------------------------
Mjs/src/jit/x86-shared/Lowering-x86-shared.cpp | 16+++++++++++-----
Mjs/src/jit/x86/CodeGenerator-x86.cpp | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 152 insertions(+), 57 deletions(-)

diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -305,6 +305,66 @@ void CodeGeneratorX64::emitBigIntPtrMod(LBigIntPtrMod* ins, Register dividend, masm.idivq(divisor); } +void CodeGenerator::visitShiftIntPtr(LShiftIntPtr* ins) { + Register lhs = ToRegister(ins->lhs()); + const LAllocation* rhs = ins->rhs(); + Register out = ToRegister(ins->output()); + + if (rhs->isConstant()) { + MOZ_ASSERT(out == lhs); + + int32_t shift = ToIntPtr(rhs) & 0x3f; + switch (ins->bitop()) { + case JSOp::Lsh: + if (shift) { + masm.lshiftPtr(Imm32(shift), lhs); + } + break; + case JSOp::Rsh: + if (shift) { + masm.rshiftPtrArithmetic(Imm32(shift), lhs); + } + break; + case JSOp::Ursh: + if (shift) { + masm.rshiftPtr(Imm32(shift), lhs); + } + break; + default: + MOZ_CRASH("Unexpected shift op"); + } + } else { + Register shift = ToRegister(rhs); + MOZ_ASSERT_IF(out != lhs, Assembler::HasBMI2()); + + switch (ins->bitop()) { + case JSOp::Lsh: + if (out != lhs) { + masm.shlxq(lhs, shift, out); + } else { + masm.lshiftPtr(shift, lhs); + } + break; + case JSOp::Rsh: + if (out != lhs) { + masm.sarxq(lhs, shift, out); + } else { + masm.rshiftPtrArithmetic(shift, lhs); + } + break; + case JSOp::Ursh: + if (out != lhs) { + masm.shrxq(lhs, shift, out); + } else { + masm.rshiftPtr(shift, lhs); + } + break; + default: + MOZ_CRASH("Unexpected shift op"); + } + } +} + void CodeGenerator::visitAtomicLoad64(LAtomicLoad64* lir) { Register elements = ToRegister(lir->elements()); Register64 out = ToOutRegister64(lir); diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp @@ -1528,10 +1528,11 @@ void CodeGenerator::visitBitOpI64(LBitOpI64* lir) { void CodeGenerator::visitShiftI(LShiftI* ins) { Register lhs = ToRegister(ins->lhs()); const LAllocation* rhs = ins->rhs(); - - MOZ_ASSERT(ToRegister(ins->output()) == lhs); + Register out = ToRegister(ins->output()); if (rhs->isConstant()) { + MOZ_ASSERT(out == lhs); + int32_t shift = ToInt32(rhs) & 0x1F; switch (ins->bitop()) { case JSOp::Lsh: @@ -1558,66 +1559,34 @@ void CodeGenerator::visitShiftI(LShiftI* ins) { } } else { Register shift = ToRegister(rhs); - switch (ins->bitop()) { - case JSOp::Lsh: - masm.lshift32(shift, lhs); - break; - case JSOp::Rsh: - masm.rshift32Arithmetic(shift, lhs); - break; - case JSOp::Ursh: - masm.rshift32(shift, lhs); - if (ins->mir()->toUrsh()->fallible()) { - // x >>> 0 can overflow. - masm.test32(lhs, lhs); - bailoutIf(Assembler::Signed, ins->snapshot()); - } - break; - default: - MOZ_CRASH("Unexpected shift op"); - } - } -} + MOZ_ASSERT_IF(out != lhs, Assembler::HasBMI2()); -void CodeGenerator::visitShiftIntPtr(LShiftIntPtr* ins) { - Register lhs = ToRegister(ins->lhs()); - const LAllocation* rhs = ins->rhs(); - - MOZ_ASSERT(ToRegister(ins->output()) == lhs); - - if (rhs->isConstant()) { - constexpr intptr_t mask = (sizeof(intptr_t) * CHAR_BIT) - 1; - int32_t shift = ToIntPtr(rhs) & mask; switch (ins->bitop()) { case JSOp::Lsh: - if (shift) { - masm.lshiftPtr(Imm32(shift), lhs); + if (out != lhs) { + masm.shlxl(lhs, shift, out); + } else { + masm.lshift32(shift, lhs); } break; case JSOp::Rsh: - if (shift) { - masm.rshiftPtrArithmetic(Imm32(shift), lhs); + if (out != lhs) { + masm.sarxl(lhs, shift, out); + } else { + masm.rshift32Arithmetic(shift, lhs); } break; case JSOp::Ursh: - if (shift) { - masm.rshiftPtr(Imm32(shift), lhs); + if (out != lhs) { + masm.shrxl(lhs, shift, out); + } else { + masm.rshift32(shift, lhs); + } + if (ins->mir()->toUrsh()->fallible()) { + // x >>> 0 can overflow. + masm.test32(out, out); + bailoutIf(Assembler::Signed, ins->snapshot()); } - break; - default: - MOZ_CRASH("Unexpected shift op"); - } - } else { - Register shift = ToRegister(rhs); - switch (ins->bitop()) { - case JSOp::Lsh: - masm.lshiftPtr(shift, lhs); - break; - case JSOp::Rsh: - masm.rshiftPtrArithmetic(shift, lhs); - break; - case JSOp::Ursh: - masm.rshiftPtr(shift, lhs); break; default: MOZ_CRASH("Unexpected shift op"); diff --git a/js/src/jit/x86-shared/Lowering-x86-shared.cpp b/js/src/jit/x86-shared/Lowering-x86-shared.cpp @@ -68,17 +68,23 @@ void LIRGeneratorX86Shared::lowerForShift(LInstructionHelper<1, 2, 0>* ins, if (rhs->isConstant()) { ins->setOperand(1, useOrConstantAtStart(rhs)); + defineReuseInput(ins, mir, 0); } else if (!mir->isRotate()) { - ins->setOperand(1, willHaveDifferentLIRNodes(lhs, rhs) - ? useShiftRegister(rhs) - : useShiftRegisterAtStart(rhs)); + if (Assembler::HasBMI2()) { + ins->setOperand(1, useRegisterAtStart(rhs)); + define(ins, mir); + } else { + ins->setOperand(1, willHaveDifferentLIRNodes(lhs, rhs) + ? useShiftRegister(rhs) + : useShiftRegisterAtStart(rhs)); + defineReuseInput(ins, mir, 0); + } } else { ins->setOperand(1, willHaveDifferentLIRNodes(lhs, rhs) ? useFixed(rhs, ecx) : useFixedAtStart(rhs, ecx)); + defineReuseInput(ins, mir, 0); } - - defineReuseInput(ins, mir, 0); } template <class LInstr> diff --git a/js/src/jit/x86/CodeGenerator-x86.cpp b/js/src/jit/x86/CodeGenerator-x86.cpp @@ -996,6 +996,66 @@ void CodeGeneratorX86::emitBigIntPtrMod(LBigIntPtrMod* ins, Register dividend, masm.idiv(divisor); } +void CodeGenerator::visitShiftIntPtr(LShiftIntPtr* ins) { + Register lhs = ToRegister(ins->lhs()); + const LAllocation* rhs = ins->rhs(); + Register out = ToRegister(ins->output()); + + if (rhs->isConstant()) { + MOZ_ASSERT(out == lhs); + + int32_t shift = ToIntPtr(rhs) & 0x1F; + switch (ins->bitop()) { + case JSOp::Lsh: + if (shift) { + masm.lshiftPtr(Imm32(shift), lhs); + } + break; + case JSOp::Rsh: + if (shift) { + masm.rshiftPtrArithmetic(Imm32(shift), lhs); + } + break; + case JSOp::Ursh: + if (shift) { + masm.rshiftPtr(Imm32(shift), lhs); + } + break; + default: + MOZ_CRASH("Unexpected shift op"); + } + } else { + Register shift = ToRegister(rhs); + MOZ_ASSERT_IF(out != lhs, Assembler::HasBMI2()); + + switch (ins->bitop()) { + case JSOp::Lsh: + if (out != lhs) { + masm.shlxl(lhs, shift, out); + } else { + masm.lshiftPtr(shift, lhs); + } + break; + case JSOp::Rsh: + if (out != lhs) { + masm.sarxl(lhs, shift, out); + } else { + masm.rshiftPtrArithmetic(shift, lhs); + } + break; + case JSOp::Ursh: + if (out != lhs) { + masm.shrxl(lhs, shift, out); + } else { + masm.rshiftPtr(shift, lhs); + } + break; + default: + MOZ_CRASH("Unexpected shift op"); + } + } +} + void CodeGenerator::visitWasmSelectI64(LWasmSelectI64* lir) { MOZ_ASSERT(lir->mir()->type() == MIRType::Int64);