commit 1b30618ccf0f6e1febaac598fbb6717d0d7402d3
parent 8a0ce9ee7a6a3e0479de1d299a00d0f82b9f76aa
Author: André Bargull <andre.bargull@gmail.com>
Date: Thu, 23 Oct 2025 09:56:10 +0000
Bug 1995496 - Part 2: Inline ma_div_branch_overflow into callers. r=spidermonkey-reviewers,iain
The name `ma_div_branch_overflow` is misleading, because there's no "overflow".
Inlining the method also makes it easier to use the recommended div-mod
sequence on riscv64.
Differential Revision: https://phabricator.services.mozilla.com/D269368
Diffstat:
9 files changed, 26 insertions(+), 137 deletions(-)
diff --git a/js/src/jit/loong64/CodeGenerator-loong64.cpp b/js/src/jit/loong64/CodeGenerator-loong64.cpp
@@ -995,7 +995,6 @@ void CodeGenerator::visitMulI64(LMulI64* lir) {
}
void CodeGenerator::visitDivI(LDivI* ins) {
- // Extract the registers from this instruction
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register dest = ToRegister(ins->output());
@@ -1057,8 +1056,6 @@ void CodeGenerator::visitDivI(LDivI* ins) {
bailoutCmp32(Assembler::LessThan, rhs, Imm32(0), ins->snapshot());
masm.bind(&nonzero);
}
- // Note: above safety checks could not be verified as Ion seems to be
- // smarter and requires double arithmetic in such cases.
// All regular. Lets call div.
if (mir->canTruncateRemainder()) {
@@ -1066,9 +1063,10 @@ void CodeGenerator::visitDivI(LDivI* ins) {
} else {
MOZ_ASSERT(mir->fallible());
- Label remainderNonZero;
- masm.ma_div_branch_overflow(dest, lhs, rhs, &remainderNonZero);
- bailoutFrom(&remainderNonZero, ins->snapshot());
+ masm.as_mod_w(temp, lhs, rhs);
+ bailoutCmp32(Assembler::NonZero, temp, temp, ins->snapshot());
+
+ masm.as_div_w(dest, lhs, rhs);
}
masm.bind(&done);
@@ -1116,7 +1114,6 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
}
void CodeGenerator::visitModI(LModI* ins) {
- // Extract the registers from this instruction
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register dest = ToRegister(ins->output());
diff --git a/js/src/jit/loong64/MacroAssembler-loong64.cpp b/js/src/jit/loong64/MacroAssembler-loong64.cpp
@@ -1632,24 +1632,6 @@ void MacroAssemblerLOONG64::ma_mul32TestOverflow(Register rd, Register rj,
ma_b(rd, scratch, overflow, Assembler::NotEqual);
}
-void MacroAssemblerLOONG64::ma_div_branch_overflow(Register rd, Register rj,
- Register rk,
- Label* overflow) {
- UseScratchRegisterScope temps(asMasm());
- Register scratch = temps.Acquire();
- as_mod_w(scratch, rj, rk);
- ma_b(scratch, scratch, overflow, Assembler::NonZero);
- as_div_w(rd, rj, rk);
-}
-
-void MacroAssemblerLOONG64::ma_div_branch_overflow(Register rd, Register rj,
- Imm32 imm, Label* overflow) {
- UseScratchRegisterScope temps(asMasm());
- Register scratch = temps.Acquire();
- ma_li(scratch, imm);
- ma_div_branch_overflow(rd, rj, scratch, overflow);
-}
-
void MacroAssemblerLOONG64::ma_mod_mask(Register src, Register dest,
Register hold, Register remain,
int32_t shift, Label* negZero) {
diff --git a/js/src/jit/loong64/MacroAssembler-loong64.h b/js/src/jit/loong64/MacroAssembler-loong64.h
@@ -312,12 +312,6 @@ class MacroAssemblerLOONG64 : public Assembler {
void ma_mul32TestOverflow(Register rd, Register rj, Imm32 imm,
Label* overflow);
- // divisions
- void ma_div_branch_overflow(Register rd, Register rj, Register rk,
- Label* overflow);
- void ma_div_branch_overflow(Register rd, Register rj, Imm32 imm,
- Label* overflow);
-
// fast mod, uses scratch registers, and thus needs to be in the assembler
// implicitly assumes that we can overwrite dest at the beginning of the
// sequence
diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -484,7 +484,6 @@ void CodeGenerator::visitMulI64(LMulI64* lir) {
}
void CodeGenerator::visitDivI(LDivI* ins) {
- // Extract the registers from this instruction
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register dest = ToRegister(ins->output());
@@ -546,8 +545,6 @@ void CodeGenerator::visitDivI(LDivI* ins) {
bailoutCmp32(Assembler::LessThan, rhs, Imm32(0), ins->snapshot());
masm.bind(&nonzero);
}
- // Note: above safety checks could not be verified as Ion seems to be
- // smarter and requires double arithmetic in such cases.
// All regular. Lets call div.
if (mir->canTruncateRemainder()) {
@@ -560,9 +557,20 @@ void CodeGenerator::visitDivI(LDivI* ins) {
} else {
MOZ_ASSERT(mir->fallible());
- Label remainderNonZero;
- masm.ma_div_branch_overflow(dest, lhs, rhs, &remainderNonZero);
- bailoutFrom(&remainderNonZero, ins->snapshot());
+#ifdef MIPSR6
+ masm.as_mod(temp, lhs, rhs);
+#else
+ masm.as_div(lhs, rhs);
+ masm.as_mfhi(temp);
+#endif
+
+ bailoutCmp32(Assembler::NonZero, temp, temp, ins->snapshot());
+
+#ifdef MIPSR6
+ masm.as_div(dest, lhs, rhs);
+#else
+ masm.as_mflo(dest);
+#endif
}
masm.bind(&done);
@@ -609,7 +617,6 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
}
void CodeGenerator::visitModI(LModI* ins) {
- // Extract the registers from this instruction
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register dest = ToRegister(ins->output());
diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -386,39 +386,6 @@ void MacroAssemblerMIPSShared::ma_mul32TestOverflow(Register rd, Register rs,
ma_b(rd, scratch, overflow, Assembler::NotEqual);
}
-void MacroAssemblerMIPSShared::ma_div_branch_overflow(Register rd, Register rs,
- Register rt,
- Label* overflow) {
- UseScratchRegisterScope temps(*this);
- Register scratch = temps.Acquire();
-#ifdef MIPSR6
- if (rd == rs) {
- Register scratch2 = temps.Acquire();
- ma_move(scratch2, rs);
- rs = scratch2;
- }
- as_mod(scratch, rs, rt);
-#else
- as_div(rs, rt);
- as_mfhi(scratch);
-#endif
- ma_b(scratch, scratch, overflow, Assembler::NonZero);
-#ifdef MIPSR6
- as_div(rd, rs, rt);
-#else
- as_mflo(rd);
-#endif
-}
-
-void MacroAssemblerMIPSShared::ma_div_branch_overflow(Register rd, Register rs,
- Imm32 imm,
- Label* overflow) {
- UseScratchRegisterScope temps(*this);
- Register scratch = temps.Acquire();
- ma_li(scratch, imm);
- ma_div_branch_overflow(rd, rs, scratch, overflow);
-}
-
void MacroAssemblerMIPSShared::ma_mod_mask(Register src, Register dest,
Register hold, Register remain,
int32_t shift, Label* negZero) {
diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
@@ -147,12 +147,6 @@ class MacroAssemblerMIPSShared : public Assembler {
void ma_mul32TestOverflow(Register rd, Register rs, Imm32 imm,
Label* overflow);
- // divisions
- void ma_div_branch_overflow(Register rd, Register rs, Register rt,
- Label* overflow);
- void ma_div_branch_overflow(Register rd, Register rs, Imm32 imm,
- Label* overflow);
-
// fast mod, uses scratch registers, and thus needs to be in the assembler
// implicitly assumes that we can overwrite dest at the beginning of the
// sequence
diff --git a/js/src/jit/riscv64/CodeGenerator-riscv64.cpp b/js/src/jit/riscv64/CodeGenerator-riscv64.cpp
@@ -465,8 +465,6 @@ void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) {
Register rhs = ToRegister(lir->rhs());
Register output = ToRegister(lir->output());
- Label done;
-
// Prevent divide by zero.
if (lir->canBeDivideByZero()) {
Label nonZero;
@@ -480,8 +478,6 @@ void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) {
} else {
masm.ma_divu64(output, lhs, rhs);
}
-
- masm.bind(&done);
}
void CodeGenerator::visitWasmLoadI64(LWasmLoadI64* lir) {
@@ -1055,7 +1051,6 @@ void CodeGenerator::visitMulI64(LMulI64* lir) {
}
void CodeGenerator::visitDivI(LDivI* ins) {
- // Extract the registers from this instruction
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register dest = ToRegister(ins->output());
@@ -1117,18 +1112,21 @@ void CodeGenerator::visitDivI(LDivI* ins) {
bailoutCmp32(Assembler::LessThan, rhs, Imm32(0), ins->snapshot());
masm.bind(&nonzero);
}
- // Note: above safety checks could not be verified as Ion seems to be
- // smarter and requires double arithmetic in such cases.
// All regular. Lets call div.
if (mir->canTruncateRemainder()) {
masm.ma_div32(dest, lhs, rhs);
} else {
MOZ_ASSERT(mir->fallible());
+ MOZ_ASSERT(lhs != dest && rhs != dest);
+
+ // The recommended code sequence to obtain both the quotient and remainder
+ // is div[u] followed by mod[u].
+ masm.ma_div32(dest, lhs, rhs);
+ masm.ma_mod32(temp, lhs, rhs);
- Label remainderNonZero;
- masm.ma_div_branch_overflow(dest, lhs, rhs, &remainderNonZero);
- bailoutFrom(&remainderNonZero, ins->snapshot());
+ // If the remainder is != 0, bailout since this must be a double.
+ bailoutCmp32(Assembler::NonZero, temp, temp, ins->snapshot());
}
masm.bind(&done);
diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.cpp b/js/src/jit/riscv64/MacroAssembler-riscv64.cpp
@@ -6503,50 +6503,6 @@ void MacroAssemblerRiscv64::Popcnt64(Register rd, Register rs,
}
#endif
-void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj,
- Register rk,
- Label* overflow) {
- UseScratchRegisterScope temps(this);
- Register scratch = temps.Acquire();
-
- Register dest = rd;
- if (rd == rj || rd == rk) {
- dest = temps.Acquire();
- }
-
- // The recommended code sequence to obtain both the quotient and remainder
- // is div[u] followed by mod[u].
- ma_div32(dest, rj, rk);
- ma_mod32(scratch, rj, rk);
- ma_b(scratch, scratch, overflow, Assembler::NonZero);
-
- if (dest != rd) {
- mv(rd, dest);
- }
-}
-
-void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj,
- Imm32 imm, Label* overflow) {
- UseScratchRegisterScope temps(this);
- Register scratch = temps.Acquire();
- ma_li(scratch, imm);
-
- Register dest = rd;
- if (rd == rj) {
- dest = temps.Acquire();
- }
-
- // The recommended code sequence to obtain both the quotient and remainder
- // is div[u] followed by mod[u].
- ma_div32(dest, rj, scratch);
- ma_mod32(scratch, rj, scratch);
- ma_b(scratch, scratch, overflow, Assembler::NonZero);
-
- if (dest != rd) {
- mv(rd, dest);
- }
-}
-
void MacroAssemblerRiscv64::ma_mod_mask(Register src, Register dest,
Register hold, Register remain,
int32_t shift, Label* negZero) {
diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.h b/js/src/jit/riscv64/MacroAssembler-riscv64.h
@@ -365,12 +365,6 @@ class MacroAssemblerRiscv64 : public Assembler {
void ma_mul32TestOverflow(Register rd, Register rj, Imm32 imm,
Label* overflow);
- // divisions
- void ma_div_branch_overflow(Register rd, Register rj, Register rk,
- Label* overflow);
- void ma_div_branch_overflow(Register rd, Register rj, Imm32 imm,
- Label* overflow);
-
// fast mod, uses scratch registers, and thus needs to be in the assembler
// implicitly assumes that we can overwrite dest at the beginning of the
// sequence