commit 46af4d9a893a594fd1dbc8ee5d2dbe4ba8a69baf
parent f8e4fb61645e565b3d8d876c7f351a509bcd354c
Author: André Bargull <andre.bargull@gmail.com>
Date: Thu, 23 Oct 2025 09:56:07 +0000
Bug 1995490 - Part 2: Replace modulus with bit-and for shift/rotate with immediate. r=spidermonkey-reviewers,iain
Shift and rotate instructions are defined as using the low five resp. six bits.
This is more accurately implemented when using bit-and instead of (signed)
integer modulus.
Differential Revision: https://phabricator.services.mozilla.com/D269357
Diffstat:
7 files changed, 44 insertions(+), 46 deletions(-)
diff --git a/js/src/jit/loong64/CodeGenerator-loong64.cpp b/js/src/jit/loong64/CodeGenerator-loong64.cpp
@@ -1079,19 +1079,20 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
Register dest = ToRegister(ins->output());
Register tmp = ToRegister(ins->temp0());
int32_t shift = ins->shift();
+ MOZ_ASSERT(0 <= shift && shift <= 31);
if (shift != 0) {
MDiv* mir = ins->mir();
if (!mir->isTruncated()) {
// If the remainder is going to be != 0, bailout since this must
// be a double.
- masm.as_slli_w(tmp, lhs, (32 - shift) % 32);
+ masm.as_slli_w(tmp, lhs, (32 - shift));
bailoutCmp32(Assembler::NonZero, tmp, tmp, ins->snapshot());
}
if (!mir->canBeNegativeDividend()) {
// Numerator is unsigned, so needs no adjusting. Do the shift.
- masm.as_srai_w(dest, lhs, shift % 32);
+ masm.as_srai_w(dest, lhs, shift);
return;
}
@@ -1100,15 +1101,15 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
// Power of 2" in Henry S. Warren, Jr.'s Hacker's Delight.
if (shift > 1) {
masm.as_srai_w(tmp, lhs, 31);
- masm.as_srli_w(tmp, tmp, (32 - shift) % 32);
+ masm.as_srli_w(tmp, tmp, (32 - shift));
masm.add32(lhs, tmp);
} else {
- masm.as_srli_w(tmp, lhs, (32 - shift) % 32);
+ masm.as_srli_w(tmp, lhs, (32 - shift));
masm.add32(lhs, tmp);
}
// Do the shift.
- masm.as_srai_w(dest, tmp, shift % 32);
+ masm.as_srai_w(dest, tmp, shift);
} else {
masm.move32(lhs, dest);
}
@@ -1302,21 +1303,21 @@ void CodeGenerator::visitShiftI(LShiftI* ins) {
switch (ins->bitop()) {
case JSOp::Lsh:
if (shift) {
- masm.as_slli_w(dest, lhs, shift % 32);
+ masm.as_slli_w(dest, lhs, shift);
} else {
masm.move32(lhs, dest);
}
break;
case JSOp::Rsh:
if (shift) {
- masm.as_srai_w(dest, lhs, shift % 32);
+ masm.as_srai_w(dest, lhs, shift);
} else {
masm.move32(lhs, dest);
}
break;
case JSOp::Ursh:
if (shift) {
- masm.as_srli_w(dest, lhs, shift % 32);
+ masm.as_srli_w(dest, lhs, shift);
} else {
// x >>> 0 can overflow.
if (ins->mir()->toUrsh()->fallible()) {
@@ -1441,7 +1442,7 @@ void CodeGenerator::visitUrshD(LUrshD* ins) {
FloatRegister out = ToFloatRegister(ins->output());
if (rhs->isConstant()) {
- masm.as_srli_w(temp, lhs, ToInt32(rhs) % 32);
+ masm.as_srli_w(temp, lhs, ToInt32(rhs) & 0x1f);
} else {
masm.as_srl_w(temp, lhs, ToRegister(rhs));
}
diff --git a/js/src/jit/loong64/MacroAssembler-loong64-inl.h b/js/src/jit/loong64/MacroAssembler-loong64-inl.h
@@ -735,7 +735,7 @@ void MacroAssembler::lshift32(Imm32 imm, Register dest) {
}
void MacroAssembler::lshift32(Imm32 imm, Register src, Register dest) {
- as_slli_w(dest, src, imm.value % 32);
+ as_slli_w(dest, src, imm.value & 0x1f);
}
void MacroAssembler::flexibleLshift32(Register src, Register dest) {
@@ -777,7 +777,7 @@ void MacroAssembler::rshift32(Imm32 imm, Register dest) {
}
void MacroAssembler::rshift32(Imm32 imm, Register src, Register dest) {
- as_srli_w(dest, src, imm.value % 32);
+ as_srli_w(dest, src, imm.value & 0x1f);
}
void MacroAssembler::flexibleRshift32(Register src, Register dest) {
@@ -794,7 +794,7 @@ void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) {
void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register src,
Register dest) {
- as_srai_w(dest, src, imm.value % 32);
+ as_srai_w(dest, src, imm.value & 0x1f);
}
void MacroAssembler::flexibleRshift32Arithmetic(Register src, Register dest) {
diff --git a/js/src/jit/loong64/Simulator-loong64.cpp b/js/src/jit/loong64/Simulator-loong64.cpp
@@ -3424,38 +3424,38 @@ void Simulator::decodeTypeOp17(SimInstruction* instr) {
setRegister(rd_reg(instr), rj(instr) & (~rk(instr)));
break;
case op_sll_w:
- setRegister(rd_reg(instr), (int32_t)rj(instr) << (rk_u(instr) % 32));
+ setRegister(rd_reg(instr), (int32_t)rj(instr) << (rk_u(instr) & 0x1f));
break;
case op_srl_w: {
alu_out =
- static_cast<int32_t>((uint32_t)rj_u(instr) >> (rk_u(instr) % 32));
+ static_cast<int32_t>((uint32_t)rj_u(instr) >> (rk_u(instr) & 0x1f));
setRegister(rd_reg(instr), alu_out);
break;
}
case op_sra_w:
- setRegister(rd_reg(instr), (int32_t)rj(instr) >> (rk_u(instr) % 32));
+ setRegister(rd_reg(instr), (int32_t)rj(instr) >> (rk_u(instr) & 0x1f));
break;
case op_sll_d:
- setRegister(rd_reg(instr), rj(instr) << (rk_u(instr) % 64));
+ setRegister(rd_reg(instr), rj(instr) << (rk_u(instr) & 0x3f));
break;
case op_srl_d: {
- alu_out = static_cast<int64_t>(rj_u(instr) >> (rk_u(instr) % 64));
+ alu_out = static_cast<int64_t>(rj_u(instr) >> (rk_u(instr) & 0x3f));
setRegister(rd_reg(instr), alu_out);
break;
}
case op_sra_d:
- setRegister(rd_reg(instr), rj(instr) >> (rk_u(instr) % 64));
+ setRegister(rd_reg(instr), rj(instr) >> (rk_u(instr) & 0x3f));
break;
case op_rotr_w: {
alu_out = static_cast<int32_t>(
RotateRight32(static_cast<const uint32_t>(rj_u(instr)),
- static_cast<const uint32_t>(rk_u(instr) % 32)));
+ static_cast<const uint32_t>(rk_u(instr) & 0x1f)));
setRegister(rd_reg(instr), alu_out);
break;
}
case op_rotr_d: {
alu_out = static_cast<int64_t>(
- RotateRight64((rj_u(instr)), (rk_u(instr) % 64)));
+ RotateRight64((rj_u(instr)), (rk_u(instr) & 0x3f)));
setRegister(rd_reg(instr), alu_out);
break;
}
diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -48,36 +48,36 @@ void MacroAssemblerMIPSShared::ma_liPatchable(Register dest, Imm32 imm) {
// Shifts
void MacroAssemblerMIPSShared::ma_sll(Register rd, Register rt, Imm32 shift) {
- as_sll(rd, rt, shift.value % 32);
+ as_sll(rd, rt, shift.value & 0x1f);
}
void MacroAssemblerMIPSShared::ma_srl(Register rd, Register rt, Imm32 shift) {
- as_srl(rd, rt, shift.value % 32);
+ as_srl(rd, rt, shift.value & 0x1f);
}
void MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Imm32 shift) {
- as_sra(rd, rt, shift.value % 32);
+ as_sra(rd, rt, shift.value & 0x1f);
}
void MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Imm32 shift) {
if (hasR2()) {
- as_rotr(rd, rt, shift.value % 32);
+ as_rotr(rd, rt, shift.value & 0x1f);
} else {
UseScratchRegisterScope temps(*this);
Register scratch = temps.Acquire();
- as_srl(scratch, rt, shift.value % 32);
- as_sll(rd, rt, (32 - (shift.value % 32)) % 32);
+ as_srl(scratch, rt, shift.value & 0x1f);
+ as_sll(rd, rt, 32 - (shift.value & 0x1f));
as_or(rd, rd, scratch);
}
}
void MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Imm32 shift) {
if (hasR2()) {
- as_rotr(rd, rt, (32 - (shift.value % 32)) % 32);
+ as_rotr(rd, rt, 32 - (shift.value & 0x1f));
} else {
UseScratchRegisterScope temps(*this);
Register scratch = temps.Acquire();
- as_srl(scratch, rt, (32 - (shift.value % 32)) % 32);
- as_sll(rd, rt, shift.value % 32);
+ as_srl(scratch, rt, 32 - (shift.value & 0x1f));
+ as_sll(rd, rt, shift.value & 0x1f);
as_or(rd, rd, scratch);
}
}
diff --git a/js/src/jit/riscv64/CodeGenerator-riscv64.cpp b/js/src/jit/riscv64/CodeGenerator-riscv64.cpp
@@ -1139,19 +1139,20 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
Register dest = ToRegister(ins->output());
Register tmp = ToRegister(ins->temp0());
int32_t shift = ins->shift();
+ MOZ_ASSERT(0 <= shift && shift <= 31);
if (shift != 0) {
MDiv* mir = ins->mir();
if (!mir->isTruncated()) {
// If the remainder is going to be != 0, bailout since this must
// be a double.
- masm.slliw(tmp, lhs, (32 - shift) % 32);
+ masm.slliw(tmp, lhs, (32 - shift));
bailoutCmp32(Assembler::NonZero, tmp, tmp, ins->snapshot());
}
if (!mir->canBeNegativeDividend()) {
// Numerator is unsigned, so needs no adjusting. Do the shift.
- masm.sraiw(dest, lhs, shift % 32);
+ masm.sraiw(dest, lhs, shift);
return;
}
@@ -1160,15 +1161,15 @@ void CodeGenerator::visitDivPowTwoI(LDivPowTwoI* ins) {
// Power of 2" in Henry S. Warren, Jr.'s Hacker's Delight.
if (shift > 1) {
masm.sraiw(tmp, lhs, 31);
- masm.srliw(tmp, tmp, (32 - shift) % 32);
+ masm.srliw(tmp, tmp, (32 - shift));
masm.add32(lhs, tmp);
} else {
- masm.srliw(tmp, lhs, (32 - shift) % 32);
+ masm.srliw(tmp, lhs, (32 - shift));
masm.add32(lhs, tmp);
}
// Do the shift.
- masm.sraiw(dest, tmp, shift % 32);
+ masm.sraiw(dest, tmp, shift);
} else {
masm.move32(lhs, dest);
}
@@ -1527,7 +1528,7 @@ void CodeGenerator::visitUrshD(LUrshD* ins) {
FloatRegister out = ToFloatRegister(ins->output());
if (rhs->isConstant()) {
- masm.srliw(temp, lhs, ToInt32(rhs) % 32);
+ masm.srliw(temp, lhs, ToInt32(rhs) & 0x1f);
} else {
masm.srlw(temp, lhs, ToRegister(rhs));
}
diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h b/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h
@@ -1592,7 +1592,7 @@ void MacroAssembler::lshift32(Imm32 imm, Register dest) {
}
void MacroAssembler::lshift32(Imm32 imm, Register src, Register dest) {
- slliw(dest, src, imm.value % 32);
+ slliw(dest, src, imm.value & 0x1f);
}
void MacroAssembler::lshift64(Register shift, Register64 dest) {
@@ -2006,7 +2006,7 @@ void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) {
void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register src,
Register dest) {
- sraiw(dest, src, imm.value % 32);
+ sraiw(dest, src, imm.value & 0x1f);
}
void MacroAssembler::rshift32(Register src, Register dest) {
@@ -2018,7 +2018,7 @@ void MacroAssembler::rshift32(Imm32 imm, Register dest) {
}
void MacroAssembler::rshift32(Imm32 imm, Register src, Register dest) {
- srliw(dest, src, imm.value % 32);
+ srliw(dest, src, imm.value & 0x1f);
}
void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) {
diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.cpp b/js/src/jit/riscv64/MacroAssembler-riscv64.cpp
@@ -6742,7 +6742,7 @@ void MacroAssemblerRiscv64::Rol(Register rd, Register rs, const Operand& rt) {
or_(rd, scratch, rd);
sext_w(rd, rd);
} else {
- Ror(rd, rs, Operand(32 - (rt.immediate() % 32)));
+ Ror(rd, rs, Operand(32 - (rt.immediate() & 0x1f)));
}
}
@@ -6756,12 +6756,10 @@ void MacroAssemblerRiscv64::Ror(Register rd, Register rs, const Operand& rt) {
or_(rd, scratch, rd);
sext_w(rd, rd);
} else {
- int64_t ror_value = rt.immediate() % 32;
+ int64_t ror_value = rt.immediate() & 0x1f;
if (ror_value == 0) {
mv(rd, rs);
return;
- } else if (ror_value < 0) {
- ror_value += 32;
}
srliw(scratch, rs, ror_value);
slliw(rd, rs, 32 - ror_value);
@@ -6780,7 +6778,7 @@ void MacroAssemblerRiscv64::Drol(Register rd, Register rs, const Operand& rt) {
sll(rd, rs, rt.rm());
or_(rd, scratch, rd);
} else {
- Dror(rd, rs, Operand(64 - (rt.immediate() % 64)));
+ Dror(rd, rs, Operand(64 - (rt.immediate() & 0x3f)));
}
}
@@ -6793,12 +6791,10 @@ void MacroAssemblerRiscv64::Dror(Register rd, Register rs, const Operand& rt) {
srl(rd, rs, rt.rm());
or_(rd, scratch, rd);
} else {
- int64_t dror_value = rt.immediate() % 64;
+ int64_t dror_value = rt.immediate() & 0x3f;
if (dror_value == 0) {
mv(rd, rs);
return;
- } else if (dror_value < 0) {
- dror_value += 64;
}
srli(scratch, rs, dror_value);
slli(rd, rs, 64 - dror_value);