| Index: src/crankshaft/x64/lithium-codegen-x64.cc
|
| diff --git a/src/crankshaft/x64/lithium-codegen-x64.cc b/src/crankshaft/x64/lithium-codegen-x64.cc
|
| index 144889ef08537154c9ec5355e4fbf724e34b2e41..da86d317123b9bb3dfdac53b31351231f32e05ed 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.
|
| +
|
| + // 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.
|
|
|
| - __ 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);
|
|
|
|
|