Commit ce8a22a8 authored by alph's avatar alph Committed by Commit bot

[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}
parent d16c822b
......@@ -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, &not_nan, Label::kNear); // Both are not NaN.
// 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(&not_nan);
__ j(not_equal, &distinct, Label::kNear); // left != right.
__ bind(&check_zero);
// 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);
......
......@@ -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);
......
......@@ -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));
......
......@@ -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);
......
......@@ -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);
......
......@@ -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));
......
......@@ -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));
......
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