Index: src/ia32/lithium-codegen-ia32.cc |
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc |
index 8869a3e98d1b9d9fe89836d731b6e59ac3b94af2..9f336e5b57a722222c221045136db65b567bee2e 100644 |
--- a/src/ia32/lithium-codegen-ia32.cc |
+++ b/src/ia32/lithium-codegen-ia32.cc |
@@ -1497,6 +1497,67 @@ void LCodeGen::DoAddI(LAddI* instr) { |
} |
+void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
+ LOperand* left = instr->InputAt(0); |
+ LOperand* right = instr->InputAt(1); |
+ ASSERT(left->Equals(instr->result())); |
+ HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
+ if (instr->hydrogen()->representation().IsInteger32()) { |
+ Label return_left; |
+ Condition condition = (operation == HMathMinMax::kMathMin) |
+ ? less_equal |
+ : greater_equal; |
+ if (right->IsConstantOperand()) { |
+ Operand left_op = ToOperand(left); |
+ Immediate right_imm = ToInteger32Immediate(right); |
+ __ cmp(left_op, right_imm); |
+ __ j(condition, &return_left, Label::kNear); |
+ __ mov(left_op, right_imm); |
+ } else { |
+ Register left_reg = ToRegister(left); |
+ Operand right_op = ToOperand(right); |
+ __ cmp(left_reg, right_op); |
+ __ j(condition, &return_left, Label::kNear); |
+ __ mov(left_reg, right_op); |
+ } |
+ __ bind(&return_left); |
+ } else { |
+ ASSERT(instr->hydrogen()->representation().IsDouble()); |
+ Label check_nan_left, check_zero, 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); |
+ |
+ __ bind(&check_zero); |
+ XMMRegister xmm_scratch = xmm0; |
+ __ xorps(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. |
+ if (operation == HMathMinMax::kMathMin) { |
+ __ 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); |
+ } |
+ __ jmp(&return_left, Label::kNear); |
+ |
+ __ bind(&check_nan_left); |
+ __ ucomisd(left_reg, left_reg); // NaN check. |
+ __ j(parity_even, &return_left, Label::kNear); // left == NaN. |
+ __ bind(&return_right); |
+ __ movsd(left_reg, right_reg); |
+ |
+ __ bind(&return_left); |
+ } |
+} |
+ |
+ |
void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
XMMRegister left = ToDoubleRegister(instr->InputAt(0)); |
XMMRegister right = ToDoubleRegister(instr->InputAt(1)); |