Bug 891083 - Make the ImmWord version of x64's movq always use smaller immediate fields when possible; use movWithPatch when a patchable 64-bit immediate field is needed. Also, implement movq_i32r, which is useful for immediates in the range [INT32_MIN, 0). r=sstangl
authorDan Gohman <sunfish@google.com>
Mon, 08 Jul 2013 19:28:20 -0700
changeset 137697 3b34a02b5f46155f00562011e41029b46534b8eb
parent 137696 575d402f0dae033e552a799e92eddd6a95eef460
child 137698 628af50ed0585cc202eecdf3debf9a7399c806e7
push id30653
push usersunfish@google.com
push dateTue, 09 Jul 2013 02:28:58 +0000
treeherdermozilla-inbound@3b34a02b5f46 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs891083
milestone25.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 891083 - Make the ImmWord version of x64's movq always use smaller immediate fields when possible; use movWithPatch when a patchable 64-bit immediate field is needed. Also, implement movq_i32r, which is useful for immediates in the range [INT32_MIN, 0). r=sstangl
js/src/assembler/assembler/X86Assembler.h
js/src/ion/x64/Assembler-x64.h
js/src/ion/x64/MacroAssembler-x64.h
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -1670,20 +1670,28 @@ public:
     void movq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
     {
         spew("movq       $%d, %s0x%x(%s)",
              imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
         m_formatter.immediate32(imm);
     }
 
-    // Intentionally left undefined. If you need this operation, consider
-    // naming it movq_i32r_signExtended to highlight the fact the operand size
-    // is not 32; the 32-bit immediate is sign-extended.
-    void movq_i32r(int imm, RegisterID dst);
+    // Note that this instruction sign-extends its 32-bit immediate field to 64
+    // bits and loads the 64-bit value into a 64-bit register.
+    //
+    // Note also that this is similar to the movl_i32r instruction, except that
+    // movl_i32r *zero*-extends its 32-bit immediate, and it has smaller code
+    // size, so it's preferred for values which could use either.
+    void movq_i32r(int imm, RegisterID dst) {
+        spew("movq       $%d, %s",
+             imm, nameIReg(dst));
+        m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, dst);
+        m_formatter.immediate32(imm);
+    }
 
     void movq_i64r(int64_t imm, RegisterID dst)
     {
         spew("movabsq    $0x%llx, %s",
              (unsigned long long int)imm, nameIReg(8,dst));
         m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
         m_formatter.immediate64(imm);
     }
--- a/js/src/ion/x64/Assembler-x64.h
+++ b/js/src/ion/x64/Assembler-x64.h
@@ -357,22 +357,37 @@ class Assembler : public AssemblerX86Sha
     }
 
     void pop(const FloatRegister &src) {
         movsd(Operand(StackPointer, 0), src);
         addq(Imm32(sizeof(double)), StackPointer);
     }
 
     CodeOffsetLabel movWithPatch(const ImmWord &word, const Register &dest) {
-        movq(word, dest);
+        masm.movq_i64r(word.value, dest.code());
         return masm.currentOffset();
     }
 
+    // Load an ImmWord value into a register. Note that this instruction will
+    // attempt to optimize its immediate field size. When a full 64-bit
+    // immediate is needed for a relocation, use movWithPatch.
     void movq(ImmWord word, const Register &dest) {
-        masm.movq_i64r(word.value, dest.code());
+        // Load a 64-bit immediate into a register. If the value falls into
+        // certain ranges, we can use specialized instructions which have
+        // smaller encodings.
+        if (word.value <= UINT32_MAX) {
+            // movl has a 32-bit unsigned (effectively) immediate field.
+            masm.movl_i32r((uint32_t)word.value, dest.code());
+        } else if ((intptr_t)word.value >= INT32_MIN && (intptr_t)word.value <= INT32_MAX) {
+            // movq has a 32-bit signed immediate field.
+            masm.movq_i32r((int32_t)(intptr_t)word.value, dest.code());
+        } else {
+            // Otherwise use movabs.
+            masm.movq_i64r(word.value, dest.code());
+        }
     }
     void movq(ImmGCPtr ptr, const Register &dest) {
         masm.movq_i64r(ptr.value, dest.code());
         writeDataRelocation(ptr);
     }
     void movq(const Operand &src, const Register &dest) {
         switch (src.kind()) {
           case Operand::REG:
@@ -518,26 +533,17 @@ class Assembler : public AssemblerX86Sha
     void xorq(const Register &src, const Register &dest) {
         masm.xorq_rr(src.code(), dest.code());
     }
     void xorq(Imm32 imm, const Register &dest) {
         masm.xorq_ir(imm.value, dest.code());
     }
 
     void mov(ImmWord word, const Register &dest) {
-        // If the word value is in [0,UINT32_MAX], we can use the more compact
-        // movl instruction, which has a 32-bit immediate field which it
-        // zero-extends into the 64-bit register.
-        if (word.value <= UINT32_MAX) {
-            uint32_t value32 = static_cast<uint32_t>(word.value);
-            Imm32 imm32(static_cast<int32_t>(value32));
-            movl(imm32, dest);
-        } else {
-            movq(word, dest);
-        }
+        movq(word, dest);
     }
     void mov(const Imm32 &imm32, const Register &dest) {
         movl(imm32, dest);
     }
     void mov(const Operand &src, const Register &dest) {
         movq(src, dest);
     }
     void mov(const Register &src, const Operand &dest) {
--- a/js/src/ion/x64/MacroAssembler-x64.h
+++ b/js/src/ion/x64/MacroAssembler-x64.h
@@ -156,19 +156,22 @@ class MacroAssemblerX64 : public MacroAs
         } else {
             boxValue(type, reg, ScratchReg);
             movq(ScratchReg, Operand(dest));
         }
     }
     template <typename T>
     void storeValue(const Value &val, const T &dest) {
         jsval_layout jv = JSVAL_TO_IMPL(val);
-        movq(ImmWord(jv.asBits), ScratchReg);
-        if (val.isMarkable())
+        if (val.isMarkable()) {
+            movWithPatch(ImmWord(jv.asBits), ScratchReg);
             writeDataRelocation(val);
+        } else {
+            mov(ImmWord(jv.asBits), ScratchReg);
+        }
         movq(ScratchReg, Operand(dest));
     }
     void storeValue(ValueOperand val, BaseIndex dest) {
         storeValue(val, Operand(dest));
     }
     void loadValue(Operand src, ValueOperand val) {
         movq(src, val.valueReg());
     }
@@ -208,17 +211,17 @@ class MacroAssemblerX64 : public MacroAs
     }
     void Pop(const ValueOperand &val) {
         popValue(val);
         framePushed_ -= sizeof(Value);
     }
 
     void moveValue(const Value &val, const Register &dest) {
         jsval_layout jv = JSVAL_TO_IMPL(val);
-        movq(ImmWord(jv.asPtr), dest);
+        movWithPatch(ImmWord(jv.asPtr), dest);
         writeDataRelocation(val);
     }
     void moveValue(const Value &src, const ValueOperand &dest) {
         moveValue(src, dest.valueReg());
     }
     void moveValue(const ValueOperand &src, const ValueOperand &dest) {
         if (src.valueReg() != dest.valueReg())
             movq(src.valueReg(), dest.valueReg());