1316803 Wasm baseline: fold constant rhs into integer operations

1316803 part 1 - fold constant rhs for add/sub/shift/rotate/bitwise-ops.

1316803 part 2 - optimize division for constant rhs.
This commit is contained in:
win7-7 2025-12-29 00:27:18 +02:00 committed by wuggy
commit d100b1fbca
3 changed files with 455 additions and 257 deletions

View file

@ -771,8 +771,8 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void add64(Register64 src, Register64 dest) PER_ARCH;
inline void add64(Imm32 imm, Register64 dest) PER_ARCH;
inline void add64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
inline void add64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
inline void add64(Imm64 imm, Register64 dest) PER_ARCH;
inline void add64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
inline void addFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
@ -790,8 +790,8 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void subPtr(const Address& addr, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64, loongarch64);
inline void sub64(Register64 src, Register64 dest) PER_ARCH;
inline void sub64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
inline void sub64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
inline void sub64(Imm64 imm, Register64 dest) PER_ARCH;
inline void sub64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
inline void subFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
@ -905,7 +905,7 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64, loongarch64);
inline void rotateLeft64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64, loongarch64);
inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp)
DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
PER_ARCH;
inline void rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
PER_ARCH;
@ -914,7 +914,7 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void rotateRight64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64, loongarch64);
inline void rotateRight64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64, loongarch64);
inline void rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp)
DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
PER_ARCH;
inline void rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
PER_ARCH;

View file

@ -305,6 +305,24 @@ MacroAssembler::add64(Imm32 imm, Register64 dest)
Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
}
void
MacroAssembler::add64(Imm64 imm, Register64 dest)
{
Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
}
CodeOffset
MacroAssembler::add32ToPtrWithPatch(Register src, Register dest)
{
MOZ_CRASH("NYI - add32ToPtrWithPatch");
}
void
MacroAssembler::patchAdd32ToPtr(CodeOffset offset, Imm32 imm)
{
MOZ_CRASH("NYI - patchAdd32ToPtr");
}
void
MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
{
@ -380,6 +398,12 @@ MacroAssembler::sub64(Register64 src, Register64 dest)
MOZ_CRASH("NYI: sub64");
}
void
MacroAssembler::sub64(Imm64 imm, Register64 dest)
{
MOZ_CRASH("NYI: sub64");
}
void
MacroAssembler::subDouble(FloatRegister src, FloatRegister dest)
{
@ -724,12 +748,25 @@ MacroAssembler::rotateLeft64(Register count, Register64 input, Register64 dest,
MOZ_CRASH("NYI: rotateLeft64");
}
void
MacroAssembler::rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp)
{
MOZ_CRASH("NYI: rotateLeft64");
}
void
MacroAssembler::rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
{
MOZ_CRASH("NYI: rotateRight64");
}
void
MacroAssembler::rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp)
{
MOZ_CRASH("NYI: rotateRight64");
}
// ===============================================================
// Bit counting functions

View file

