Revision: 3821
Author: [email protected]
Date: Tue Feb  9 05:10:32 2010
Log: Ported ia32 optimization of revision 3487 to x64.

Review URL: http://codereview.chromium.org/597005
http://code.google.com/p/v8/source/detail?r=3821

Modified:
 /branches/bleeding_edge/src/x64/assembler-x64.cc
 /branches/bleeding_edge/src/x64/assembler-x64.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/codegen-x64.h
 /branches/bleeding_edge/src/x64/disasm-x64.cc

=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Thu Feb 4 13:32:02 2010 +++ /branches/bleeding_edge/src/x64/assembler-x64.cc Tue Feb 9 05:10:32 2010
@@ -2508,6 +2508,38 @@
 }


+void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0f);
+  emit(0x57);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::comisd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0f);
+  emit(0x2f);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0f);
+  emit(0x2e);
+  emit_sse_operand(dst, src);
+}
+

 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
   Register ireg = { reg.code() };
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h     Thu Feb  4 13:32:02 2010
+++ /branches/bleeding_edge/src/x64/assembler-x64.h     Tue Feb  9 05:10:32 2010
@@ -1122,6 +1122,10 @@
   void mulsd(XMMRegister dst, XMMRegister src);
   void divsd(XMMRegister dst, XMMRegister src);

+  void xorpd(XMMRegister dst, XMMRegister src);
+
+  void comisd(XMMRegister dst, XMMRegister src);
+  void ucomisd(XMMRegister dst, XMMRegister src);

   void emit_sse_operand(XMMRegister dst, XMMRegister src);
   void emit_sse_operand(XMMRegister reg, const Operand& adr);
@@ -1168,14 +1172,6 @@
   static const int kMaximalBufferSize = 512*MB;
   static const int kMinimalBufferSize = 4*KB;

- protected:
-  // void movsd(XMMRegister dst, const Operand& src);
-  // void movsd(const Operand& dst, XMMRegister src);
-
-  // void emit_sse_operand(XMMRegister reg, const Operand& adr);
-  // void emit_sse_operand(XMMRegister dst, XMMRegister src);
-
-
  private:
   byte* addr_at(int pos)  { return buffer_ + pos; }
   byte byte_at(int pos)  { return buffer_[pos]; }
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Mon Feb  8 05:44:49 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Tue Feb  9 05:10:32 2010
@@ -1221,7 +1221,7 @@
     // Compare and branch to the body if true or the next test if
     // false.  Prefer the next test as a fall through.
     ControlDestination dest(clause->body_target(), &next_test, false);
-    Comparison(equal, true, &dest);
+    Comparison(node, equal, true, &dest);

     // If the comparison fell through to the true target, jump to the
     // actual body.
@@ -3585,7 +3585,7 @@
   }
   Load(left);
   Load(right);
-  Comparison(cc, strict, destination());
+  Comparison(node, cc, strict, destination());
 }


@@ -4867,7 +4867,8 @@
 }


-void CodeGenerator::Comparison(Condition cc,
+void CodeGenerator::Comparison(AstNode* node,
+                               Condition cc,
                                bool strict,
                                ControlDestination* dest) {
   // Strict only makes sense for equality comparisons.
@@ -4914,7 +4915,8 @@
         default:
           UNREACHABLE();
       }
-    } else {  // Only one side is a constant Smi.
+    } else {
+      // Only one side is a constant Smi.
       // If left side is a constant Smi, reverse the operands.
// Since one side is a constant Smi, conversion order does not matter.
       if (left_side_constant_smi) {
@@ -4928,6 +4930,8 @@
       // Implement comparison against a constant Smi, inlining the case
       // where both sides are Smis.
       left_side.ToRegister();
+      Register left_reg = left_side.reg();
+      Handle<Object> right_val = right_side.handle();

       // Here we split control flow to the stub call and inlined cases
       // before finally splitting it to the control destination.  We use
@@ -4935,11 +4939,47 @@
       // the first split.  We manually handle the off-frame references
       // by reconstituting them on the non-fall-through path.
       JumpTarget is_smi;
-      Register left_reg = left_side.reg();
-      Handle<Object> right_val = right_side.handle();

       Condition left_is_smi = masm_->CheckSmi(left_side.reg());
       is_smi.Branch(left_is_smi);
+
+      bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
+          && node->AsCompareOperation()->is_for_loop_condition();
+      if (!is_for_loop_compare && right_val->IsSmi()) {
+        // Right side is a constant smi and left side has been checked
+        // not to be a smi.
+        JumpTarget not_number;
+        __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
+               Factory::heap_number_map());
+        not_number.Branch(not_equal, &left_side);
+        __ movsd(xmm1,
+                 FieldOperand(left_reg, HeapNumber::kValueOffset));
+        int value = Smi::cast(*right_val)->value();
+        if (value == 0) {
+          __ xorpd(xmm0, xmm0);
+        } else {
+          Result temp = allocator()->Allocate();
+          __ movl(temp.reg(), Immediate(value));
+          __ cvtlsi2sd(xmm0, temp.reg());
+          temp.Unuse();
+        }
+        __ ucomisd(xmm1, xmm0);
+        // Jump to builtin for NaN.
+        not_number.Branch(parity_even, &left_side);
+        left_side.Unuse();
+        Condition double_cc = cc;
+        switch (cc) {
+          case less:          double_cc = below;       break;
+          case equal:         double_cc = equal;       break;
+          case less_equal:    double_cc = below_equal; break;
+          case greater:       double_cc = above;       break;
+          case greater_equal: double_cc = above_equal; break;
+          default: UNREACHABLE();
+        }
+        dest->true_target()->Branch(double_cc);
+        dest->false_target()->Jump();
+        not_number.Bind(&left_side);
+      }

       // Setup and call the compare stub.
       CompareStub stub(cc, strict);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h       Thu Feb  4 07:21:05 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h       Tue Feb  9 05:10:32 2010
@@ -484,7 +484,8 @@
                                   Result* right,
                                   OverwriteMode overwrite_mode);

