commit e9fa485e4ac0f53d50f0a7ae49e10de7ca2deb84
parent 38a0c9534a4888903ecc02eb9f11aad7909438b9
Author: André Bargull <andre.bargull@gmail.com>
Date: Thu, 6 Nov 2025 07:45:55 +0000
Bug 1998162: Improve lowering and codegen for div/mod instructions on riscv64. r=spidermonkey-reviewers,iain
Ports the changes from bug 1997975 to riscv64.
Changes:
- Splits the `DivOrMod` instructions into separate instructions.
- The `rem[w]` instruction returns zero for `INT_MIN % -1` on riscv64, so no
extra code is needed to handle this case.
- `divw` returns `INT32_MIN` for `INT32_MIN / -1`, so we also don't need to
special case this for truncated division.
Differential Revision: https://phabricator.services.mozilla.com/D271222
Diffstat:
4 files changed, 225 insertions(+), 253 deletions(-)
diff --git a/js/src/jit/LIROps.yaml b/js/src/jit/LIROps.yaml
@@ -4119,7 +4119,7 @@
# Negative divisor case not implemented for all targets.
negativeDivisor: bool
#endif
-#if defined(JS_CODEGEN_MIPS64) || defined(JS_CODEGEN_LOONG64) || defined(JS_CODEGEN_RISCV64)
+#if defined(JS_CODEGEN_MIPS64) || defined(JS_CODEGEN_LOONG64)
num_temps: 1
#endif
mir_op: Div
@@ -4639,14 +4639,47 @@
#endif
#ifdef JS_CODEGEN_RISCV64
-- name: DivOrModI64
- gen_boilerplate: false
+- name: UDiv
+ result_type: WordSized
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Div
-- name: UDivOrMod
- gen_boilerplate: false
+- name: UMod
+ result_type: WordSized
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Mod
-- name: UDivOrModI64
- gen_boilerplate: false
+- name: DivI64
+ result_type: Int64
+ operands:
+ lhs: WordSized
+ rhs: WordSized
+ mir_op: Div
+
+- 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: ModMaskI
result_type: WordSized
diff --git a/js/src/jit/riscv64/CodeGenerator-riscv64.cpp b/js/src/jit/riscv64/CodeGenerator-riscv64.cpp
@@ -409,62 +409,82 @@ void CodeGeneratorRiscv64::emitBigIntPtrMod(LBigIntPtrMod* ins,
masm.ma_mod64(output, dividend, divisor);
}
-void CodeGenerator::visitDivOrModI64(LDivOrModI64* lir) {
+template <class LIR>
+static void TrapIfDivideByZero(MacroAssembler& masm, LIR* lir, Register rhs) {
+ auto* mir = lir->mir();
+ MOZ_ASSERT(mir->trapOnError());
+
+ if (mir->canBeDivideByZero()) {
+ Label nonZero;
+ masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero, ShortJump);
+ masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
+ masm.bind(&nonZero);
+ }
+}
+
+void CodeGenerator::visitDivI64(LDivI64* lir) {
Register lhs = ToRegister(lir->lhs());
Register rhs = ToRegister(lir->rhs());
Register output = ToRegister(lir->output());
- Label done;
+ MDiv* div = lir->mir();
// Handle divide by zero.
- if (lir->canBeDivideByZero()) {
- Label nonZero;
- masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->trapSiteDesc());
- masm.bind(&nonZero);
- }
+ TrapIfDivideByZero(masm, lir, rhs);
// Handle an integer overflow exception from INT64_MIN / -1.
- if (lir->canBeNegativeOverflow()) {
+ if (div->canBeNegativeOverflow()) {
Label notOverflow;
masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(INT64_MIN), ¬Overflow);
masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(-1), ¬Overflow);
- if (lir->mir()->isMod()) {
- masm.ma_xor(output, output, Operand(output));
- } else {
- masm.wasmTrap(wasm::Trap::IntegerOverflow, lir->trapSiteDesc());
- }
- masm.jump(&done);
+ masm.wasmTrap(wasm::Trap::IntegerOverflow, div->trapSiteDesc());
masm.bind(¬Overflow);
}
- if (lir->mir()->isMod()) {
- masm.ma_mod64(output, lhs, rhs);
- } else {
- masm.ma_div64(output, lhs, rhs);
- }
+ masm.ma_div64(output, lhs, rhs);
+}
- masm.bind(&done);
+void CodeGenerator::visitModI64(LModI64* lir) {
+ Register lhs = ToRegister(lir->lhs());
+ Register rhs = ToRegister(lir->rhs());
+ Register output = ToRegister(lir->output());
+
+ // rem result table:
+ // --------------------------------
+ // | Dividend | Divisor | Result |
+ // |------------------------------|
+ // | X | 0 | X |
+ // | INT64_MIN | -1 | 0 |
+ // --------------------------------
+ //
+ // NOTE: INT64_MIN % -1 returns 0, which is the expected result.
+
+ // Handle divide by zero.
+ TrapIfDivideByZero(masm, lir, rhs);
+
+ masm.ma_mod64(output, lhs, rhs);
}
-void CodeGenerator::visitUDivOrModI64(LUDivOrModI64* lir) {
+void CodeGenerator::visitUDivI64(LUDivI64* lir) {
Register lhs = ToRegister(lir->lhs());
Register rhs = ToRegister(lir->rhs());
Register output = ToRegister(lir->output());
// Prevent divide by zero.
- if (lir->canBeDivideByZero()) {
- Label nonZero;
- masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, lir->trapSiteDesc());
- masm.bind(&nonZero);
- }
+ TrapIfDivideByZero(masm, lir, rhs);
- if (lir->mir()->isMod()) {
- masm.ma_modu64(output, lhs, rhs);
- } else {
- masm.ma_divu64(output, lhs, rhs);
- }
+ masm.ma_divu64(output, lhs, rhs);
+}
+
+void CodeGenerator::visitUModI64(LUModI64* lir) {
+ Register lhs = ToRegister(lir->lhs());
+ Register rhs = ToRegister(lir->rhs());
+ Register output = ToRegister(lir->output());
+
+ // Prevent divide by zero.
+ TrapIfDivideByZero(masm, lir, rhs);
+
+ masm.ma_modu64(output, lhs, rhs);
}
void CodeGenerator::visitWasmLoadI64(LWasmLoadI64* lir) {
@@ -996,18 +1016,26 @@ void CodeGenerator::visitDivI(LDivI* ins) {
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register dest = ToRegister(ins->output());
- Register temp = ToRegister(ins->temp0());
MDiv* mir = ins->mir();
+ // divw result table:
+ // ------------------------------------
+ // | Dividend | Divisor | Result |
+ // |----------------------------------|
+ // | X | 0 | -1 |
+ // | INT32_MIN | -1 | INT32_MIN |
+ // ------------------------------------
+ //
+ // NOTE: INT32_MIN / -1 returns INT32_MIN, which is the expected (truncated)
+ // result. Division by zero returns -1, whereas the truncated result should
+ // be 0, so it needs to be handled explicitly.
+
Label done;
// Handle divide by zero.
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
- Label nonZero;
- masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
- masm.bind(&nonZero);
+ TrapIfDivideByZero(masm, ins, rhs);
} else if (mir->canTruncateInfinities()) {
// Truncated division by zero is zero (Infinity|0 == 0)
Label notzero;
@@ -1021,33 +1049,27 @@ void CodeGenerator::visitDivI(LDivI* ins) {
}
}
- // Handle an integer overflow exception from -2147483648 / -1.
- if (mir->canBeNegativeOverflow()) {
+ // Handle an integer overflow from (INT32_MIN / -1).
+ // The integer division gives INT32_MIN, but should be -(double)INT32_MIN.
+ if (mir->canBeNegativeOverflow() &&
+ (mir->trapOnError() || !mir->canTruncateOverflow())) {
Label notMinInt;
- masm.move32(Imm32(INT32_MIN), temp);
- masm.ma_b(lhs, temp, ¬MinInt, Assembler::NotEqual, ShortJump);
+ masm.ma_b(lhs, Imm32(INT32_MIN), ¬MinInt, Assembler::NotEqual,
+ ShortJump);
- masm.move32(Imm32(-1), temp);
if (mir->trapOnError()) {
Label ok;
- masm.ma_b(rhs, temp, &ok, Assembler::NotEqual);
+ masm.ma_b(rhs, Imm32(-1), &ok, Assembler::NotEqual, ShortJump);
masm.wasmTrap(wasm::Trap::IntegerOverflow, mir->trapSiteDesc());
masm.bind(&ok);
- } else if (mir->canTruncateOverflow()) {
- // (-INT32_MIN)|0 == INT32_MIN
- Label skip;
- masm.ma_b(rhs, temp, &skip, Assembler::NotEqual, ShortJump);
- masm.move32(Imm32(INT32_MIN), dest);
- masm.ma_branch(&done, ShortJump);
- masm.bind(&skip);
} else {
MOZ_ASSERT(mir->fallible());
- bailoutCmp32(Assembler::Equal, rhs, temp, ins->snapshot());
+ bailoutCmp32(Assembler::Equal, rhs, Imm32(-1), ins->snapshot());
}
masm.bind(¬MinInt);
}
- // Handle negative 0. (0/-Y)
+ // Handle negative zero: lhs == 0 && rhs < 0.
if (!mir->canTruncateNegativeZero() && mir->canBeNegativeZero()) {
Label nonzero;
masm.ma_b(lhs, lhs, &nonzero, Assembler::NonZero, ShortJump);
@@ -1062,6 +1084,9 @@ void CodeGenerator::visitDivI(LDivI* ins) {
MOZ_ASSERT(mir->fallible());
MOZ_ASSERT(lhs != dest && rhs != dest);
+ UseScratchRegisterScope temps(masm);
+ Register temp = temps.Acquire();
+
// The recommended code sequence to obtain both the quotient and remainder
// is div[u] followed by mod[u].
masm.ma_div32(dest, lhs, rhs);
@@ -1077,11 +1102,13 @@ void CodeGenerator::visitDivI(LDivI* ins) {
void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
Register lhs = ToRegister(ins->numerator());
Register dest = ToRegister(ins->output());
- Register tmp = ToRegister(ins->temp0());
int32_t shift = ins->shift();
MOZ_ASSERT(0 <= shift && shift <= 31);
if (shift != 0) {
+ UseScratchRegisterScope temps(masm);
+ Register tmp = temps.Acquire();
+
MDiv* mir = ins->mir();
if (!mir->isTruncated()) {
// If the remainder is going to be != 0, bailout since this must
@@ -1122,43 +1149,29 @@ void CodeGenerator::visitModI(LModI* ins) {
MMod* mir = ins->mir();
Label done;
- // Prevent INT_MIN % -1;
- // The integer division will give INT_MIN, but we want -(double)INT_MIN.
- if (mir->canBeNegativeDividend()) {
- Label skip;
- masm.ma_b(lhs, Imm32(INT_MIN), &skip, Assembler::NotEqual, ShortJump);
- if (mir->isTruncated()) {
- // (INT_MIN % -1)|0 == 0
- masm.ma_b(rhs, Imm32(-1), &skip, Assembler::NotEqual, ShortJump);
- masm.move32(Imm32(0), dest);
- masm.ma_branch(&done, ShortJump);
- } else {
- MOZ_ASSERT(mir->fallible());
- bailoutCmp32(Assembler::Equal, rhs, Imm32(-1), ins->snapshot());
- }
- masm.bind(&skip);
- }
-
- // X % Y (with X < 0, Y != 0) is bad because the result should
- // have the sign of X, but -0 cannot be represented in
- // integers.
- // X % 0 is bad because it will give garbage, when it
- // should give either \infty, -\infty or NAN.
+ // remw result table:
+ // --------------------------------
+ // | Dividend | Divisor | Result |
+ // |------------------------------|
+ // | X | 0 | X |
+ // | INT32_MIN | -1 | 0 |
+ // --------------------------------
+ //
+ // NOTE: INT32_MIN % -1 returns 0, which is the expected result.
- // Testing X % Y. Compare Y with 0.
- // If Y == 0, we bailout.
+ // Prevent divide by zero.
if (mir->canBeDivideByZero()) {
- if (mir->isTruncated()) {
+ if (mir->trapOnError()) {
+ TrapIfDivideByZero(masm, ins, rhs);
+ } else if (mir->isTruncated()) {
+ // Truncated division by zero yields integer zero.
Label yNonZero;
masm.ma_b(rhs, Imm32(0), &yNonZero, Assembler::NotEqual, ShortJump);
- if (mir->trapOnError()) {
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, mir->trapSiteDesc());
- } else {
- masm.move32(Imm32(0), dest);
- masm.ma_branch(&done, ShortJump);
- }
+ masm.move32(Imm32(0), dest);
+ masm.ma_branch(&done, ShortJump);
masm.bind(&yNonZero);
} else {
+ // Non-truncated division by zero produces a non-integer.
MOZ_ASSERT(mir->fallible());
bailoutCmp32(Assembler::Zero, rhs, rhs, ins->snapshot());
}
@@ -1166,12 +1179,13 @@ void CodeGenerator::visitModI(LModI* ins) {
masm.ma_mod32(dest, lhs, rhs);
- // If X%Y == 0 and X < 0, then we *actually* wanted to return -0, so bailing
- // out. -0.0|0 == 0
if (mir->canBeNegativeDividend() && !mir->isTruncated()) {
MOZ_ASSERT(mir->fallible());
MOZ_ASSERT(lhs != dest);
+ // If dest == 0 and lhs < 0, then the result should be double -0.0.
+ // Note that this guard handles lhs == INT_MIN and rhs == -1.
+
masm.ma_b(dest, Imm32(0), &done, Assembler::NotEqual, ShortJump);
bailoutCmp32(Assembler::Signed, lhs, lhs, ins->snapshot());
}
@@ -2049,55 +2063,87 @@ void CodeGenerator::visitWasmCompareAndSelect(LWasmCompareAndSelect* ins) {
trueExprAndDest);
}
-void CodeGenerator::visitUDivOrMod(LUDivOrMod* ins) {
+void CodeGenerator::visitUDiv(LUDiv* ins) {
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register output = ToRegister(ins->output());
Label done;
+ MDiv* mir = ins->mir();
+
// Prevent divide by zero.
- if (ins->canBeDivideByZero()) {
- if (ins->mir()->isTruncated()) {
- if (ins->trapOnError()) {
- Label nonZero;
- masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero);
- masm.wasmTrap(wasm::Trap::IntegerDivideByZero, ins->trapSiteDesc());
- masm.bind(&nonZero);
- } else {
- // Infinity|0 == 0
- Label notzero;
- masm.ma_b(rhs, rhs, ¬zero, Assembler::NonZero, ShortJump);
- masm.move32(Imm32(0), output);
- masm.ma_branch(&done, ShortJump);
- masm.bind(¬zero);
- }
+ if (mir->canBeDivideByZero()) {
+ if (mir->trapOnError()) {
+ TrapIfDivideByZero(masm, ins, rhs);
+ } else if (mir->isTruncated()) {
+ // Infinity|0 == 0
+ Label nonZero;
+ masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero, ShortJump);
+ masm.move32(Imm32(0), output);
+ masm.ma_branch(&done, ShortJump);
+ masm.bind(&nonZero);
} else {
bailoutCmp32(Assembler::Equal, rhs, Imm32(0), ins->snapshot());
}
}
// If the remainder is > 0, bailout since this must be a double.
- if (ins->mir()->isDiv()) {
- if (ins->mir()->toDiv()->canTruncateRemainder()) {
- masm.ma_divu32(output, lhs, rhs);
- } else {
- MOZ_ASSERT(lhs != output && rhs != output);
+ if (mir->canTruncateRemainder()) {
+ masm.ma_divu32(output, lhs, rhs);
+ } else {
+ MOZ_ASSERT(lhs != output && rhs != output);
- UseScratchRegisterScope temps(&masm);
- Register scratch = temps.Acquire();
+ UseScratchRegisterScope temps(&masm);
+ Register scratch = temps.Acquire();
- // The recommended code sequence to obtain both the quotient and remainder
- // is div[u] followed by mod[u].
- masm.ma_divu32(output, lhs, rhs);
- masm.ma_modu32(scratch, lhs, rhs);
+ // The recommended code sequence to obtain both the quotient and remainder
+ // is div[u] followed by mod[u].
+ masm.ma_divu32(output, lhs, rhs);
+ masm.ma_modu32(scratch, lhs, rhs);
- bailoutCmp32(Assembler::NonZero, scratch, scratch, ins->snapshot());
+ bailoutCmp32(Assembler::NonZero, scratch, scratch, ins->snapshot());
+ }
+
+ // Unsigned div can return a value that's not a signed int32.
+ // If our users aren't expecting that, bail.
+ if (!mir->isTruncated()) {
+ bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());
+ }
+
+ masm.bind(&done);
+}
+
+void CodeGenerator::visitUMod(LUMod* ins) {
+ Register lhs = ToRegister(ins->lhs());
+ Register rhs = ToRegister(ins->rhs());
+ Register output = ToRegister(ins->output());
+ Label done;
+
+ MMod* mir = ins->mir();
+
+ // Prevent divide by zero.
+ if (mir->canBeDivideByZero()) {
+ if (mir->trapOnError()) {
+ TrapIfDivideByZero(masm, ins, rhs);
+ } else if (mir->isTruncated()) {
+ // NaN|0 == 0
+ Label nonZero;
+ masm.ma_b(rhs, rhs, &nonZero, Assembler::NonZero, ShortJump);
+ masm.move32(Imm32(0), output);
+ masm.ma_branch(&done, ShortJump);
+ masm.bind(&nonZero);
+ } else {
+ bailoutCmp32(Assembler::Equal, rhs, Imm32(0), ins->snapshot());
}
- } else {
- masm.ma_modu32(output, lhs, rhs);
}
- if (!ins->mir()->isTruncated()) {
+ masm.ma_modu32(output, lhs, rhs);
+
+ // Bail if the output would be negative.
+ //
+ // LUMod inputs may be Uint32, so care is taken to ensure the result is not
+ // unexpectedly signed.
+ if (!mir->isTruncated()) {
bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());
}
diff --git a/js/src/jit/riscv64/LIR-riscv64.h b/js/src/jit/riscv64/LIR-riscv64.h
@@ -26,109 +26,6 @@ class LUnbox : public LInstructionHelper<1, BOX_PIECES, 0> {
const char* extraName() const { return StringFromMIRType(mir()->type()); }
};
-class LUDivOrMod : public LBinaryMath<0> {
- public:
- LIR_HEADER(UDivOrMod);
-
- LUDivOrMod() : LBinaryMath(classOpcode) {}
-
- 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 trapOnError() const {
- if (mir_->isMod()) {
- return mir_->toMod()->trapOnError();
- }
- return mir_->toDiv()->trapOnError();
- }
-
- const wasm::TrapSiteDesc& trapSiteDesc() const {
- MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
- if (mir_->isMod()) {
- return mir_->toMod()->trapSiteDesc();
- }
- return mir_->toDiv()->trapSiteDesc();
- }
-};
-
-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();
- }
- const 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();
- }
- const 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/riscv64/Lowering-riscv64.cpp b/js/src/jit/riscv64/Lowering-riscv64.cpp
@@ -18,8 +18,6 @@
using namespace js;
using namespace js::jit;
-using mozilla::FloorLog2;
-
LTableSwitch* LIRGeneratorRiscv64::newLTableSwitch(
const LAllocation& in, const LDefinition& inputCopy) {
return new (alloc()) LTableSwitch(in, inputCopy, temp());
@@ -179,10 +177,10 @@ void LIRGeneratorRiscv64::lowerDivI(MDiv* div) {
// possible; division by negative powers of two can be optimized in a
// similar manner as positive powers of two, and division by other
// constants can be optimized by a reciprocal multiplication technique.
- int32_t shift = FloorLog2(rhs);
- if (rhs > 0 && 1 << shift == rhs) {
- auto* lir = new (alloc())
- LDivPowTwoI(useRegisterAtStart(div->lhs()), temp(), shift);
+ if (rhs > 0 && mozilla::IsPowerOfTwo(mozilla::Abs(rhs))) {
+ int32_t shift = mozilla::FloorLog2(rhs);
+ auto* lir =
+ new (alloc()) LDivPowTwoI(useRegisterAtStart(div->lhs()), shift);
if (div->fallible()) {
assignSnapshot(lir, div->bailoutKind());
}
@@ -200,7 +198,9 @@ void LIRGeneratorRiscv64::lowerDivI(MDiv* div) {
rhs = useRegisterAtStart(div->rhs());
}
- auto* lir = new (alloc()) LDivI(lhs, rhs, temp());
+ // RISCV64 has plenty of scratch registers, so we don't need to request an
+ // additonal temp register from the register allocator.
+ auto* lir = new (alloc()) LDivI(lhs, rhs, LDefinition::BogusTemp());
if (div->fallible()) {
assignSnapshot(lir, div->bailoutKind());
}
@@ -208,15 +208,15 @@ void LIRGeneratorRiscv64::lowerDivI(MDiv* div) {
}
void LIRGeneratorRiscv64::lowerDivI64(MDiv* div) {
- auto* lir = new (alloc()) LDivOrModI64(useRegisterAtStart(div->lhs()),
- useRegisterAtStart(div->rhs()));
+ auto* lir = new (alloc())
+ LDivI64(useRegisterAtStart(div->lhs()), useRegisterAtStart(div->rhs()));
defineInt64(lir, div);
}
void LIRGeneratorRiscv64::lowerModI(MMod* mod) {
if (mod->rhs()->isConstant()) {
int32_t rhs = mod->rhs()->toConstant()->toInt32();
- int32_t shift = FloorLog2(rhs);
+ int32_t shift = mozilla::FloorLog2(rhs);
if (rhs > 0 && 1 << shift == rhs) {
LModPowTwoI* lir =
new (alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
@@ -225,7 +225,8 @@ void LIRGeneratorRiscv64::lowerModI(MMod* mod) {
}
define(lir, mod);
return;
- } else if (shift < 31 && (1 << (shift + 1)) - 1 == rhs) {
+ }
+ if (shift < 31 && (1 << (shift + 1)) - 1 == rhs) {
LModMaskI* lir = new (alloc())
LModMaskI(useRegister(mod->lhs()), temp(), temp(), shift + 1);
if (mod->fallible()) {
@@ -253,8 +254,8 @@ void LIRGeneratorRiscv64::lowerModI(MMod* mod) {
}
void LIRGeneratorRiscv64::lowerModI64(MMod* mod) {
- auto* lir = new (alloc()) LDivOrModI64(useRegisterAtStart(mod->lhs()),
- useRegisterAtStart(mod->rhs()));
+ auto* lir = new (alloc())
+ LModI64(useRegisterAtStart(mod->lhs()), useRegisterAtStart(mod->rhs()));
defineInt64(lir, mod);
}
@@ -268,36 +269,31 @@ void LIRGeneratorRiscv64::lowerUDiv(MDiv* div) {
rhs = useRegisterAtStart(div->rhs());
}
- auto* lir = new (alloc()) LUDivOrMod;
- lir->setOperand(0, lhs);
- lir->setOperand(1, rhs);
+ auto* lir = new (alloc()) LUDiv(lhs, rhs);
if (div->fallible()) {
assignSnapshot(lir, div->bailoutKind());
}
-
define(lir, div);
}
void LIRGeneratorRiscv64::lowerUDivI64(MDiv* div) {
- auto* lir = new (alloc()) LUDivOrModI64(useRegisterAtStart(div->lhs()),
- useRegisterAtStart(div->rhs()));
+ auto* lir = new (alloc())
+ LUDivI64(useRegisterAtStart(div->lhs()), useRegisterAtStart(div->rhs()));
defineInt64(lir, div);
}
void LIRGeneratorRiscv64::lowerUMod(MMod* mod) {
- auto* lir = new (alloc()) LUDivOrMod;
- lir->setOperand(0, useRegisterAtStart(mod->lhs()));
- lir->setOperand(1, useRegisterAtStart(mod->rhs()));
+ auto* lir = new (alloc())
+ LUMod(useRegisterAtStart(mod->lhs()), useRegisterAtStart(mod->rhs()));
if (mod->fallible()) {
assignSnapshot(lir, mod->bailoutKind());
}
-
define(lir, mod);
}
void LIRGeneratorRiscv64::lowerUModI64(MMod* mod) {
- auto* lir = new (alloc()) LUDivOrModI64(useRegisterAtStart(mod->lhs()),
- useRegisterAtStart(mod->rhs()));
+ auto* lir = new (alloc())
+ LUModI64(useRegisterAtStart(mod->lhs()), useRegisterAtStart(mod->rhs()));
defineInt64(lir, mod);
}