Change the code for materializing double constants on ia32.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 9 Feb 2011 12:39:15 +0000 (12:39 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 9 Feb 2011 12:39:15 +0000 (12:39 +0000)
Instead of using the stack, use a temporary integer register
and avoid memory access.

Review URL: http://codereview.chromium.org/6452002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6696 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/assembler-ia32.cc
src/ia32/assembler-ia32.h
src/ia32/disasm-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
test/cctest/test-disasm-ia32.cc

index 552d7b5eeae2d7351672e6d9e041e0d6efdbab96..e4d09f2e49513c640e026c5325cdd440cef5b1bc 100644 (file)
@@ -2559,6 +2559,19 @@ void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
 }
 
 
+void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
+  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0x3A);
+  EMIT(0x22);
+  emit_sse_operand(dst, src);
+  EMIT(offset);
+}
+
+
 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
   Register ireg = { reg.code() };
   emit_operand(ireg, adr);
index 20446b0085e4098c5f133b45c1f0ccf72909038b..2e84d6f0d79f9b7c1490dd301dd6e8bb2fdbfe5a 100644 (file)
@@ -928,6 +928,7 @@ class Assembler : public Malloced {
   void psrlq(XMMRegister dst, XMMRegister src);
   void pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle);
   void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
+  void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
 
   // Parallel XMM operations.
   void movntdqa(XMMRegister src, const Operand& dst);
index 4028a93421e98b8b505eaeab21425cb22473a993..e0cbe35c0d2087b62cb48e2753c1098f489912dc 100644 (file)
@@ -1115,10 +1115,20 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
               get_modrm(*data, &mod, &regop, &rm);
               int8_t imm8 = static_cast<int8_t>(data[1]);
               AppendToBuffer("pextrd %s,%s,%d",
-                             NameOfXMMRegister(regop),
+                             NameOfCPURegister(regop),
                              NameOfXMMRegister(rm),
                              static_cast<int>(imm8));
               data += 2;
+            } else if (*data == 0x22) {
+              data++;
+              int mod, regop, rm;
+              get_modrm(*data, &mod, &regop, &rm);
+              int8_t imm8 = static_cast<int8_t>(data[1]);
+              AppendToBuffer("pinsrd %s,%s,%d",
+                             NameOfXMMRegister(regop),
+                             NameOfCPURegister(rm),
+                             static_cast<int>(imm8));
+              data += 2;
             } else {
               UnimplementedInstruction();
             }
index 528c4089a599e1abdd5754e67b5df7fe7af87b01..9dde986cd20f78d4a76d191adc8692cd379973bc 100644 (file)
@@ -945,19 +945,31 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
   if (BitCast<uint64_t, double>(v) == 0) {
     __ xorpd(res, res);
   } else {
-    int32_t v_int32 = static_cast<int32_t>(v);
-    if (static_cast<double>(v_int32) == v) {
-      __ push_imm32(v_int32);
-      __ cvtsi2sd(res, Operand(esp, 0));
-      __ add(Operand(esp), Immediate(kPointerSize));
+    Register temp = ToRegister(instr->TempAt(0));
+    uint64_t int_val = BitCast<uint64_t, double>(v);
+    int32_t lower = static_cast<int32_t>(int_val);
+    int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
+    if (CpuFeatures::IsSupported(SSE4_1)) {
+      CpuFeatures::Scope scope(SSE4_1);
+      if (lower != 0) {
+        __ Set(temp, Immediate(lower));
+        __ movd(res, Operand(temp));
+        __ Set(temp, Immediate(upper));
+        __ pinsrd(res, Operand(temp), 1);
+      } else {
+        __ xorpd(res, res);
+        __ Set(temp, Immediate(upper));
+        __ pinsrd(res, Operand(temp), 1);
+      }
     } else {
-      uint64_t int_val = BitCast<uint64_t, double>(v);
-      int32_t lower = static_cast<int32_t>(int_val);
-      int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
-      __ push_imm32(upper);
-      __ push_imm32(lower);
-      __ movdbl(res, Operand(esp, 0));
-      __ add(Operand(esp), Immediate(2 * kPointerSize));
+      __ Set(temp, Immediate(upper));
+      __ movd(res, Operand(temp));
+      __ psllq(res, 32);
+      if (lower != 0) {
+        __ Set(temp, Immediate(lower));
+        __ movd(xmm0, Operand(temp));
+        __ por(res, xmm0);
+      }
     }
   }
 }
index 02129efffc83588292968b6acf8111976be7c4e5..793a3f45ee224b063af93e32828a1b4a71607d39 100644 (file)
@@ -1676,7 +1676,11 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   if (r.IsInteger32()) {
     return DefineAsRegister(new LConstantI);
   } else if (r.IsDouble()) {
-    return DefineAsRegister(new LConstantD);
+    double value = instr->DoubleValue();
+    LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
+        ? TempRegister()
+        : NULL;
+    return DefineAsRegister(new LConstantD(temp));
   } else if (r.IsTagged()) {
     return DefineAsRegister(new LConstantT);
   } else {
index c0474d997cdd8bb4d14599e9eb0f5154a36f31a0..56d031cd0b468726f4870f08a181f2c3801ec02c 100644 (file)
@@ -941,8 +941,12 @@ class LConstantI: public LTemplateInstruction<1, 0, 0> {
 };
 
 
-class LConstantD: public LTemplateInstruction<1, 0, 0> {
+class LConstantD: public LTemplateInstruction<1, 0, 1> {
  public:
+  explicit LConstantD(LOperand* temp) {
+    temps_[0] = temp;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
   DECLARE_HYDROGEN_ACCESSOR(Constant)
 
index 30d708e4086dbae82f0c10eba4859980f0224c30..c995aa8ed04fc8663e1ad0c072214ac285377dea 100644 (file)
@@ -446,6 +446,14 @@ TEST(DisasmIa320) {
     }
   }
 
+  {
+    if (CpuFeatures::IsSupported(SSE4_1)) {
+      CpuFeatures::Scope scope(SSE4_1);
+      __ pextrd(Operand(eax), xmm0, 1);
+      __ pinsrd(xmm1, Operand(eax), 0);
+    }
+  }
+
   __ ret(0);
 
   CodeDesc desc;