Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Unified Diff: src/ia32/lithium-codegen-ia32.cc

Issue 9110008: Inline Math.max and Math.min in crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen-instructions.cc ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 137d62c554648a367a14cf67e69f1d404389017e..14db90d08018a6e22b409dcf4098d53f5bcf8c9c 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -3016,6 +3016,129 @@ void LCodeGen::DoPower(LPower* instr) {
}
+void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
+ Label return_left, return_right;
+ bool is_min = instr->IsMin();
+ bool can_be_minus_zero = instr->hydrogen()->range()->CanBeMinusZero();
+ if (instr->TempAt(0) == NULL) {
+ // Integer32 case
+ Register left = ToRegister(instr->InputAt(0));
+ Register right = ToRegister(instr->InputAt(1));
+ Register result = ToRegister(instr->result());
+ ASSERT(left.is(result));
+ __ cmp(left, right);
+ __ j(is_min ? less : greater, &return_left, Label::kNear);
+ __ j(is_min ? greater : less, &return_right, Label::kNear);
+ if (can_be_minus_zero) {
+ // Both are equal, check whether we are comparing zeros.
+ __ test(result, result);
+ __ j(not_zero, &return_left, Label::kNear);
+ // Deoptimize to check for minus zero.
+ DeoptimizeIf(no_condition, instr->environment());
+ }
+ __ bind(&return_right);
+ __ mov(result, right);
+ __ bind(&return_left);
+ return;
+ }
+
+ // Tagged or unpacked double.
+ bool tagged = !instr->result()->IsDoubleRegister();
+ Label return_nan, bailout, both_smi;
+ DoubleRegister leftxmm, rightxmm, tempxmm ;
+ Register left, right;
+ Register temp = ToRegister(instr->TempAt(0));
+ if (tagged) {
+ left = ToRegister(instr->InputAt(0));
+ right = ToRegister(instr->InputAt(1));
+ leftxmm = ToDoubleRegister(instr->TempAt(1));
+ rightxmm = ToDoubleRegister(instr->TempAt(2));
+ tempxmm = rightxmm;
+ Label left_smi, right_not_smi, left_prepared, right_prepared;
+
+ __ JumpIfSmi(left, &left_smi, Label::kNear);
+ __ cmp(FieldOperand(left, HeapObject::kMapOffset),
+ masm()->isolate()->factory()->heap_number_map());
+ __ j(not_equal, &bailout);
+ __ movdbl(leftxmm, FieldOperand(left, HeapNumber::kValueOffset));
+ __ jmp(&left_prepared, Label::kNear);
+
+ __ bind(&left_smi);
+ __ JumpIfSmi(right, &both_smi);
+ __ SmiUntag(left);
+ __ cvtsi2sd(leftxmm, left);
+ __ SmiTag(left);
+ __ jmp(&right_not_smi, Label::kNear);
+ __ bind(&left_prepared);
+
+ __ JumpIfNotSmi(right, &right_not_smi, Label::kNear);
+ __ SmiUntag(right);
+ __ cvtsi2sd(rightxmm, right);
+ __ SmiTag(right);
+ __ jmp(&right_prepared, Label::kNear);
+
+ __ bind(&right_not_smi);
+ __ cmp(FieldOperand(right, HeapObject::kMapOffset),
+ masm()->isolate()->factory()->heap_number_map());
+ __ j(not_equal, &bailout);
+ __ movdbl(rightxmm, FieldOperand(right, HeapNumber::kValueOffset));
+ __ bind(&right_prepared);
+ } else {
+ leftxmm = ToDoubleRegister(instr->InputAt(0));
+ rightxmm = ToDoubleRegister(instr->InputAt(1));
+ tempxmm = ToDoubleRegister(instr->TempAt(1));
+ }
+
+ // Compare doubles.
+ __ ucomisd(leftxmm, rightxmm);
+ __ j(is_min ? below : above, &return_left);
+ __ j(is_min ? above : below, &return_right);
+ if (can_be_minus_zero) {
+ __ j(carry, &return_nan);
+ __ xorpd(tempxmm, tempxmm);
+ __ ucomisd(leftxmm, tempxmm);
+ __ j(not_equal, &return_left);
+ __ movmskpd(temp, leftxmm);
+ __ test(temp, Immediate(1));
+ __ j(is_min ? zero : not_zero, &return_right);
+ __ jmp(&return_left);
+ __ bind(&return_nan);
+ } else {
+ __ j(not_carry, &return_left);
+ }
+
+ if (tagged) {
+ Register result = ToRegister(instr->result());
+ ASSERT(left.is(result));
+ // Return NaN.
+ __ mov(result, masm()->isolate()->factory()->nan_value());
+ __ jmp(&return_left);
+
+ __ bind(&bailout);
+ DeoptimizeIf(no_condition, instr->environment());
+
+ // Both smi. Neither can be minus zero.
+ __ bind(&both_smi);
+ __ cmp(left, right);
+ __ j(is_min ? less : greater, &return_left, Label::kNear);
+ __ bind(&return_right);
+ __ mov(result, right);
+ __ bind(&return_left);
+ } else {
+ DoubleRegister result = ToDoubleRegister(instr->result());
+ ASSERT(leftxmm.is(result));
+ // Return NaN.
+ __ xorps(result, result);
+ __ divsd(result, result);
+ __ jmp(&return_left, Label::kNear);
+
+ __ bind(&return_right);
+ __ movsd(result, rightxmm);
+ __ bind(&return_left);
+ }
+}
+
+
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(instr->value()->Equals(instr->result()));
XMMRegister input_reg = ToDoubleRegister(instr->value());
« no previous file with comments | « src/hydrogen-instructions.cc ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698