commit 7f9fbe6c0367e048f5321abd796d150283766846
parent 768bf4dd8e7ddc79928660f461ebda1d8ad0d52d
Author: André Bargull <andre.bargull@gmail.com>
Date: Wed, 5 Nov 2025 20:55:57 +0000
Bug 1997975 - Part 9: Split (U)DivOrModI64 for arm64. r=spidermonkey-reviewers,iain
Using different instructions for division and modulus instructions makes it
easier to follow the code.
And use at-start allocations for division.
Differential Revision: https://phabricator.services.mozilla.com/D271110
Diffstat:
4 files changed, 99 insertions(+), 142 deletions(-)
diff --git a/js/src/jit/LIROps.yaml b/js/src/jit/LIROps.yaml
@@ -4403,11 +4403,33 @@
#endif
#ifdef JS_CODEGEN_ARM64
-- name: DivOrModI64
- gen_boilerplate: false
+- name: DivI64
+ result_type: Int64
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Div
-- name: UDivOrModI64
- gen_boilerplate: false
+- name: ModI64
+ result_type: Int64
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Mod
+
+- name: UDivI64
+ result_type: Int64
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Div
+
+- name: UModI64
+ result_type: Int64
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Mod
- name: DivConstantI
result_type: WordSized
diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -337,6 +337,20 @@ void CodeGenerator::visitMulI(LMulI* ins) {
}
}
+template <class LIR>
+static void TrapIfDivideByZero(MacroAssembler& masm, LIR* lir,
+ ARMRegister rhs) {
+ auto* mir = lir->mir();
+ MOZ_ASSERT(mir->trapOnError());
+
+ if (mir->canBeDivideByZero()) {
+ Label nonZero;
+ masm.Cbnz(rhs, &nonZero);
+ masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
+ masm.bind(&nonZero);
+ }
+}
+
void CodeGenerator::visitDivI(LDivI* ins) {
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
@@ -350,10 +364,7 @@ void CodeGenerator::visitDivI(LDivI* ins) {
// Handle division by zero.
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
- Label nonZero;
- masm.Cbnz(rhs32, &nonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
- masm.bind(&nonZero);
+ TrapIfDivideByZero(masm, ins, rhs32);
} else if (mir->canTruncateInfinities()) {
// SDIV returns zero for division by zero, exactly what we want for
// truncated division. Remainder computation expects a non-zero divisor,
@@ -703,10 +714,7 @@ void CodeGenerator::visitModI(LModI* ins) {
// Prevent divide by zero.
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
- Label nonZero;
- masm.Cbnz(rhs32, &nonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
- masm.bind(&nonZero);
+ TrapIfDivideByZero(masm, ins, rhs32);
} else if (mir->isTruncated()) {
// Truncated division by zero yields integer zero.
masm.Mov(output32, wzr);
@@ -1706,10 +1714,7 @@ void CodeGenerator::visitUDiv(LUDiv* ins) {
// Prevent divide by zero.
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
- Label nonZero;
- masm.Cbnz(rhs32, &nonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
- masm.bind(&nonZero);
+ TrapIfDivideByZero(masm, ins, rhs32);
} else if (mir->canTruncateInfinities()) {
// Udiv returns zero for division by zero, exactly what we want for
// truncated division. Remainder computation expects a non-zero divisor,
@@ -1757,10 +1762,7 @@ void CodeGenerator::visitUMod(LUMod* ins) {
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
- Label nonZero;
- masm.Cbnz(rhs32, &nonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
- masm.bind(&nonZero);
+ TrapIfDivideByZero(masm, ins, rhs32);
} else if (mir->isTruncated()) {
// Truncated division by zero yields integer zero.
masm.Mov(output32, wzr);
@@ -2651,66 +2653,68 @@ void CodeGenerator::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir) {
}
}
-void CodeGenerator::visitDivOrModI64(LDivOrModI64* lir) {
+void CodeGenerator::visitDivI64(LDivI64* lir) {
Register lhs = ToRegister(lir->lhs());
Register rhs = ToRegister(lir->rhs());
- Register output = ToRegister(lir->output());
- Label done;
+ ARMRegister lhs64 = toXRegister(lir->lhs());
+ ARMRegister rhs64 = toXRegister(lir->rhs());
+ ARMRegister output64 = toXRegister(lir->output());
+
+ MDiv* mir = lir->mir();
// Handle divide by zero.
- if (lir->canBeDivideByZero()) {
- Label isNotDivByZero;
- masm.Cbnz(ARMRegister(rhs, 64), &isNotDivByZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->trapSiteDesc());
- masm.bind(&isNotDivByZero);
- }
+ TrapIfDivideByZero(masm, lir, rhs64);
// Handle an integer overflow exception from INT64_MIN / -1.
- if (lir->canBeNegativeOverflow()) {
+ if (mir->canBeNegativeOverflow()) {
Label noOverflow;
masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(INT64_MIN), &noOverflow);
masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(-1), &noOverflow);
- if (lir->mir()->isMod()) {
- masm.movePtr(ImmWord(0), output);
- } else {
- masm.wasmTrap(wasm::Trap::IntegerOverflow, lir->trapSiteDesc());
- }
- masm.jump(&done);
+ masm.wasmTrap(wasm::Trap::IntegerOverflow, mir->trapSiteDesc());
masm.bind(&noOverflow);
}
- masm.Sdiv(ARMRegister(output, 64), ARMRegister(lhs, 64),
- ARMRegister(rhs, 64));
- if (lir->mir()->isMod()) {
- masm.Msub(ARMRegister(output, 64), ARMRegister(output, 64),
- ARMRegister(rhs, 64), ARMRegister(lhs, 64));
- }
- masm.bind(&done);
+ masm.Sdiv(output64, lhs64, rhs64);
}
-void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) {
- Register lhs = ToRegister(lir->lhs());
- Register rhs = ToRegister(lir->rhs());
- Register output = ToRegister(lir->output());
+void CodeGenerator::visitModI64(LModI64* lir) {
+ ARMRegister lhs64 = toXRegister(lir->lhs());
+ ARMRegister rhs64 = toXRegister(lir->rhs());
+ ARMRegister output64 = toXRegister(lir->output());
- Label done;
+ // Handle divide by zero.
+ TrapIfDivideByZero(masm, lir, rhs64);
+
+ masm.Sdiv(output64, lhs64, rhs64);
+
+ // Compute the remainder: output = lhs - (output * rhs).
+ masm.Msub(output64, output64, rhs64, lhs64);
+}
+
+void CodeGenerator::visitUDivI64(LUDivI64* lir) {
+ ARMRegister lhs64 = toXRegister(lir->lhs());
+ ARMRegister rhs64 = toXRegister(lir->rhs());
+ ARMRegister output64 = toXRegister(lir->output());
// Handle divide by zero.
- if (lir->canBeDivideByZero()) {
- Label isNotDivByZero;
- masm.Cbnz(ARMRegister(rhs, 64), &isNotDivByZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->trapSiteDesc());
- masm.bind(&isNotDivByZero);
- }
+ TrapIfDivideByZero(masm, lir, rhs64);
- masm.Udiv(ARMRegister(output, 64), ARMRegister(lhs, 64),
- ARMRegister(rhs, 64));
- if (lir->mir()->isMod()) {
- masm.Msub(ARMRegister(output, 64), ARMRegister(output, 64),
- ARMRegister(rhs, 64), ARMRegister(lhs, 64));
- }
- masm.bind(&done);
+ masm.Udiv(output64, lhs64, rhs64);
+}
+
+void CodeGenerator::visitUModI64(LUModI64* lir) {
+ ARMRegister lhs64 = toXRegister(lir->lhs());
+ ARMRegister rhs64 = toXRegister(lir->rhs());
+ ARMRegister output64 = toXRegister(lir->output());
+
+ // Handle divide by zero.
+ TrapIfDivideByZero(masm, lir, rhs64);
+
+ masm.Udiv(output64, lhs64, rhs64);
+
+ // Compute the remainder: output = lhs - (output * rhs).
+ masm.Msub(output64, output64, rhs64, lhs64);
}
void CodeGenerator::visitSimd128(LSimd128* ins) {
diff --git a/js/src/jit/arm64/LIR-arm64.h b/js/src/jit/arm64/LIR-arm64.h
@@ -26,75 +26,6 @@ class LUnbox : public LInstructionHelper<1, BOX_PIECES, 0> {
const char* extraName() const { return StringFromMIRType(mir()->type()); }
};
-class LDivOrModI64 : public LBinaryMath<0> {
- public:
- LIR_HEADER(DivOrModI64)
-
- LDivOrModI64(const LAllocation& lhs, const LAllocation& rhs)
- : LBinaryMath(classOpcode) {
- setOperand(0, lhs);
- setOperand(1, rhs);
- }
-
- MBinaryArithInstruction* mir() const {
- MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
- return static_cast<MBinaryArithInstruction*>(mir_);
- }
-
- bool canBeDivideByZero() const {
- if (mir_->isMod()) {
- return mir_->toMod()->canBeDivideByZero();
- }
- return mir_->toDiv()->canBeDivideByZero();
- }
- bool canBeNegativeOverflow() const {
- if (mir_->isMod()) {
- return mir_->toMod()->canBeNegativeDividend();
- }
- return mir_->toDiv()->canBeNegativeOverflow();
- }
- wasm::TrapSiteDesc trapSiteDesc() const {
- MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
- if (mir_->isMod()) {
- return mir_->toMod()->trapSiteDesc();
- }
- return mir_->toDiv()->trapSiteDesc();
- }
-};
-
-class LUDivOrModI64 : public LBinaryMath<0> {
- public:
- LIR_HEADER(UDivOrModI64);
-
- LUDivOrModI64(const LAllocation& lhs, const LAllocation& rhs)
- : LBinaryMath(classOpcode) {
- setOperand(0, lhs);
- setOperand(1, rhs);
- }
-
- const char* extraName() const {
- return mir()->isTruncated() ? "Truncated" : nullptr;
- }
-
- MBinaryArithInstruction* mir() const {
- MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
- return static_cast<MBinaryArithInstruction*>(mir_);
- }
- bool canBeDivideByZero() const {
- if (mir_->isMod()) {
- return mir_->toMod()->canBeDivideByZero();
- }
- return mir_->toDiv()->canBeDivideByZero();
- }
- wasm::TrapSiteDesc trapSiteDesc() const {
- MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
- if (mir_->isMod()) {
- return mir_->toMod()->trapSiteDesc();
- }
- return mir_->toDiv()->trapSiteDesc();
- }
-};
-
} // namespace jit
} // namespace js
diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -294,20 +294,26 @@ void LIRGeneratorARM64::lowerModI(MMod* mod) {
}
void LIRGeneratorARM64::lowerDivI64(MDiv* div) {
- LDivOrModI64* lir = new (alloc())
- LDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs()));
+ auto* lir = new (alloc())
+ LDivI64(useRegisterAtStart(div->lhs()), useRegisterAtStart(div->rhs()));
defineInt64(lir, div);
}
+void LIRGeneratorARM64::lowerModI64(MMod* mod) {
+ auto* lir =
+ new (alloc()) LModI64(useRegister(mod->lhs()), useRegister(mod->rhs()));
+ defineInt64(lir, mod);
+}
+
void LIRGeneratorARM64::lowerUDivI64(MDiv* div) {
- LUDivOrModI64* lir = new (alloc())
- LUDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs()));
+ auto* lir = new (alloc())
+ LUDivI64(useRegisterAtStart(div->lhs()), useRegisterAtStart(div->rhs()));
defineInt64(lir, div);
}
void LIRGeneratorARM64::lowerUModI64(MMod* mod) {
- LUDivOrModI64* lir = new (alloc())
- LUDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs()));
+ auto* lir =
+ new (alloc()) LUModI64(useRegister(mod->lhs()), useRegister(mod->rhs()));
defineInt64(lir, mod);
}
@@ -315,12 +321,6 @@ void LIRGeneratorARM64::lowerWasmBuiltinDivI64(MWasmBuiltinDivI64* div) {
MOZ_CRASH("We don't use runtime div for this architecture");
}
-void LIRGeneratorARM64::lowerModI64(MMod* mod) {
- LDivOrModI64* lir = new (alloc())
- LDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs()));
- defineInt64(lir, mod);
-}
-
void LIRGeneratorARM64::lowerWasmBuiltinModI64(MWasmBuiltinModI64* mod) {
MOZ_CRASH("We don't use runtime mod for this architecture");
}