-  void Comparison(Condition cc,
+  void Comparison(AstNode* node,
+                  Condition cc,
                   bool strict,
                   ControlDestination* destination);

=======================================
--- /branches/bleeding_edge/src/x64/disasm-x64.cc       Mon Jan 25 00:55:08 2010
+++ /branches/bleeding_edge/src/x64/disasm-x64.cc       Tue Feb  9 05:10:32 2010
@@ -993,7 +993,60 @@
   byte* current = data + 2;
   // At return, "current" points to the start of the next instruction.
   const char* mnemonic = TwoByteMnemonic(opcode);
-  if (opcode == 0x1F) {
+  if (operand_size_ == 0x66) {
+    // 0x66 0x0F prefix.
+    int mod, regop, rm;
+    get_modrm(*current, &mod, &regop, &rm);
+    const char* mnemonic = "?";
+    if (opcode == 0x57) {
+      mnemonic = "xorpd";
+    } else if (opcode == 0x2E) {
+      mnemonic = "comisd";
+    } else if (opcode == 0x2F) {
+      mnemonic = "ucomisd";
+    } else {
+      UnimplementedInstruction();
+    }
+    AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+    current += PrintRightXMMOperand(current);
+  } else if (group_1_prefix_ == 0xF2) {
+    // Beginning of instructions with prefix 0xF2.
+
+    if (opcode == 0x11 || opcode == 0x10) {
+ // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
+      AppendToBuffer("movsd ");
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      if (opcode == 0x11) {
+        current += PrintRightOperand(current);
+        AppendToBuffer(",%s", NameOfXMMRegister(regop));
+      } else {
+        AppendToBuffer("%s,", NameOfXMMRegister(regop));
+        current += PrintRightOperand(current);
+      }
+    } else if (opcode == 0x2A) {
+      // CVTSI2SD: integer to XMM double conversion.
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+      current += PrintRightOperand(current);
+    } else if ((opcode & 0xF8) == 0x58) {
+ // XMM arithmetic. Mnemonic was retrieved at the start of this function.
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+      current += PrintRightXMMOperand(current);
+    } else {
+      UnimplementedInstruction();
+    }
+  } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) {
+    // Instruction with prefix 0xF3.
+
+    // CVTTSS2SI: Convert scalar single-precision FP to dword integer.
+    // Assert that mod is not 3, so source is memory, not an XMM register.
+    ASSERT_NE(0xC0, *current & 0xC0);
+    current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
+  } else if (opcode == 0x1F) {
     // NOP
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
@@ -1007,8 +1060,7 @@
       current += 4;
     }  // else no immediate displacement.
     AppendToBuffer("nop");
-
-  } else  if (opcode == 0xA2 || opcode == 0x31) {
+  } else if (opcode == 0xA2 || opcode == 0x31) {
     // RDTSC or CPUID
     AppendToBuffer("%s", mnemonic);

@@ -1043,43 +1095,6 @@
     } else {
       AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
     }
-  } else if (group_1_prefix_ == 0xF2) {
-    // Beginning of instructions with prefix 0xF2.
-
-    if (opcode == 0x11 || opcode == 0x10) {
- // MOVSD: Move scalar double-precision fp to/from/between XMM registers.
-      AppendToBuffer("movsd ");
-      int mod, regop, rm;
-      get_modrm(*current, &mod, &regop, &rm);
-      if (opcode == 0x11) {
-        current += PrintRightOperand(current);
-        AppendToBuffer(",%s", NameOfXMMRegister(regop));
-      } else {
-        AppendToBuffer("%s,", NameOfXMMRegister(regop));
-        current += PrintRightOperand(current);
-      }
-    } else if (opcode == 0x2A) {
-      // CVTSI2SD: integer to XMM double conversion.
-      int mod, regop, rm;
-      get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
-      current += PrintRightOperand(current);
-    } else if ((opcode & 0xF8) == 0x58) {
- // XMM arithmetic. Mnemonic was retrieved at the start of this function.
-      int mod, regop, rm;
-      get_modrm(*current, &mod, &regop, &rm);
-      AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
-      current += PrintRightXMMOperand(current);
-    } else {
-      UnimplementedInstruction();
-    }
-  } else if (opcode == 0x2C && group_1_prefix_ == 0xF3) {
-    // Instruction with prefix 0xF3.
-
-    // CVTTSS2SI: Convert scalar single-precision FP to dword integer.
-    // Assert that mod is not 3, so source is memory, not an XMM register.
-    ASSERT_NE(0xC0, *current & 0xC0);
-    current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
   } else {
     UnimplementedInstruction();
   }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to