From 96127b68e5b371ee5248bafc888ab661b22cefb1 Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Tue, 9 Feb 2010 13:10:32 +0000 Subject: [PATCH] Ported ia32 optimization of revision 3487 to x64. Review URL: http://codereview.chromium.org/597005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3821 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/x64/assembler-x64.cc | 32 ++++++++++++++ src/x64/assembler-x64.h | 12 ++--- src/x64/codegen-x64.cc | 52 +++++++++++++++++++--- src/x64/codegen-x64.h | 3 +- src/x64/disasm-x64.cc | 95 +++++++++++++++++++++++----------------- 5 files changed, 139 insertions(+), 55 deletions(-) diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 1b6874e9a..8078a94c3 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -2508,6 +2508,38 @@ void Assembler::divsd(XMMRegister dst, XMMRegister src) { } +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() }; diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 64fbd8887..c455a2680 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -1122,6 +1122,10 @@ class Assembler : public Malloced { 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 @@ class Assembler : public Malloced { 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]; } diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index ef9e493ba..90a92cc8e 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -1221,7 +1221,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { // 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 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { } Load(left); Load(right); - Comparison(cc, strict, destination()); + Comparison(node, cc, strict, destination()); } @@ -4867,7 +4867,8 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) { } -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 @@ void CodeGenerator::Comparison(Condition cc, 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 @@ void CodeGenerator::Comparison(Condition cc, // Implement comparison against a constant Smi, inlining the case // where both sides are Smis. left_side.ToRegister(); + Register left_reg = left_side.reg(); + Handle 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,12 +4939,48 @@ void CodeGenerator::Comparison(Condition cc, // 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 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); Result result = frame_->CallStub(&stub, &left_side, &right_side); diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 8fbbe5a65..d82682fbf 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -484,7 +484,8 @@ class CodeGenerator: public AstVisitor { Result* right, OverwriteMode overwrite_mode); - void Comparison(Condition cc, + void Comparison(AstNode* node, + Condition cc, bool strict, ControlDestination* destination); diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index ce3aae8a2..547daeeb1 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -993,7 +993,60 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { 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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &rm); @@ -1007,8 +1060,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { 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 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) { } 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, ®op, &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, ®op, &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, ®op, &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(); } -- 2.34.1