From ce8a22a86fb1a9ef24e1f1c46e296a5e7fa03871 Mon Sep 17 00:00:00 2001 From: alph Date: Thu, 22 Oct 2015 23:10:20 -0700 Subject: [PATCH] [x64] Make MathMinMax use AVX instructions when available. BUG=v8:4406 LOG=N Review URL: https://codereview.chromium.org/1421733003 Cr-Commit-Position: refs/heads/master@{#31488} --- src/crankshaft/x64/lithium-codegen-x64.cc | 31 +++++++++++++---------- src/x64/assembler-x64.h | 1 + src/x64/disasm-x64.cc | 5 ++++ src/x64/macro-assembler-x64.cc | 20 +++++++++++++++ src/x64/macro-assembler-x64.h | 2 ++ test/cctest/test-assembler-x64.cc | 19 ++++++++++++++ test/cctest/test-disasm-x64.cc | 2 ++ 7 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/crankshaft/x64/lithium-codegen-x64.cc b/src/crankshaft/x64/lithium-codegen-x64.cc index 144889ef08..da86d31712 100644 --- a/src/crankshaft/x64/lithium-codegen-x64.cc +++ b/src/crankshaft/x64/lithium-codegen-x64.cc @@ -1964,33 +1964,38 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { __ bind(&return_left); } else { DCHECK(instr->hydrogen()->representation().IsDouble()); - Label check_nan_left, check_zero, return_left, return_right; + Label not_nan, distinct, return_left, return_right; Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; XMMRegister left_reg = ToDoubleRegister(left); XMMRegister right_reg = ToDoubleRegister(right); __ Ucomisd(left_reg, right_reg); - __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. - __ j(equal, &check_zero, Label::kNear); // left == right. - __ j(condition, &return_left, Label::kNear); - __ jmp(&return_right, Label::kNear); + __ j(parity_odd, ¬_nan, Label::kNear); // Both are not NaN. - __ bind(&check_zero); + // One of the numbers is NaN. Find which one and return it. + __ Ucomisd(left_reg, left_reg); + __ j(parity_even, &return_left, Label::kNear); // left is NaN. + __ jmp(&return_right, Label::kNear); // right is NaN. + + __ bind(¬_nan); + __ j(not_equal, &distinct, Label::kNear); // left != right. + + // left == right XMMRegister xmm_scratch = double_scratch0(); __ Xorpd(xmm_scratch, xmm_scratch); __ Ucomisd(left_reg, xmm_scratch); __ j(not_equal, &return_left, Label::kNear); // left == right != 0. - // At this point, both left and right are either 0 or -0. + + // At this point, both left and right are either +0 or -0. if (operation == HMathMinMax::kMathMin) { - __ orps(left_reg, right_reg); + __ Orpd(left_reg, right_reg); } else { - // Since we operate on +0 and/or -0, addsd and andsd have the same effect. - __ addsd(left_reg, right_reg); + __ Andpd(left_reg, right_reg); } __ jmp(&return_left, Label::kNear); - __ bind(&check_nan_left); - __ Ucomisd(left_reg, left_reg); // NaN check. - __ j(parity_even, &return_left, Label::kNear); + __ bind(&distinct); + __ j(condition, &return_left, Label::kNear); + __ bind(&return_right); __ Movapd(left_reg, right_reg); diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index fb622b403d..900c058e5a 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -1325,6 +1325,7 @@ class Assembler : public AssemblerBase { AVX_SP_3(vmin, 0x5d); AVX_SP_3(vmax, 0x5f); AVX_P_3(vand, 0x54); + AVX_P_3(vor, 0x56); AVX_P_3(vxor, 0x57); AVX_3(vpcmpeqd, 0x76, vpd); AVX_3(vcvtsd2ss, 0x5a, vsd); diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index 5dacdd7c32..3d3b57e00b 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -1240,6 +1240,11 @@ int DisassemblerX64::AVXInstruction(byte* data) { NameOfXMMRegister(vvvv)); current += PrintRightXMMOperand(current); break; + case 0x56: + AppendToBuffer("vorpd %s,%s,", NameOfXMMRegister(regop), + NameOfXMMRegister(vvvv)); + current += PrintRightXMMOperand(current); + break; case 0x57: AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop), NameOfXMMRegister(vvvv)); diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index d85ba12ec6..df010e04fd 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -2709,6 +2709,26 @@ void MacroAssembler::Ucomisd(XMMRegister src1, const Operand& src2) { } +void MacroAssembler::Andpd(XMMRegister dst, XMMRegister src) { + if (CpuFeatures::IsSupported(AVX)) { + CpuFeatureScope scope(this, AVX); + vandpd(dst, dst, src); + } else { + andpd(dst, src); + } +} + + +void MacroAssembler::Orpd(XMMRegister dst, XMMRegister src) { + if (CpuFeatures::IsSupported(AVX)) { + CpuFeatureScope scope(this, AVX); + vorpd(dst, dst, src); + } else { + orpd(dst, src); + } +} + + void MacroAssembler::Xorpd(XMMRegister dst, XMMRegister src) { if (CpuFeatures::IsSupported(AVX)) { CpuFeatureScope scope(this, AVX); diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index ec1cb2ac6c..08a183486c 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -926,6 +926,8 @@ class MacroAssembler: public Assembler { void Ucomisd(XMMRegister src1, XMMRegister src2); void Ucomisd(XMMRegister src1, const Operand& src2); + void Andpd(XMMRegister dst, XMMRegister src); + void Orpd(XMMRegister dst, XMMRegister src); void Xorpd(XMMRegister dst, XMMRegister src); void Pcmpeqd(XMMRegister dst, XMMRegister src); void Psllq(XMMRegister dst, byte imm8); diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc index b9e4b5fcc5..c3ec40a146 100644 --- a/test/cctest/test-assembler-x64.cc +++ b/test/cctest/test-assembler-x64.cc @@ -1450,6 +1450,25 @@ TEST(AssemblerX64AVX_sd) { __ cmpq(rdx, rcx); __ j(not_equal, &exit); + // Test vandpd, vorpd, vxorpd + __ movl(rax, Immediate(14)); + __ movl(rdx, Immediate(0x00ff00ff)); + __ movl(rcx, Immediate(0x0f0f0f0f)); + __ vmovd(xmm4, rdx); + __ vmovd(xmm5, rcx); + __ vandpd(xmm6, xmm4, xmm5); + __ vmovd(rdx, xmm6); + __ cmpl(rdx, Immediate(0x000f000f)); + __ j(not_equal, &exit); + __ vorpd(xmm6, xmm4, xmm5); + __ vmovd(rdx, xmm6); + __ cmpl(rdx, Immediate(0x0fff0fff)); + __ j(not_equal, &exit); + __ vxorpd(xmm6, xmm4, xmm5); + __ vmovd(rdx, xmm6); + __ cmpl(rdx, Immediate(0x0ff00ff0)); + __ j(not_equal, &exit); + __ movl(rdx, Immediate(6)); __ vcvtlsi2sd(xmm6, xmm6, rdx); __ movl(Operand(rsp, 0), Immediate(5)); diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc index 74e1d2212f..77b9816b4c 100644 --- a/test/cctest/test-disasm-x64.cc +++ b/test/cctest/test-disasm-x64.cc @@ -565,6 +565,8 @@ TEST(DisasmX64) { __ vandpd(xmm0, xmm9, xmm2); __ vandpd(xmm9, xmm1, Operand(rbx, rcx, times_4, 10000)); + __ vorpd(xmm0, xmm1, xmm9); + __ vorpd(xmm0, xmm1, Operand(rbx, rcx, times_4, 10000)); __ vxorpd(xmm0, xmm1, xmm9); __ vxorpd(xmm0, xmm1, Operand(rbx, rcx, times_4, 10000));