Bug 1316803 part 1 - fold constant rhs for add/sub/shift/rotate/bitwise-ops r=lth
☠☠ backed out by dffe47871714 ☠ ☠
authorDaniel Näslund <dannas@dannas.name>
Thu, 24 Nov 2016 18:39:35 +0100
changeset 325435 3bfbdec4ea08c9fb7fb0a4ee624c1607e85a4013
parent 325403 387b89eeed54d07238a2e0e878e44ca7cdbd26cb
child 325436 c65a9a96f48a5c3d7ac132df804cb829619a41b2
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewerslth
bugs1316803
milestone53.0a1
Bug 1316803 part 1 - fold constant rhs for add/sub/shift/rotate/bitwise-ops r=lth
js/src/jit-test/tests/wasm/integer.js
js/src/jit/MacroAssembler.h
js/src/jit/arm64/MacroAssembler-arm64-inl.h
js/src/wasm/WasmBaselineCompile.cpp
--- a/js/src/jit-test/tests/wasm/integer.js
+++ b/js/src/jit-test/tests/wasm/integer.js
@@ -202,16 +202,18 @@ assertEq(testTrunc(13.37), 1);
     testBinary64('shr_s', "0xff00ff0000000", 28, 0xff00ff);
     testBinary64('shr_u', "0x8ffff00ff0000000", 56, 0x8f);
     testBinary64('rotl', 40, 2, 160);
     testBinary64('rotr', 40, 2, 10);
     testBinary64('rotr', "0x1234567812345678", 4, "0x8123456781234567");
     testBinary64('rotl', "0x1234567812345678", 4, "0x2345678123456781");
     testBinary64('rotl', "0x1234567812345678", 60, "0x8123456781234567");
     testBinary64('rotr', "0x1234567812345678", 60, "0x2345678123456781");
+    testBinary64('rotl', "0x0000000000001000", 127, "0x0000000000000800");
+    testBinary64('rotr', "0x0000000000001000", 127, "0x0000000000002000");
     testBinary64('rotr', 40, 0, 40);
     testBinary64('rotl', 40, 0, 40);
     testBinary64('and', 42, 0, 0);
     testBinary64('and', "0x0000000012345678", "0xffff0000ffff0000", "0x0000000012340000");
 
     testComparison64('eq', 40, 40, 1);
     testComparison64('ne', 40, 40, 0);
     testComparison64('lt_s', 40, 40, 0);
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -761,17 +761,17 @@ class MacroAssembler : public MacroAssem
     inline void addPtr(ImmWord imm, Register dest) PER_ARCH;
     inline void addPtr(ImmPtr imm, Register dest);
     inline void addPtr(Imm32 imm, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
     inline void addPtr(Imm32 imm, const AbsoluteAddress& dest) DEFINED_ON(x86, x64);
     inline void addPtr(const Address& src, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
 
     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);
+    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;
 
     inline void addDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
     inline void addConstantDouble(double d, FloatRegister dest) DEFINED_ON(x86);
 
     inline void sub32(const Address& src, Register dest) PER_SHARED_ARCH;
@@ -780,17 +780,17 @@ class MacroAssembler : public MacroAssem
 
     inline void subPtr(Register src, Register dest) PER_ARCH;
     inline void subPtr(Register src, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
     inline void subPtr(Imm32 imm, Register dest) PER_ARCH;
     inline void subPtr(ImmWord imm, Register dest) DEFINED_ON(x64);
     inline void subPtr(const Address& addr, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
 
     inline void sub64(Register64 src, Register64 dest) PER_ARCH;
-    inline void sub64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64);
+    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;
 
     inline void subDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
 
     // On x86-shared, srcDest must be eax and edx will be clobbered.
     inline void mul32(Register rhs, Register srcDest) PER_SHARED_ARCH;
@@ -895,26 +895,26 @@ class MacroAssembler : public MacroAssem
     // Note: - on x86 and x64 the count register must be in CL.
     //       - on x64 the temp register should be InvalidReg.
 
     inline void rotateLeft(Imm32 count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateLeft(Register count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateLeft64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp)
-        DEFINED_ON(x86, x64, arm, mips32, mips64);
+        PER_ARCH;
     inline void rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
         PER_ARCH;
 
     inline void rotateRight(Imm32 count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateRight(Register count, Register input, Register dest) PER_SHARED_ARCH;
     inline void rotateRight64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateRight64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64);
     inline void rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp)
-        DEFINED_ON(x86, x64, arm, mips32, mips64);
+        PER_ARCH;
     inline void rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
         PER_ARCH;
 
     // ===============================================================
     // Bit counting functions
 
     // knownNotZero may be true only if the src is known not to be zero.
     inline void clz32(Register src, Register dest, bool knownNotZero) PER_SHARED_ARCH;
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -302,16 +302,22 @@ MacroAssembler::add64(Register64 src, Re
 
 void
 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));
+}
+
+void
 MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
 {
     fadd(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
 }
 
 void
 MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest)
 {
@@ -377,16 +383,22 @@ MacroAssembler::subPtr(const Address& ad
 
 void
 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)
 {
     fsub(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), ARMFPRegister(src, 64));
 }
 
 void
 MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest)
 {
@@ -721,21 +733,33 @@ MacroAssembler::rotateRight(Register cou
 
 void
 MacroAssembler::rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
 {
     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
 
 void
 MacroAssembler::clz32(Register src, Register dest, bool knownNotZero)
 {
     MOZ_CRASH("NYI: clz32");
 }
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1687,16 +1687,25 @@ class BaseCompiler
         Stk& v = stk_.back();
         if (v.kind() != Stk::ConstI32)
             return false;
         c = v.i32val();
         stk_.popBack();
         return true;
     }
 
+    MOZ_MUST_USE bool popConstI64(int64_t& c) {
+        Stk& v = stk_.back();
+        if (v.kind() != Stk::ConstI64)
+            return false;
+        c = v.i64val();
+        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
     // register set and will be heavily wanted by the register
     // allocator that uses takeFirst().
     //
     // Obvious options:
     //  - pick a register at the back of the register set
@@ -3969,64 +3978,82 @@ BaseCompiler::emitAddI32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitAddI64()
 {
-    // TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64(&r0, &r1);
-    masm.add64(r1, r0);
-    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, r0);
     freeF64(r1);
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitAddF32()
 {
-    // TODO / OPTIMIZE: Ditto check for constant here (Bug 1316803)
     RegF32 r0, r1;
     pop2xF32(&r0, &r1);
     masm.addFloat32(r1, r0);
     freeF32(r1);
     pushF32(r0);
 }
 
 void
 BaseCompiler::emitSubtractI32()
 {
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    masm.sub32(r1, r0);
-    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, r0);
-    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
 BaseCompiler::emitSubtractF32()
 {
     RegF32 r0, r1;
     pop2xF32(&r0, &r1);
     masm.subFloat32(r1, r0);
@@ -4386,71 +4413,113 @@ BaseCompiler::emitCopysignF64()
     freeI64(x1);
     freeF64(r1);
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitOrI32()
 {
-    RegI32 r0, r1;
-    pop2xI32(&r0, &r1);
-    masm.or32(r1, r0);
-    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, r0);
-    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, r0);
-    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, r0);
-    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, r0);
-    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, r0);
-    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
 BaseCompiler::emitShlI32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
