Bug 1510334 - Lower LMulI and fix register corruption. Fixes arguments/args2d.js. r=nbp
authorSean Stangl <sean.stangl@gmail.com>
Fri, 30 Nov 2018 09:28:00 +0200
changeset 505486 beea2dd156f7a7cb57acc5450e78b6abeda028e8
parent 505485 035d5b058729aed86f13d9309c657ffb94ba8fdb
child 505487 7a80928fff2952f4cc1839b6af341fde892d7464
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1510334
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1510334 - Lower LMulI and fix register corruption. Fixes arguments/args2d.js. r=nbp
js/src/jit/arm64/CodeGenerator-arm64.cpp
js/src/jit/arm64/LIR-arm64.h
js/src/jit/arm64/Lowering-arm64.cpp
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -291,60 +291,63 @@ void CodeGenerator::visitMulI(LMulI* ins
   const LAllocation* lhs = ins->getOperand(0);
   const LAllocation* rhs = ins->getOperand(1);
   const LDefinition* dest = ins->getDef(0);
   MMul* mul = ins->mir();
   MOZ_ASSERT_IF(mul->mode() == MMul::Integer,
                 !mul->canBeNegativeZero() && !mul->canOverflow());
 
   Register lhsreg = ToRegister(lhs);
+  const ARMRegister lhsreg32 = ARMRegister(lhsreg, 32);
+  Register destreg = ToRegister(dest);
+  const ARMRegister destreg32 = ARMRegister(destreg, 32);
 
   if (rhs->isConstant()) {
     // Bailout on -0.0.
     int32_t constant = ToInt32(rhs);
     if (mul->canBeNegativeZero() && constant <= 0) {
       Assembler::Condition bailoutCond =
           (constant == 0) ? Assembler::LessThan : Assembler::Equal;
       masm.Cmp(toWRegister(lhs), Operand(0));
       bailoutIf(bailoutCond, ins->snapshot());
     }
 
     switch (constant) {
       case -1:
-        masm.neg32(lhsreg);
-        break;
+        masm.Negs(destreg32, Operand(lhsreg32));
+        break;  // Go to overflow check.
       case 0:
-        masm.Mov(ARMRegister(lhsreg, 32), wzr);
-        return;  // escape overflow check;
+        masm.Mov(destreg32, wzr);
+        return;  // Avoid overflow check.
       case 1:
         // nop
-        return;  // escape overflow check;
+        return;  // Avoid overflow check.
       case 2:
-        masm.add32(lhsreg, lhsreg);
-        break;
+        masm.Adds(destreg32, lhsreg32, Operand(lhsreg32));
+        break;  // Go to overflow check.
       default:
         // Use shift if cannot overflow and constant is a power of 2
         if (!mul->canOverflow() && constant > 0) {
           int32_t shift = FloorLog2(constant);
           if ((1 << shift) == constant) {
-            masm.lshift32(Imm32(shift), lhsreg);
+            masm.Lsl(destreg32, lhsreg32, shift);
             return;
           }
         }
 
         // Otherwise, just multiply.
         Label bailout;
         Label* onZero = mul->canBeNegativeZero() ? &bailout : nullptr;
         Label* onOverflow = mul->canOverflow() ? &bailout : nullptr;
 
         vixl::UseScratchRegisterScope temps(&masm.asVIXL());
         const Register scratch = temps.AcquireW().asUnsized();
 
         masm.move32(Imm32(constant), scratch);
-        masm.mul32(lhsreg, scratch, ToRegister(dest), onOverflow, onZero);
+        masm.mul32(lhsreg, scratch, destreg, onOverflow, onZero);
         if (onZero || onOverflow) {
           bailoutFrom(&bailout, ins->snapshot());
         }
         return;  // escape overflow check;
     }
 
     // Overflow check.
     if (mul->canOverflow()) {
@@ -353,17 +356,17 @@ void CodeGenerator::visitMulI(LMulI* ins
   } else {
     Register rhsreg = ToRegister(rhs);
 
     Label bailout;
     // TODO: x64 (but not other platforms) have an OOL path for onZero.
     Label* onZero = mul->canBeNegativeZero() ? &bailout : nullptr;
     Label* onOverflow = mul->canOverflow() ? &bailout : nullptr;
 
-    masm.mul32(lhsreg, rhsreg, ToRegister(dest), onOverflow, onZero);
+    masm.mul32(lhsreg, rhsreg, destreg, onOverflow, onZero);
     if (onZero || onOverflow) {
       bailoutFrom(&bailout, ins->snapshot());
     }
   }
 }
 
 void CodeGenerator::visitDivI(LDivI* ins) {
   const Register lhs = ToRegister(ins->lhs());
--- a/js/src/jit/arm64/LIR-arm64.h
+++ b/js/src/jit/arm64/LIR-arm64.h
@@ -241,16 +241,18 @@ class LTableSwitchV : public LInstructio
   const LDefinition* tempFloat() { return getTemp(1); }
   const LDefinition* tempPointer() { return nullptr; }
 };
 
 class LMulI : public LBinaryMath<0> {
  public:
   LIR_HEADER(MulI);
 
+  LMulI() : LBinaryMath(classOpcode) {}
+
   MMul* mir() { return mir_->toMul(); }
 };
 
 class LUDiv : public LBinaryMath<0> {
  public:
   LIR_HEADER(UDiv);
 
   MDiv* mir() { return mir_->toDiv(); }
--- a/js/src/jit/arm64/Lowering-arm64.cpp
+++ b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -210,17 +210,21 @@ void LIRGeneratorARM64::lowerDivI(MDiv* 
   if (div->fallible()) {
     assignSnapshot(lir, Bailout_DoubleOutput);
   }
   define(lir, div);
 }
 
 void LIRGeneratorARM64::lowerMulI(MMul* mul, MDefinition* lhs,
                                   MDefinition* rhs) {
-  MOZ_CRASH("lowerMulI");
+  LMulI* lir = new(alloc()) LMulI;
+  if (mul->fallible()) {
+      assignSnapshot(lir, Bailout_DoubleOutput);
+  }
+  lowerForALU(lir, mul, lhs, rhs);
 }
 
 void LIRGeneratorARM64::lowerModI(MMod* mod) { MOZ_CRASH("lowerModI"); }
 
 void LIRGeneratorARM64::lowerDivI64(MDiv* div) { MOZ_CRASH("NYI"); }
 
 void LIRGeneratorARM64::lowerModI64(MMod* mod) { MOZ_CRASH("NYI"); }