commit 8a0ce9ee7a6a3e0479de1d299a00d0f82b9f76aa
parent 177ecde7d631a7201c2f8363cef0373efc6c17fb
Author: André Bargull <andre.bargull@gmail.com>
Date: Thu, 23 Oct 2025 09:56:10 +0000
Bug 1995496 - Part 1: Use div+mod sequence on risc64. r=spidermonkey-reviewers,iain
From <https://riscv.github.io/riscv-isa-manual/snapshot/unprivileged/#_division_operations>:
> If both the quotient and remainder are required from the same division, the
> recommended code sequence is: `DIV[U] rdq, rs1, rs2; REM[U] rdr, rs1, rs2`
> (`rdq` cannot be the same as `rs1` or `rs2`). Microarchitectures can then
> fuse these into a single divide operation instead of performing two separate
> divides.
Differential Revision: https://phabricator.services.mozilla.com/D269367
Diffstat:
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.cpp b/js/src/jit/riscv64/MacroAssembler-riscv64.cpp
@@ -6508,9 +6508,21 @@ void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj,
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);
- divw(rd, rj, rk);
+
+ if (dest != rd) {
+ mv(rd, dest);
+ }
}
void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj,
@@ -6518,7 +6530,21 @@ void MacroAssemblerRiscv64::ma_div_branch_overflow(Register rd, Register rj,
UseScratchRegisterScope temps(this);
Register scratch = temps.Acquire();
ma_li(scratch, imm);
- ma_div_branch_overflow(rd, rj, scratch, overflow);
+
+ 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,