[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}
This commit is contained in:
parent
d16c822ba2
commit
ce8a22a86f
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user