Loading js/src/jit-test/tests/wasm/regress/bug1836708.js 0 → 100644 +19 −0 Original line number Diff line number Diff line // Testing i64.mul in wasm with a 2 ** n +- 1 value as operand, which may // be optimized in code generation. var mulImmOperands = []; for (let i = 0n; i < 64n; i++) { mulImmOperands.push(2n ** i - 1n); mulImmOperands.push(2n ** i + 1n); } for (const immVal of mulImmOperands) { const ins = wasmEvalText(`(module (func (export "mul_i64") (param i64) (result i64) local.get 0 i64.const ${immVal} i64.mul ))`); assertEq(ins.exports.mul_i64(42n), BigInt.asIntN(64, 42n * immVal)); } js/src/jit/loong64/CodeGenerator-loong64.cpp +21 −8 Original line number Diff line number Diff line Loading @@ -1072,6 +1072,7 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { const LInt64Allocation lhs = lir->getInt64Operand(LMulI64::Lhs); const LInt64Allocation rhs = lir->getInt64Operand(LMulI64::Rhs); const Register64 output = ToOutRegister64(lir); MOZ_ASSERT(ToRegister64(lhs) == output); if (IsConstant(rhs)) { int64_t constant = ToInt64(rhs); Loading @@ -1085,18 +1086,30 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { case 1: // nop return; case 2: masm.as_add_d(output.reg, ToRegister64(lhs).reg, ToRegister64(lhs).reg); return; default: if (constant > 0) { if (mozilla::IsPowerOfTwo(static_cast<uint32_t>(constant + 1))) { masm.move64(ToRegister64(lhs), output); masm.lshift64(Imm32(FloorLog2(constant + 1)), output); masm.sub64(ToRegister64(lhs), output); if (mozilla::IsPowerOfTwo(static_cast<uint64_t>(constant + 1))) { ScratchRegisterScope scratch(masm); masm.movePtr(ToRegister64(lhs).reg, scratch); masm.as_slli_d(output.reg, ToRegister64(lhs).reg, FloorLog2(constant + 1)); masm.sub64(scratch, output); return; } else if (mozilla::IsPowerOfTwo( static_cast<uint32_t>(constant - 1))) { masm.move64(ToRegister64(lhs), output); masm.lshift64(Imm32(FloorLog2(constant - 1u)), output); masm.add64(ToRegister64(lhs), output); static_cast<uint64_t>(constant - 1))) { int32_t shift = mozilla::FloorLog2(constant - 1); if (shift < 5) { masm.as_alsl_d(output.reg, ToRegister64(lhs).reg, ToRegister64(lhs).reg, shift - 1); } else { ScratchRegisterScope scratch(masm); masm.movePtr(ToRegister64(lhs).reg, scratch); masm.as_slli_d(output.reg, ToRegister64(lhs).reg, shift); masm.add64(scratch, output); } return; } // Use shift if constant is power of 2. Loading js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +14 −6 Original line number Diff line number Diff line Loading @@ -455,6 +455,7 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { const LInt64Allocation lhs = lir->getInt64Operand(LMulI64::Lhs); const LInt64Allocation rhs = lir->getInt64Operand(LMulI64::Rhs); const Register64 output = ToOutRegister64(lir); MOZ_ASSERT(ToRegister64(lhs) == output); if (IsConstant(rhs)) { int64_t constant = ToInt64(rhs); Loading @@ -468,18 +469,25 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { case 1: // nop return; case 2: masm.add64(ToRegister64(lhs), ToRegister64(lhs)); return; default: if (constant > 0) { if (mozilla::IsPowerOfTwo(static_cast<uint32_t>(constant + 1))) { masm.move64(ToRegister64(lhs), output); if (mozilla::IsPowerOfTwo(static_cast<uint64_t>(constant + 1))) { ScratchRegisterScope scratch(masm); Register64 scratch64(scratch); masm.move64(ToRegister64(lhs), scratch64); masm.lshift64(Imm32(FloorLog2(constant + 1)), output); masm.sub64(ToRegister64(lhs), output); masm.sub64(scratch64, output); return; } else if (mozilla::IsPowerOfTwo( static_cast<uint32_t>(constant - 1))) { masm.move64(ToRegister64(lhs), output); static_cast<uint64_t>(constant - 1))) { ScratchRegisterScope scratch(masm); Register64 scratch64(scratch); masm.move64(ToRegister64(lhs), scratch64); masm.lshift64(Imm32(FloorLog2(constant - 1u)), output); masm.add64(ToRegister64(lhs), output); masm.add64(scratch64, output); return; } // Use shift if constant is power of 2. Loading Loading
js/src/jit-test/tests/wasm/regress/bug1836708.js 0 → 100644 +19 −0 Original line number Diff line number Diff line // Testing i64.mul in wasm with a 2 ** n +- 1 value as operand, which may // be optimized in code generation. var mulImmOperands = []; for (let i = 0n; i < 64n; i++) { mulImmOperands.push(2n ** i - 1n); mulImmOperands.push(2n ** i + 1n); } for (const immVal of mulImmOperands) { const ins = wasmEvalText(`(module (func (export "mul_i64") (param i64) (result i64) local.get 0 i64.const ${immVal} i64.mul ))`); assertEq(ins.exports.mul_i64(42n), BigInt.asIntN(64, 42n * immVal)); }
js/src/jit/loong64/CodeGenerator-loong64.cpp +21 −8 Original line number Diff line number Diff line Loading @@ -1072,6 +1072,7 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { const LInt64Allocation lhs = lir->getInt64Operand(LMulI64::Lhs); const LInt64Allocation rhs = lir->getInt64Operand(LMulI64::Rhs); const Register64 output = ToOutRegister64(lir); MOZ_ASSERT(ToRegister64(lhs) == output); if (IsConstant(rhs)) { int64_t constant = ToInt64(rhs); Loading @@ -1085,18 +1086,30 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { case 1: // nop return; case 2: masm.as_add_d(output.reg, ToRegister64(lhs).reg, ToRegister64(lhs).reg); return; default: if (constant > 0) { if (mozilla::IsPowerOfTwo(static_cast<uint32_t>(constant + 1))) { masm.move64(ToRegister64(lhs), output); masm.lshift64(Imm32(FloorLog2(constant + 1)), output); masm.sub64(ToRegister64(lhs), output); if (mozilla::IsPowerOfTwo(static_cast<uint64_t>(constant + 1))) { ScratchRegisterScope scratch(masm); masm.movePtr(ToRegister64(lhs).reg, scratch); masm.as_slli_d(output.reg, ToRegister64(lhs).reg, FloorLog2(constant + 1)); masm.sub64(scratch, output); return; } else if (mozilla::IsPowerOfTwo( static_cast<uint32_t>(constant - 1))) { masm.move64(ToRegister64(lhs), output); masm.lshift64(Imm32(FloorLog2(constant - 1u)), output); masm.add64(ToRegister64(lhs), output); static_cast<uint64_t>(constant - 1))) { int32_t shift = mozilla::FloorLog2(constant - 1); if (shift < 5) { masm.as_alsl_d(output.reg, ToRegister64(lhs).reg, ToRegister64(lhs).reg, shift - 1); } else { ScratchRegisterScope scratch(masm); masm.movePtr(ToRegister64(lhs).reg, scratch); masm.as_slli_d(output.reg, ToRegister64(lhs).reg, shift); masm.add64(scratch, output); } return; } // Use shift if constant is power of 2. Loading
js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +14 −6 Original line number Diff line number Diff line Loading @@ -455,6 +455,7 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { const LInt64Allocation lhs = lir->getInt64Operand(LMulI64::Lhs); const LInt64Allocation rhs = lir->getInt64Operand(LMulI64::Rhs); const Register64 output = ToOutRegister64(lir); MOZ_ASSERT(ToRegister64(lhs) == output); if (IsConstant(rhs)) { int64_t constant = ToInt64(rhs); Loading @@ -468,18 +469,25 @@ void CodeGenerator::visitMulI64(LMulI64* lir) { case 1: // nop return; case 2: masm.add64(ToRegister64(lhs), ToRegister64(lhs)); return; default: if (constant > 0) { if (mozilla::IsPowerOfTwo(static_cast<uint32_t>(constant + 1))) { masm.move64(ToRegister64(lhs), output); if (mozilla::IsPowerOfTwo(static_cast<uint64_t>(constant + 1))) { ScratchRegisterScope scratch(masm); Register64 scratch64(scratch); masm.move64(ToRegister64(lhs), scratch64); masm.lshift64(Imm32(FloorLog2(constant + 1)), output); masm.sub64(ToRegister64(lhs), output); masm.sub64(scratch64, output); return; } else if (mozilla::IsPowerOfTwo( static_cast<uint32_t>(constant - 1))) { masm.move64(ToRegister64(lhs), output); static_cast<uint64_t>(constant - 1))) { ScratchRegisterScope scratch(masm); Register64 scratch64(scratch); masm.move64(ToRegister64(lhs), scratch64); masm.lshift64(Imm32(FloorLog2(constant - 1u)), output); masm.add64(ToRegister64(lhs), output); masm.add64(scratch64, output); return; } // Use shift if constant is power of 2. Loading