@ -126,6 +126,7 @@
using mozilla::DebugOnly;
using mozilla::FloatingPoint;
using mozilla::FloorLog2;
using mozilla::IsPowerOfTwo;
using mozilla::SpecificNaN;
@ -1699,6 +1700,45 @@ class BaseCompiler
return true;
}
[[nodiscard]] bool popConstI64(int64_t& c) {
Stk& v = stk_.back();
if (v.kind() != Stk::ConstI64)
return false;
c = v.i64val();
stk_.popBack();
return true;
}
[[nodiscard]] bool popConstPositivePowerOfTwoI32(int32_t& c,
uint_fast8_t& power,
int32_t cutoff)
{
Stk& v = stk_.back();
if (v.kind() != Stk::ConstI32)
return false;
c = v.i32val();
if (c <= cutoff || !IsPowerOfTwo(static_cast<uint32_t>(c)))
return false;
power = FloorLog2(c);
stk_.popBack();
return true;
}
[[nodiscard]] bool popConstPositivePowerOfTwoI64(int64_t& c,
uint_fast8_t& power,
int64_t cutoff)
{
Stk& v = stk_.back();
if (v.kind() != Stk::ConstI64)
return false;
c = v.i64val();
if (c <= cutoff || !IsPowerOfTwo(static_cast<uint64_t>(c)))
return false;
power = FloorLog2(c);
stk_.popBack();
return true;
}
// TODO / OPTIMIZE (Bug 1316818): At the moment we use ReturnReg
// for JoinReg. It is possible other choices would lead to better
// register allocation, as ReturnReg is often first in the
@ -2695,6 +2735,14 @@ class BaseCompiler
#endif
}
bool rotate64NeedsTemp() const {
#if defined(JS_CODEGEN_X86)
return true;
#else
return false;
#endif
}
void maskShiftCount32(RegI32 r) {
#if defined(JS_CODEGEN_ARM)
masm.and32(Imm32(31), r.reg);
@ -4214,18 +4262,23 @@ BaseCompiler::emitAddI32()
void
BaseCompiler::emitAddI64()
{
// TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.add64(r1.reg, r0.reg);
freeI64(r1);
pushI64(r0);
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.add64(Imm64(c), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.add64(r1, r0);
freeI64(r1);
pushI64(r0);
}
}
void
BaseCompiler::emitAddF64()
{
// TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
RegF64 r0, r1;
pop2xF64(&r0, &r1);
masm.addDouble(r1.reg, r0.reg);
@ -4236,7 +4289,6 @@ BaseCompiler::emitAddF64()
void
BaseCompiler::emitAddF32()
{
// TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
RegF32 r0, r1;
pop2xF32(&r0, &r1);
masm.addFloat32(r1.reg, r0.reg);
@ -4247,21 +4299,35 @@ BaseCompiler::emitAddF32()
void
BaseCompiler::emitSubtractI32()
{
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.sub32(r1.reg, r0.reg);
freeI32(r1);
pushI32(r0);
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.sub32(Imm32(c), r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.sub32(r1, r0);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitSubtractI64()
{
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.sub64(r1.reg, r0.reg);
freeI64(r1);
pushI64(r0);
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.sub64(Imm64(c), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.sub64(r1, r0);
freeI64(r1);
pushI64(r0);
}
}
void
@ -4388,116 +4454,116 @@ BaseCompiler::emitMultiplyF64()
void
BaseCompiler::emitQuotientI32()
{
// TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two (Bug 1316803)
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
int32_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI32(c, power, 0)) {
if (power != 0) {
RegI32 r = popI32();
Label positive;
masm.branchTest32(Assembler::NotSigned, r, r, &positive);
masm.add32(Imm32(c-1), r);
masm.bind(&positive);
Label done;
checkDivideByZeroI32(r1, r0, &done);
checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
masm.quotient32(r1.reg, r0.reg, IsUnsigned(false));
masm.bind(&done);
masm.rshift32Arithmetic(Imm32(power & 31), r);
pushI32(r);
}
} else {
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
freeI32(r1);
pushI32(r0);
Label done;
checkDivideByZeroI32(r1, r0, &done);
checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
masm.quotient32(r1, r0, IsUnsigned(false));
masm.bind(&done);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitQuotientU32()
{
int32_t c;
if (popConstI32(c)) {
uint32_t uc = uint32_t(c);
RegI32 r = popI32();
int32_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI32(c, power, 0)) {
if (power != 0) {
RegI32 r = popI32();
masm.rshift32(Imm32(power & 31), r);
pushI32(r);
}
} else {
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
if (uc != 0 && IsPowerOfTwo(uc)) {
uint32_t shift = 0;
while ((uint32_t(1) << shift) != uc)
shift++;
masm.rshift32(Imm32(shift), r.reg);
pushI32(r);
return;
Label done;
checkDivideByZeroI32(r1, r0, &done);
masm.quotient32(r1, r0, IsUnsigned(true));
masm.bind(&done);
freeI32(r1);
pushI32(r0);
}
RegI32 rhs = needI32();
masm.move32(Imm32(c), rhs.reg);
Label done;
checkDivideByZeroI32(rhs, r, &done);
masm.quotient32(rhs.reg, r.reg, IsUnsigned(true));
masm.bind(&done);
freeI32(rhs);
pushI32(r);
return;
}
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
Label done;
checkDivideByZeroI32(r1, r0, &done);
masm.quotient32(r1.reg, r0.reg, IsUnsigned(true));
masm.bind(&done);
freeI32(r1);
pushI32(r0);
}
void
BaseCompiler::emitRemainderI32()
{
// TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two (Bug 1316803)
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
int32_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI32(c, power, 1)) {
RegI32 r = popI32();
RegI32 temp = needI32();
moveI32(r, temp);
Label done;
checkDivideByZeroI32(r1, r0, &done);
checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
masm.remainder32(r1.reg, r0.reg, IsUnsigned(false));
masm.bind(&done);
Label positive;
masm.branchTest32(Assembler::NotSigned, temp, temp, &positive);
masm.add32(Imm32(c-1), temp);
masm.bind(&positive);
freeI32(r1);
pushI32(r0);
masm.rshift32Arithmetic(Imm32(power & 31), temp);
masm.lshift32(Imm32(power & 31), temp);
masm.sub32(temp, r);
freeI32(temp);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
Label done;
checkDivideByZeroI32(r1, r0, &done);
checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
masm.remainder32(r1, r0, IsUnsigned(false));
masm.bind(&done);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitRemainderU32()
{
int32_t c;
if (popConstI32(c)) {
uint32_t uc = uint32_t(c);
RegI32 r = popI32();
int32_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI32(c, power, 1)) {
RegI32 r = popI32();
masm.and32(Imm32(c-1), r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
if (uc != 0 && IsPowerOfTwo(uc)) {
masm.and32(Imm32(int32_t(uc - 1)), r.reg);
pushI32(r);
return;
Label done;
checkDivideByZeroI32(r1, r0, &done);
masm.remainder32(r1, r0, IsUnsigned(true));
masm.bind(&done);
freeI32(r1);
pushI32(r0);
}
RegI32 rhs = needI32();
masm.move32(Imm32(c), rhs.reg);
Label done;
checkDivideByZeroI32(rhs, r, &done);
masm.remainder32(rhs.reg, r.reg, IsUnsigned(true));
masm.bind(&done);
freeI32(rhs);
pushI32(r);
return;
}
RegI32 r0, r1;
pop2xI32ForIntMulDiv(&r0, &r1);
Label done;
checkDivideByZeroI32(r1, r0, &done);
masm.remainder32(r1.reg, r0.reg, IsUnsigned(true));
masm.bind(&done);
freeI32(r1);
pushI32(r0);
}
#ifndef INT_DIV_I64_CALLOUT
@ -4505,11 +4571,27 @@ void
BaseCompiler::emitQuotientI64()
{
# ifdef JS_PUNBOX64
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
quotientI64(r1, r0, IsUnsigned(false));
freeI64(r1);
pushI64(r0);
int64_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI64(c, power, 0)) {
if (power != 0) {
RegI64 r = popI64();
Label positive;
masm.branchTest64(Assembler::NotSigned, r, r, Register::Invalid(),
&positive);
masm.add64(Imm32(c-1), r);
masm.bind(&positive);
masm.rshift64Arithmetic(Imm32(power & 63), r);
pushI64(r);
}
} else {
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
quotientI64(r1, r0, IsUnsigned(false));
freeI64(r1);
pushI64(r0);
}
# else
MOZ_CRASH("BaseCompiler platform hook: emitQuotientI64");
# endif
@ -4519,11 +4601,21 @@ void
BaseCompiler::emitQuotientU64()
{
# ifdef JS_PUNBOX64
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
quotientI64(r1, r0, IsUnsigned(true));
freeI64(r1);
pushI64(r0);
int64_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI64(c, power, 0)) {
if (power != 0) {
RegI64 r = popI64();
masm.rshift64(Imm32(power & 63), r);
pushI64(r);
}
} else {
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
quotientI64(r1, r0, IsUnsigned(true));
freeI64(r1);
pushI64(r0);
}
# else
MOZ_CRASH("BaseCompiler platform hook: emitQuotientU64");
# endif
@ -4533,11 +4625,32 @@ void
BaseCompiler::emitRemainderI64()
{
# ifdef JS_PUNBOX64
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
remainderI64(r1, r0, IsUnsigned(false));
freeI64(r1);
pushI64(r0);
int64_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI64(c, power, 1)) {
RegI64 r = popI64();
RegI64 temp = needI64();
moveI64(r, temp);
Label positive;
masm.branchTest64(Assembler::NotSigned, temp, temp,
Register::Invalid(), &positive);
masm.add64(Imm64(c-1), temp);
masm.bind(&positive);
masm.rshift64Arithmetic(Imm32(power & 63), temp);
masm.lshift64(Imm32(power & 63), temp);
masm.sub64(temp, r);
freeI64(temp);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
remainderI64(r1, r0, IsUnsigned(false));
freeI64(r1);
pushI64(r0);
}
# else
MOZ_CRASH("BaseCompiler platform hook: emitRemainderI64");
# endif
@ -4547,11 +4660,19 @@ void
BaseCompiler::emitRemainderU64()
{
# ifdef JS_PUNBOX64
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
remainderI64(r1, r0, IsUnsigned(true));
freeI64(r1);
pushI64(r0);
int64_t c;
uint_fast8_t power;
if (popConstPositivePowerOfTwoI64(c, power, 1)) {
RegI64 r = popI64();
masm.and64(Imm64(c-1), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForIntDiv(&r0, &r1);
remainderI64(r1, r0, IsUnsigned(true));
freeI64(r1);
pushI64(r0);
}
# else
MOZ_CRASH("BaseCompiler platform hook: emitRemainderU64");
# endif
@ -4722,61 +4843,103 @@ BaseCompiler::emitCopysignF64()
void
BaseCompiler::emitOrI32()
{
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.or32(r1.reg, r0.reg);
freeI32(r1);
pushI32(r0);
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.or32(Imm32(c), r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.or32(r1, r0);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitOrI64()
{
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.or64(r1.reg, r0.reg);
freeI64(r1);
pushI64(r0);
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.or64(Imm64(c), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.or64(r1, r0);
freeI64(r1);
pushI64(r0);
}
}
void
BaseCompiler::emitAndI32()
{
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.and32(r1.reg, r0.reg);
freeI32(r1);
pushI32(r0);
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.and32(Imm32(c), r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.and32(r1, r0);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitAndI64()
{
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.and64(r1.reg, r0.reg);
freeI64(r1);
pushI64(r0);
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.and64(Imm64(c), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.and64(r1, r0);
freeI64(r1);
pushI64(r0);
}
}
void
BaseCompiler::emitXorI32()
{
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.xor32(r1.reg, r0.reg);
freeI32(r1);
pushI32(r0);
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.xor32(Imm32(c), r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32(&r0, &r1);
masm.xor32(r1, r0);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitXorI64()
{
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.xor64(r1.reg, r0.reg);
freeI64(r1);
pushI64(r0);
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.xor64(Imm64(c), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64(&r0, &r1);
masm.xor64(r1, r0);
freeI64(r1);
pushI64(r0);
}
}
void
@ -4800,18 +4963,18 @@ BaseCompiler::emitShlI32()
void
BaseCompiler::emitShlI64()
{
int32_t c;
if (popConstI32(c)) {
RegI64 r = popI64();
masm.lshift64(Imm32(c & 63), r.reg);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.lshift64(lowPart(r1), r0.reg);
freeI64(r1);
pushI64(r0);
}
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.lshift64(Imm32(c & 63), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.lshift64(lowPart(r1), r0);
freeI64(r1);
pushI64(r0);
}
}
void
@ -4835,18 +4998,18 @@ BaseCompiler::emitShrI32()
void
BaseCompiler::emitShrI64()
{
int32_t c;
if (popConstI32(c)) {
RegI64 r = popI64();
masm.rshift64Arithmetic(Imm32(c & 63), r.reg);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rshift64Arithmetic(lowPart(r1), r0.reg);
freeI64(r1);
pushI64(r0);
}
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.rshift64Arithmetic(Imm32(c & 63), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rshift64Arithmetic(lowPart(r1), r0);
freeI64(r1);
pushI64(r0);
}
}
void
@ -4870,98 +5033,96 @@ BaseCompiler::emitShrU32()
void
BaseCompiler::emitShrU64()
{
int32_t c;
if (popConstI32(c)) {
RegI64 r = popI64();
masm.rshift64(Imm32(c & 63), r.reg);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rshift64(lowPart(r1), r0.reg);
freeI64(r1);
pushI64(r0);
}
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
masm.rshift64(Imm32(c & 63), r);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rshift64(lowPart(r1), r0);
freeI64(r1);
pushI64(r0);
}
}
void
BaseCompiler::emitRotrI32()
{
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.rotateRight(Imm32(c & 31), r.reg, r.reg);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32ForShiftOrRotate(&r0, &r1);
masm.rotateRight(r1.reg, r0.reg, r0.reg);
freeI32(r1);
pushI32(r0);
}
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.rotateRight(Imm32(c & 31), r, r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32ForShiftOrRotate(&r0, &r1);
masm.rotateRight(r1, r0, r0);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitRotrI64()
{
int32_t c;
if (popConstI32(c)) {
RegI64 r = popI64();
#ifdef JS_PUNBOX64
masm.rotateRight64(Imm32(c & 63), r.reg, r.reg);
#else
RegI32 temp = needI32();
masm.rotateRight64(Imm32(c & 63), r.reg, r.reg, temp.reg);
freeI32(temp);
#endif
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rotateRight64(lowPart(r1), r0.reg, r0.reg, maybeHighPart(r1));
freeI64(r1);
pushI64(r0);
}
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
RegI32 temp;
if (rotate64NeedsTemp())
temp = needI32();
masm.rotateRight64(Imm32(c & 63), r, r, temp);
if (temp != Register::Invalid())
freeI32(temp);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rotateRight64(lowPart(r1), r0, r0, maybeHighPart(r1));
freeI64(r1);
pushI64(r0);
}
}
void
BaseCompiler::emitRotlI32()
{
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.rotateLeft(Imm32(c & 31), r.reg, r.reg);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32ForShiftOrRotate(&r0, &r1);
masm.rotateLeft(r1.reg, r0.reg, r0.reg);
freeI32(r1);
pushI32(r0);
}
int32_t c;
if (popConstI32(c)) {
RegI32 r = popI32();
masm.rotateLeft(Imm32(c & 31), r, r);
pushI32(r);
} else {
RegI32 r0, r1;
pop2xI32ForShiftOrRotate(&r0, &r1);
masm.rotateLeft(r1, r0, r0);
freeI32(r1);
pushI32(r0);
}
}
void
BaseCompiler::emitRotlI64()
{
int32_t c;
if (popConstI32(c)) {
RegI64 r = popI64();
#ifdef JS_PUNBOX64
masm.rotateLeft64(Imm32(c & 63), r.reg, r.reg);
#else
RegI32 temp = needI32();
masm.rotateLeft64(Imm32(c & 63), r.reg, r.reg, temp.reg);
freeI32(temp);
#endif
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rotateLeft64(lowPart(r1), r0.reg, r0.reg, maybeHighPart(r1));
freeI64(r1);
pushI64(r0);
}
int64_t c;
if (popConstI64(c)) {
RegI64 r = popI64();
RegI32 temp;
if (rotate64NeedsTemp())
temp = needI32();
masm.rotateLeft64(Imm32(c & 63), r, r, temp);
if (temp != Register::Invalid())
freeI32(temp);
pushI64(r);
} else {
RegI64 r0, r1;
pop2xI64ForShiftOrRotate(&r0, &r1);
masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
freeI64(r1);
pushI64(r0);
}
}
void