@@ -4464,22 +4533,28 @@ BaseCompiler::emitShlI32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShlI64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.lshift64(lowPart(r1), r0);
-    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
 BaseCompiler::emitShrI32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
@@ -4493,22 +4568,28 @@ BaseCompiler::emitShrI32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrI64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rshift64Arithmetic(lowPart(r1), r0);
-    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
 BaseCompiler::emitShrU32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
@@ -4522,66 +4603,96 @@ BaseCompiler::emitShrU32()
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrU64()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rshift64(lowPart(r1), r0);
-    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()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForShiftOrRotate(&r0, &r1);
-    masm.rotateRight(r1, r0, r0);
-    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()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rotateRight64(lowPart(r1), r0, r0, maybeHighPart(r1));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.rotateRight64(Imm32(c & 63), r, r, InvalidReg);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.rotateRight64(lowPart(r1), r0, r0, maybeHighPart(r1));
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitRotlI32()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI32 r0, r1;
-    pop2xI32ForShiftOrRotate(&r0, &r1);
-    masm.rotateLeft(r1, r0, r0);
-    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()
 {
-    // TODO / OPTIMIZE: Constant rhs (Bug 1316803)
-    RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
-    freeI64(r1);
-    pushI64(r0);
+    int64_t c;
+    if (popConstI64(c)) {
+        RegI64 r = popI64();
+        masm.rotateLeft64(Imm32(c & 63), r, r, InvalidReg);
+        pushI64(r);
+    } else {
+        RegI64 r0, r1;
+        pop2xI64ForShiftOrRotate(&r0, &r1);
+        masm.rotateLeft64(lowPart(r1), r0, r0, maybeHighPart(r1));
+        freeI64(r1);
+        pushI64(r0);
+    }
 }
 
 void
 BaseCompiler::emitEqzI32()
 {
     if (sniffConditionalControlEqz(ValType::I32))
         return;