From 49ffb141d9841a6ee5035a153be15c923b0c8beb Mon Sep 17 00:00:00 2001 From: "dcarney@chromium.org" Date: Tue, 30 Sep 2014 10:24:11 +0000 Subject: [PATCH] [turbofan] IA: Uint32ToFloat64 supports mem operand. BUG= R=dcarney@chromium.org Review URL: https://codereview.chromium.org/583963002 Patch from Jing Bao . git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24318 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/ia32/code-generator-ia32.cc | 3 +- .../instruction-selector-ia32-unittest.cc | 12 +++++++ .../ia32/instruction-selector-ia32.cc | 4 +-- src/compiler/x64/code-generator-x64.cc | 7 ++-- .../x64/instruction-selector-x64-unittest.cc | 9 ++++++ src/compiler/x64/instruction-selector-x64.cc | 4 +-- src/ia32/macro-assembler-ia32.cc | 6 ++-- src/ia32/macro-assembler-ia32.h | 5 ++- src/x64/assembler-x64.cc | 10 ++++++ test/cctest/compiler/test-run-machops.cc | 32 +++++++++++++++++++ test/cctest/test-disasm-x64.cc | 2 ++ 11 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc index d9f8833ff7..a99beed904 100644 --- a/src/compiler/ia32/code-generator-ia32.cc +++ b/src/compiler/ia32/code-generator-ia32.cc @@ -370,8 +370,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0)); break; case kSSEUint32ToFloat64: - // TODO(turbofan): IA32 SSE LoadUint32() should take an operand. - __ LoadUint32(i.OutputDoubleRegister(), i.InputRegister(0)); + __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0)); break; case kIA32Movsxbl: __ movsx_b(i.OutputRegister(), i.MemoryOperand()); diff --git a/src/compiler/ia32/instruction-selector-ia32-unittest.cc b/src/compiler/ia32/instruction-selector-ia32-unittest.cc index 89d150f26e..650bb8c07f 100644 --- a/src/compiler/ia32/instruction-selector-ia32-unittest.cc +++ b/src/compiler/ia32/instruction-selector-ia32-unittest.cc @@ -133,6 +133,18 @@ TEST_F(InstructionSelectorTest, BetterLeftOperandTestMulBinop) { } +// ----------------------------------------------------------------------------- +// Conversions. + +TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) { + StreamBuilder m(this, kMachFloat64, kMachUint32); + m.Return(m.ChangeUint32ToFloat64(m.Parameter(0))); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode()); +} + + // ----------------------------------------------------------------------------- // Loads and stores diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc index 70bee35a2f..0f5c7b29c0 100644 --- a/src/compiler/ia32/instruction-selector-ia32.cc +++ b/src/compiler/ia32/instruction-selector-ia32.cc @@ -459,9 +459,7 @@ void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { IA32OperandGenerator g(this); - // TODO(turbofan): IA32 SSE LoadUint32() should take an operand. - Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), - g.UseRegister(node->InputAt(0))); + Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); } diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index 7bf26a4c91..2c8783322e 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -424,8 +424,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { } break; case kSSEUint32ToFloat64: - // TODO(turbofan): X64 SSE cvtqsi2sd should support operands. - __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0)); + if (instr->InputAt(0)->IsRegister()) { + __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0)); + } else { + __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputOperand(0)); + } break; case kX64Movsxbl: __ movsxbl(i.OutputRegister(), i.MemoryOperand()); diff --git a/src/compiler/x64/instruction-selector-x64-unittest.cc b/src/compiler/x64/instruction-selector-x64-unittest.cc index cc2fedb3fc..431ae435d3 100644 --- a/src/compiler/x64/instruction-selector-x64-unittest.cc +++ b/src/compiler/x64/instruction-selector-x64-unittest.cc @@ -33,6 +33,15 @@ TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) { } +TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) { + StreamBuilder m(this, kMachFloat64, kMachUint32); + m.Return(m.ChangeUint32ToFloat64(m.Parameter(0))); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode()); +} + + TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) { StreamBuilder m(this, kMachUint64, kMachUint32); m.Return(m.ChangeUint32ToUint64(m.Parameter(0))); diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index ab159a2bbc..322955e7b6 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -600,9 +600,7 @@ void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { X64OperandGenerator g(this); - // TODO(turbofan): X64 SSE cvtqsi2sd should support operands. - Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), - g.UseRegister(node->InputAt(0))); + Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); } diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index e95ee39cea..43043e5b27 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -345,12 +345,10 @@ void MacroAssembler::TruncateHeapNumberToI(Register result_reg, } -void MacroAssembler::LoadUint32(XMMRegister dst, - Register src) { +void MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) { Label done; cmp(src, Immediate(0)); - ExternalReference uint32_bias = - ExternalReference::address_of_uint32_bias(); + ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias(); Cvtsi2sd(dst, src); j(not_sign, &done, Label::kNear); addsd(dst, Operand::StaticVariable(uint32_bias)); diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 81347e58f2..b11145db0f 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -486,7 +486,10 @@ class MacroAssembler: public Assembler { j(not_carry, is_smi); } - void LoadUint32(XMMRegister dst, Register src); + void LoadUint32(XMMRegister dst, Register src) { + LoadUint32(dst, Operand(src)); + } + void LoadUint32(XMMRegister dst, const Operand& src); // Jump the register contains a smi. inline void JumpIfSmi(Register value, diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index ce68524524..a9fb834394 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -2683,6 +2683,16 @@ void Assembler::cvtlsi2ss(XMMRegister dst, Register src) { } +void Assembler::cvtqsi2sd(XMMRegister dst, const Operand& src) { + EnsureSpace ensure_space(this); + emit(0xF2); + emit_rex_64(dst, src); + emit(0x0F); + emit(0x2A); + emit_sse_operand(dst, src); +} + + void Assembler::cvtqsi2sd(XMMRegister dst, Register src) { EnsureSpace ensure_space(this); emit(0xF2); diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc index 5606126e06..cdfb7ecdf9 100644 --- a/test/cctest/compiler/test-run-machops.cc +++ b/test/cctest/compiler/test-run-machops.cc @@ -3102,6 +3102,38 @@ TEST(RunChangeUint32ToFloat64_B) { } +TEST(RunChangeUint32ToFloat64_spilled) { + RawMachineAssemblerTester m; + const int kNumInputs = 32; + int32_t magic = 0x786234; + uint32_t input[kNumInputs]; + double result[kNumInputs]; + Node* input_node[kNumInputs]; + + for (int i = 0; i < kNumInputs; i++) { + input_node[i] = + m.Load(kMachUint32, m.PointerConstant(&input), m.Int32Constant(i * 4)); + } + + for (int i = 0; i < kNumInputs; i++) { + m.Store(kMachFloat64, m.PointerConstant(&result), m.Int32Constant(i * 8), + m.ChangeUint32ToFloat64(input_node[i])); + } + + m.Return(m.Int32Constant(magic)); + + for (int i = 0; i < kNumInputs; i++) { + input[i] = 100 + i; + } + + CHECK_EQ(magic, m.Call()); + + for (int i = 0; i < kNumInputs; i++) { + CHECK_EQ(result[i], static_cast(100 + i)); + } +} + + TEST(RunChangeFloat64ToInt32_A) { RawMachineAssemblerTester m; int32_t magic = 0x786234; diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc index d238410fa4..480c91f536 100644 --- a/test/cctest/test-disasm-x64.cc +++ b/test/cctest/test-disasm-x64.cc @@ -380,6 +380,8 @@ TEST(DisasmX64) { __ cvttsd2si(rdx, xmm1); __ cvttsd2siq(rdx, xmm1); __ cvttsd2siq(rdx, Operand(rbx, rcx, times_4, 10000)); + __ cvtqsi2sd(xmm1, Operand(rbx, rcx, times_4, 10000)); + __ cvtqsi2sd(xmm1, rdx); __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000)); __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1); // 128 bit move instructions.