Commit 0138b265 authored by alph's avatar alph Committed by Commit bot

[x64] Emit vcvttsd2si[q] when AVX is enabled.

BUG=v8:4406
LOG=N

Review URL: https://codereview.chromium.org/1406353003

Cr-Commit-Position: refs/heads/master@{#31348}
parent 106aecf2
......@@ -643,7 +643,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
auto result = i.OutputRegister();
auto input = i.InputDoubleRegister(0);
auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input);
__ cvttsd2siq(result, input);
__ Cvttsd2siq(result, input);
__ cmpq(result, Immediate(1));
__ j(overflow, ool->entry());
__ bind(ool->exit());
......@@ -913,16 +913,16 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
case kSSEFloat64ToInt32:
if (instr->InputAt(0)->IsDoubleRegister()) {
__ cvttsd2si(i.OutputRegister(), i.InputDoubleRegister(0));
__ Cvttsd2si(i.OutputRegister(), i.InputDoubleRegister(0));
} else {
__ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
__ Cvttsd2si(i.OutputRegister(), i.InputOperand(0));
}
break;
case kSSEFloat64ToUint32: {
if (instr->InputAt(0)->IsDoubleRegister()) {
__ cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
__ Cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
} else {
__ cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
__ Cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
}
__ AssertZeroExtended(i.OutputRegister());
break;
......
......@@ -3013,6 +3013,7 @@ void Assembler::psrld(XMMRegister reg, byte imm8) {
void Assembler::cvttss2si(Register dst, const Operand& src) {
DCHECK(!IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit(0xF3);
emit_optional_rex_32(dst, src);
......@@ -3023,6 +3024,7 @@ void Assembler::cvttss2si(Register dst, const Operand& src) {
void Assembler::cvttss2si(Register dst, XMMRegister src) {
DCHECK(!IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit(0xF3);
emit_optional_rex_32(dst, src);
......@@ -3033,6 +3035,7 @@ void Assembler::cvttss2si(Register dst, XMMRegister src) {
void Assembler::cvttsd2si(Register dst, const Operand& src) {
DCHECK(!IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit(0xF2);
emit_optional_rex_32(dst, src);
......@@ -3043,6 +3046,7 @@ void Assembler::cvttsd2si(Register dst, const Operand& src) {
void Assembler::cvttsd2si(Register dst, XMMRegister src) {
DCHECK(!IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit(0xF2);
emit_optional_rex_32(dst, src);
......@@ -3053,6 +3057,7 @@ void Assembler::cvttsd2si(Register dst, XMMRegister src) {
void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
DCHECK(!IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit(0xF2);
emit_rex_64(dst, src);
......@@ -3063,6 +3068,7 @@ void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
void Assembler::cvttsd2siq(Register dst, const Operand& src) {
DCHECK(!IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit(0xF2);
emit_rex_64(dst, src);
......@@ -3551,45 +3557,28 @@ void Assembler::vmovq(Register dst, XMMRegister src) {
void Assembler::vmovapd(XMMRegister dst, XMMRegister src) {
DCHECK(IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit_vex_prefix(dst, xmm0, src, kLIG, k66, k0F, kWIG);
emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kWIG);
emit(0x28);
emit_sse_operand(dst, src);
}
void Assembler::vucomisd(XMMRegister dst, XMMRegister src) {
DCHECK(IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit_vex_prefix(dst, xmm0, src, kLIG, k66, k0F, kWIG);
emit(0x2e);
emit_sse_operand(dst, src);
}
void Assembler::vucomisd(XMMRegister dst, const Operand& src) {
DCHECK(IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit_vex_prefix(dst, xmm0, src, kLIG, k66, k0F, kWIG);
emit(0x2e);
emit_sse_operand(dst, src);
}
void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
XMMRegister src2) {
XMMRegister src2, SIMDPrefix pp, LeadingOpcode m, VexW w) {
DCHECK(IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit_vex_prefix(dst, src1, src2, kLIG, kF2, k0F, kWIG);
emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
emit(op);
emit_sse_operand(dst, src2);
}
void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
const Operand& src2) {
const Operand& src2, SIMDPrefix pp, LeadingOpcode m,
VexW w) {
DCHECK(IsEnabled(AVX));
EnsureSpace ensure_space(this);
emit_vex_prefix(dst, src1, src2, kLIG, kF2, k0F, kWIG);
emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
emit(op);
emit_sse_operand(dst, src2);
}
......
......@@ -576,6 +576,11 @@ class Assembler : public AssemblerBase {
static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
static const byte kJzShortOpcode = kJccShortPrefix | zero;
// VEX prefix encodings.
enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 };
enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 };
enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 };
enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 };
// ---------------------------------------------------------------------------
// Code generation
......@@ -1322,15 +1327,44 @@ class Assembler : public AssemblerBase {
}
void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
XMMRegister isrc2 = {src2.code()};
vsd(0x2a, dst, src1, isrc2);
vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW0);
}
void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
vsd(0x2a, dst, src1, src2);
vsd(0x2a, dst, src1, src2, kF2, k0F, kW0);
}
void vcvttsd2si(Register dst, XMMRegister src) {
XMMRegister idst = {dst.code()};
vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
}
void vcvttsd2si(Register dst, const Operand& src) {
XMMRegister idst = {dst.code()};
vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
}
void vcvttsd2siq(Register dst, XMMRegister src) {
XMMRegister idst = {dst.code()};
vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
}
void vcvttsd2siq(Register dst, const Operand& src) {
XMMRegister idst = {dst.code()};
vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
}
void vucomisd(XMMRegister dst, XMMRegister src) {
vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
}
void vucomisd(XMMRegister dst, const Operand& src) {
vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
}
void vucomisd(XMMRegister dst, XMMRegister src);
void vucomisd(XMMRegister dst, const Operand& src);
void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2) {
vsd(op, dst, src1, src2, kF2, k0F, kWIG);
}
void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2) {
vsd(op, dst, src1, src2, kF2, k0F, kWIG);
}
void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2,
SIMDPrefix pp, LeadingOpcode m, VexW w);
void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2,
SIMDPrefix pp, LeadingOpcode m, VexW w);
void vaddss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
vss(0x58, dst, src1, src2);
......@@ -1773,11 +1807,6 @@ class Assembler : public AssemblerBase {
}
// Emit vex prefix
enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 };
enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 };
enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 };
enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 };
void emit_vex2_byte0() { emit(0xc5); }
inline void emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
SIMDPrefix pp);
......
......@@ -200,7 +200,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ jmp(&check_negative);
__ bind(&process_64_bits);
__ cvttsd2siq(result_reg, xmm0);
__ Cvttsd2siq(result_reg, xmm0);
__ jmp(&done, Label::kNear);
// If the double was negative, negate the integer result.
......@@ -324,7 +324,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ jmp(&int_exponent);
__ bind(&try_arithmetic_simplification);
__ cvttsd2si(exponent, double_exponent);
__ Cvttsd2si(exponent, double_exponent);
// Skip to runtime if possibly NaN (indicated by the indefinite integer).
__ cmpl(exponent, Immediate(0x1));
__ j(overflow, &call_runtime);
......
......@@ -1007,6 +1007,11 @@ int DisassemblerX64::AVXInstruction(byte* data) {
NameOfXMMRegister(vvvv));
current += PrintRightOperand(current);
break;
case 0x2c:
AppendToBuffer("vcvttsd2si%s %s,", vex_w() ? "q" : "",
NameOfCPURegister(regop));
current += PrintRightXMMOperand(current);
break;
case 0x58:
AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
NameOfXMMRegister(vvvv));
......
......@@ -3609,7 +3609,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero);
}
__ roundsd(xmm_scratch, input_reg, kRoundDown);
__ cvttsd2si(output_reg, xmm_scratch);
__ Cvttsd2si(output_reg, xmm_scratch);
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
} else {
......@@ -3633,7 +3633,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
}
// Use truncating instruction (OK because input is positive).
__ cvttsd2si(output_reg, input_reg);
__ Cvttsd2si(output_reg, input_reg);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
......@@ -3642,7 +3642,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
// Non-zero negative reaches here.
__ bind(&negative_sign);
// Truncate, then compare and compensate.
__ cvttsd2si(output_reg, input_reg);
__ Cvttsd2si(output_reg, input_reg);
__ Cvtlsi2sd(xmm_scratch, output_reg);
__ ucomisd(input_reg, xmm_scratch);
__ j(equal, &done, Label::kNear);
......@@ -3671,7 +3671,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
__ addsd(xmm_scratch, input_reg);
__ cvttsd2si(output_reg, xmm_scratch);
__ Cvttsd2si(output_reg, xmm_scratch);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
......@@ -3687,7 +3687,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// compare and compensate.
__ Movapd(input_temp, input_reg); // Do not alter input_reg.
__ subsd(input_temp, xmm_scratch);
__ cvttsd2si(output_reg, input_temp);
__ Cvttsd2si(output_reg, input_temp);
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmpl(output_reg, Immediate(0x1));
DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
......@@ -4994,7 +4994,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
__ Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ cvttsd2si(input_reg, xmm0);
__ Cvttsd2si(input_reg, xmm0);
__ Cvtlsi2sd(scratch, input_reg);
__ ucomisd(xmm0, scratch);
DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
......
......@@ -811,6 +811,46 @@ void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
}
void MacroAssembler::Cvttsd2si(Register dst, XMMRegister src) {
if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(this, AVX);
vcvttsd2si(dst, src);
} else {
cvttsd2si(dst, src);
}
}
void MacroAssembler::Cvttsd2si(Register dst, const Operand& src) {
if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(this, AVX);
vcvttsd2si(dst, src);
} else {
cvttsd2si(dst, src);
}
}
void MacroAssembler::Cvttsd2siq(Register dst, XMMRegister src) {
if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(this, AVX);
vcvttsd2siq(dst, src);
} else {
cvttsd2siq(dst, src);
}
}
void MacroAssembler::Cvttsd2siq(Register dst, const Operand& src) {
if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(this, AVX);
vcvttsd2siq(dst, src);
} else {
cvttsd2siq(dst, src);
}
}
void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
DCHECK(!r.IsDouble());
if (r.IsInteger8()) {
......@@ -3286,7 +3326,7 @@ void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
Register input_reg) {
Label done;
Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
cvttsd2siq(result_reg, xmm0);
Cvttsd2siq(result_reg, xmm0);
cmpq(result_reg, Immediate(1));
j(no_overflow, &done, Label::kNear);
......@@ -3309,7 +3349,7 @@ void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
void MacroAssembler::TruncateDoubleToI(Register result_reg,
XMMRegister input_reg) {
Label done;
cvttsd2siq(result_reg, input_reg);
Cvttsd2siq(result_reg, input_reg);
cmpq(result_reg, Immediate(1));
j(no_overflow, &done, Label::kNear);
......@@ -3329,7 +3369,7 @@ void MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,
MinusZeroMode minus_zero_mode,
Label* lost_precision, Label* is_nan,
Label* minus_zero, Label::Distance dst) {
cvttsd2si(result_reg, input_reg);
Cvttsd2si(result_reg, input_reg);
Cvtlsi2sd(xmm0, result_reg);
ucomisd(xmm0, input_reg);
j(not_equal, lost_precision, dst);
......
......@@ -812,6 +812,11 @@ class MacroAssembler: public Assembler {
void Cvtlsi2sd(XMMRegister dst, Register src);
void Cvtlsi2sd(XMMRegister dst, const Operand& src);
void Cvttsd2si(Register dst, XMMRegister src);
void Cvttsd2si(Register dst, const Operand& src);
void Cvttsd2siq(Register dst, XMMRegister src);
void Cvttsd2siq(Register dst, const Operand& src);
// Move if the registers are not identical.
void Move(Register target, Register source);
......
......@@ -1351,15 +1351,42 @@ TEST(AssemblerX64AVX_sd) {
CpuFeatureScope avx_scope(&assm, AVX);
Label exit;
// arguments in xmm0, xmm1 and xmm2
__ subq(rsp, Immediate(kDoubleSize * 2)); // For memory operand
__ movl(rax, Immediate(0));
__ vmaxsd(xmm4, xmm0, xmm1);
__ subq(rsp, Immediate(kDoubleSize * 2)); // For memory operand
__ vmovsd(Operand(rsp, kDoubleSize), xmm4);
__ vmovsd(xmm5, Operand(rsp, kDoubleSize));
__ vmovsd(xmm6, xmm5);
__ vmovapd(xmm3, xmm6);
// Test vcvttsd2si
__ movl(rax, Immediate(10));
__ movl(rdx, Immediate(123));
__ vcvtlsi2sd(xmm6, xmm6, rdx);
__ vcvttsd2si(rcx, xmm6);
__ cmpl(rcx, rdx);
__ j(not_equal, &exit);
__ xorl(rcx, rcx);
__ vmovsd(Operand(rsp, 0), xmm6);
__ vcvttsd2si(rcx, Operand(rsp, 0));
__ cmpl(rcx, rdx);
__ j(not_equal, &exit);
// Test vcvttsd2siq
__ movl(rax, Immediate(11));
__ movq(rdx, V8_INT64_C(0x426D1A94A2000000)); // 1.0e12
__ vmovq(xmm6, rdx);
__ vcvttsd2siq(rcx, xmm6);
__ movq(rdx, V8_INT64_C(1000000000000));
__ cmpq(rcx, rdx);
__ j(not_equal, &exit);
__ xorq(rcx, rcx);
__ vmovsd(Operand(rsp, 0), xmm6);
__ vcvttsd2siq(rcx, Operand(rsp, 0));
__ cmpq(rcx, rdx);
__ j(not_equal, &exit);
__ movl(rdx, Immediate(6));
__ vcvtlsi2sd(xmm6, xmm6, rdx);
__ movl(Operand(rsp, 0), Immediate(5));
......@@ -1373,7 +1400,6 @@ TEST(AssemblerX64AVX_sd) {
__ movq(Operand(rsp, 0), rdx);
__ vmovq(xmm6, Operand(rsp, 0));
__ vmulsd(xmm1, xmm1, xmm6);
__ addq(rsp, Immediate(kDoubleSize * 2));
__ vucomisd(xmm3, xmm1);
__ j(parity_even, &exit);
......@@ -1414,6 +1440,7 @@ TEST(AssemblerX64AVX_sd) {
// result in eax
__ bind(&exit);
__ addq(rsp, Immediate(kDoubleSize * 2));
__ ret(0);
}
......
......@@ -537,8 +537,13 @@ TEST(DisasmX64) {
__ vmaxsd(xmm9, xmm1, Operand(rbx, rcx, times_1, 10000));
__ vucomisd(xmm9, xmm1);
__ vucomisd(xmm8, Operand(rbx, rdx, times_2, 10981));
__ vcvtlsi2sd(xmm5, xmm9, rcx);
__ vcvtlsi2sd(xmm9, xmm3, Operand(rbx, r9, times_4, 10000));
__ vcvttsd2si(r9, xmm6);
__ vcvttsd2si(rax, Operand(rbx, r9, times_4, 10000));
__ vcvttsd2siq(rdi, xmm9);
__ vcvttsd2siq(r8, Operand(r9, rbx, times_4, 10000));
__ vandps(xmm0, xmm9, xmm2);
__ vandps(xmm9, xmm1, Operand(rbx, rcx, times_4, 10000));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment