Commit 60d1225b authored by Zhao Jiazhong's avatar Zhao Jiazhong
Browse files

Bug 1836708 - [loong64][mips64] Fix register conflict in MulI64. r=jandem, a=dsmith

parent d0189a6d
Loading
Loading
Loading
Loading
+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));
}
+21 −8
Original line number Diff line number Diff line
@@ -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);
@@ -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.
+14 −6
Original line number Diff line number Diff line
@@ -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);
@@ -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.