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

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 1406293003: [x64] Make use of vucomiss and vucomisd when AVX is enabled. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebaseline Created 5 years, 2 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 unified diff | Download patch
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/base/bits.h" 7 #include "src/base/bits.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/hydrogen-osr.h" 10 #include "src/hydrogen-osr.h"
(...skipping 1949 matching lines...) Expand 10 before | Expand all | Expand 10 after
1960 __ j(condition, &return_left, Label::kNear); 1960 __ j(condition, &return_left, Label::kNear);
1961 __ movp(left_reg, right_op); 1961 __ movp(left_reg, right_op);
1962 } 1962 }
1963 __ bind(&return_left); 1963 __ bind(&return_left);
1964 } else { 1964 } else {
1965 DCHECK(instr->hydrogen()->representation().IsDouble()); 1965 DCHECK(instr->hydrogen()->representation().IsDouble());
1966 Label check_nan_left, check_zero, return_left, return_right; 1966 Label check_nan_left, check_zero, return_left, return_right;
1967 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; 1967 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
1968 XMMRegister left_reg = ToDoubleRegister(left); 1968 XMMRegister left_reg = ToDoubleRegister(left);
1969 XMMRegister right_reg = ToDoubleRegister(right); 1969 XMMRegister right_reg = ToDoubleRegister(right);
1970 __ ucomisd(left_reg, right_reg); 1970 __ Ucomisd(left_reg, right_reg);
1971 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. 1971 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
1972 __ j(equal, &check_zero, Label::kNear); // left == right. 1972 __ j(equal, &check_zero, Label::kNear); // left == right.
1973 __ j(condition, &return_left, Label::kNear); 1973 __ j(condition, &return_left, Label::kNear);
1974 __ jmp(&return_right, Label::kNear); 1974 __ jmp(&return_right, Label::kNear);
1975 1975
1976 __ bind(&check_zero); 1976 __ bind(&check_zero);
1977 XMMRegister xmm_scratch = double_scratch0(); 1977 XMMRegister xmm_scratch = double_scratch0();
1978 __ Xorpd(xmm_scratch, xmm_scratch); 1978 __ Xorpd(xmm_scratch, xmm_scratch);
1979 __ ucomisd(left_reg, xmm_scratch); 1979 __ Ucomisd(left_reg, xmm_scratch);
1980 __ j(not_equal, &return_left, Label::kNear); // left == right != 0. 1980 __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
1981 // At this point, both left and right are either 0 or -0. 1981 // At this point, both left and right are either 0 or -0.
1982 if (operation == HMathMinMax::kMathMin) { 1982 if (operation == HMathMinMax::kMathMin) {
1983 __ orps(left_reg, right_reg); 1983 __ orps(left_reg, right_reg);
1984 } else { 1984 } else {
1985 // Since we operate on +0 and/or -0, addsd and andsd have the same effect. 1985 // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
1986 __ addsd(left_reg, right_reg); 1986 __ addsd(left_reg, right_reg);
1987 } 1987 }
1988 __ jmp(&return_left, Label::kNear); 1988 __ jmp(&return_left, Label::kNear);
1989 1989
1990 __ bind(&check_nan_left); 1990 __ bind(&check_nan_left);
1991 __ ucomisd(left_reg, left_reg); // NaN check. 1991 __ Ucomisd(left_reg, left_reg); // NaN check.
1992 __ j(parity_even, &return_left, Label::kNear); 1992 __ j(parity_even, &return_left, Label::kNear);
1993 __ bind(&return_right); 1993 __ bind(&return_right);
1994 __ Movapd(left_reg, right_reg); 1994 __ Movapd(left_reg, right_reg);
1995 1995
1996 __ bind(&return_left); 1996 __ bind(&return_left);
1997 } 1997 }
1998 } 1998 }
1999 1999
2000 2000
2001 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 2001 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2122 } else if (r.IsSmi()) { 2122 } else if (r.IsSmi()) {
2123 DCHECK(!info()->IsStub()); 2123 DCHECK(!info()->IsStub());
2124 Register reg = ToRegister(instr->value()); 2124 Register reg = ToRegister(instr->value());
2125 __ testp(reg, reg); 2125 __ testp(reg, reg);
2126 EmitBranch(instr, not_zero); 2126 EmitBranch(instr, not_zero);
2127 } else if (r.IsDouble()) { 2127 } else if (r.IsDouble()) {
2128 DCHECK(!info()->IsStub()); 2128 DCHECK(!info()->IsStub());
2129 XMMRegister reg = ToDoubleRegister(instr->value()); 2129 XMMRegister reg = ToDoubleRegister(instr->value());
2130 XMMRegister xmm_scratch = double_scratch0(); 2130 XMMRegister xmm_scratch = double_scratch0();
2131 __ Xorpd(xmm_scratch, xmm_scratch); 2131 __ Xorpd(xmm_scratch, xmm_scratch);
2132 __ ucomisd(reg, xmm_scratch); 2132 __ Ucomisd(reg, xmm_scratch);
2133 EmitBranch(instr, not_equal); 2133 EmitBranch(instr, not_equal);
2134 } else { 2134 } else {
2135 DCHECK(r.IsTagged()); 2135 DCHECK(r.IsTagged());
2136 Register reg = ToRegister(instr->value()); 2136 Register reg = ToRegister(instr->value());
2137 HType type = instr->hydrogen()->value()->type(); 2137 HType type = instr->hydrogen()->value()->type();
2138 if (type.IsBoolean()) { 2138 if (type.IsBoolean()) {
2139 DCHECK(!info()->IsStub()); 2139 DCHECK(!info()->IsStub());
2140 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 2140 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2141 EmitBranch(instr, equal); 2141 EmitBranch(instr, equal);
2142 } else if (type.IsSmi()) { 2142 } else if (type.IsSmi()) {
2143 DCHECK(!info()->IsStub()); 2143 DCHECK(!info()->IsStub());
2144 __ SmiCompare(reg, Smi::FromInt(0)); 2144 __ SmiCompare(reg, Smi::FromInt(0));
2145 EmitBranch(instr, not_equal); 2145 EmitBranch(instr, not_equal);
2146 } else if (type.IsJSArray()) { 2146 } else if (type.IsJSArray()) {
2147 DCHECK(!info()->IsStub()); 2147 DCHECK(!info()->IsStub());
2148 EmitBranch(instr, no_condition); 2148 EmitBranch(instr, no_condition);
2149 } else if (type.IsHeapNumber()) { 2149 } else if (type.IsHeapNumber()) {
2150 DCHECK(!info()->IsStub()); 2150 DCHECK(!info()->IsStub());
2151 XMMRegister xmm_scratch = double_scratch0(); 2151 XMMRegister xmm_scratch = double_scratch0();
2152 __ Xorpd(xmm_scratch, xmm_scratch); 2152 __ Xorpd(xmm_scratch, xmm_scratch);
2153 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 2153 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
2154 EmitBranch(instr, not_equal); 2154 EmitBranch(instr, not_equal);
2155 } else if (type.IsString()) { 2155 } else if (type.IsString()) {
2156 DCHECK(!info()->IsStub()); 2156 DCHECK(!info()->IsStub());
2157 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 2157 __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2158 EmitBranch(instr, not_equal); 2158 EmitBranch(instr, not_equal);
2159 } else { 2159 } else {
2160 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2160 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2161 // Avoid deopts in the case where we've never executed this path before. 2161 // Avoid deopts in the case where we've never executed this path before.
2162 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); 2162 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2163 2163
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2232 __ j(equal, instr->TrueLabel(chunk_)); 2232 __ j(equal, instr->TrueLabel(chunk_));
2233 } 2233 }
2234 2234
2235 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2235 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2236 // heap number -> false iff +0, -0, or NaN. 2236 // heap number -> false iff +0, -0, or NaN.
2237 Label not_heap_number; 2237 Label not_heap_number;
2238 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 2238 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
2239 __ j(not_equal, &not_heap_number, Label::kNear); 2239 __ j(not_equal, &not_heap_number, Label::kNear);
2240 XMMRegister xmm_scratch = double_scratch0(); 2240 XMMRegister xmm_scratch = double_scratch0();
2241 __ Xorpd(xmm_scratch, xmm_scratch); 2241 __ Xorpd(xmm_scratch, xmm_scratch);
2242 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 2242 __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
2243 __ j(zero, instr->FalseLabel(chunk_)); 2243 __ j(zero, instr->FalseLabel(chunk_));
2244 __ jmp(instr->TrueLabel(chunk_)); 2244 __ jmp(instr->TrueLabel(chunk_));
2245 __ bind(&not_heap_number); 2245 __ bind(&not_heap_number);
2246 } 2246 }
2247 2247
2248 if (!expected.IsGeneric()) { 2248 if (!expected.IsGeneric()) {
2249 // We've seen something for the first time -> deopt. 2249 // We've seen something for the first time -> deopt.
2250 // This can only happen if we are not generic already. 2250 // This can only happen if we are not generic already.
2251 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject); 2251 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject);
2252 } 2252 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2312 // We can statically evaluate the comparison. 2312 // We can statically evaluate the comparison.
2313 double left_val = ToDouble(LConstantOperand::cast(left)); 2313 double left_val = ToDouble(LConstantOperand::cast(left));
2314 double right_val = ToDouble(LConstantOperand::cast(right)); 2314 double right_val = ToDouble(LConstantOperand::cast(right));
2315 int next_block = EvalComparison(instr->op(), left_val, right_val) ? 2315 int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2316 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); 2316 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2317 EmitGoto(next_block); 2317 EmitGoto(next_block);
2318 } else { 2318 } else {
2319 if (instr->is_double()) { 2319 if (instr->is_double()) {
2320 // Don't base result on EFLAGS when a NaN is involved. Instead 2320 // Don't base result on EFLAGS when a NaN is involved. Instead
2321 // jump to the false block. 2321 // jump to the false block.
2322 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 2322 __ Ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
2323 __ j(parity_even, instr->FalseLabel(chunk_)); 2323 __ j(parity_even, instr->FalseLabel(chunk_));
2324 } else { 2324 } else {
2325 int32_t value; 2325 int32_t value;
2326 if (right->IsConstantOperand()) { 2326 if (right->IsConstantOperand()) {
2327 value = ToInteger32(LConstantOperand::cast(right)); 2327 value = ToInteger32(LConstantOperand::cast(right));
2328 if (instr->hydrogen_value()->representation().IsSmi()) { 2328 if (instr->hydrogen_value()->representation().IsSmi()) {
2329 __ Cmp(ToRegister(left), Smi::FromInt(value)); 2329 __ Cmp(ToRegister(left), Smi::FromInt(value));
2330 } else { 2330 } else {
2331 __ cmpl(ToRegister(left), Immediate(value)); 2331 __ cmpl(ToRegister(left), Immediate(value));
2332 } 2332 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2380 2380
2381 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { 2381 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2382 if (instr->hydrogen()->representation().IsTagged()) { 2382 if (instr->hydrogen()->representation().IsTagged()) {
2383 Register input_reg = ToRegister(instr->object()); 2383 Register input_reg = ToRegister(instr->object());
2384 __ Cmp(input_reg, factory()->the_hole_value()); 2384 __ Cmp(input_reg, factory()->the_hole_value());
2385 EmitBranch(instr, equal); 2385 EmitBranch(instr, equal);
2386 return; 2386 return;
2387 } 2387 }
2388 2388
2389 XMMRegister input_reg = ToDoubleRegister(instr->object()); 2389 XMMRegister input_reg = ToDoubleRegister(instr->object());
2390 __ ucomisd(input_reg, input_reg); 2390 __ Ucomisd(input_reg, input_reg);
2391 EmitFalseBranch(instr, parity_odd); 2391 EmitFalseBranch(instr, parity_odd);
2392 2392
2393 __ subp(rsp, Immediate(kDoubleSize)); 2393 __ subp(rsp, Immediate(kDoubleSize));
2394 __ Movsd(MemOperand(rsp, 0), input_reg); 2394 __ Movsd(MemOperand(rsp, 0), input_reg);
2395 __ addp(rsp, Immediate(kDoubleSize)); 2395 __ addp(rsp, Immediate(kDoubleSize));
2396 2396
2397 int offset = sizeof(kHoleNanUpper32); 2397 int offset = sizeof(kHoleNanUpper32);
2398 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32)); 2398 __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32));
2399 EmitBranch(instr, equal); 2399 EmitBranch(instr, equal);
2400 } 2400 }
2401 2401
2402 2402
2403 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { 2403 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2404 Representation rep = instr->hydrogen()->value()->representation(); 2404 Representation rep = instr->hydrogen()->value()->representation();
2405 DCHECK(!rep.IsInteger32()); 2405 DCHECK(!rep.IsInteger32());
2406 2406
2407 if (rep.IsDouble()) { 2407 if (rep.IsDouble()) {
2408 XMMRegister value = ToDoubleRegister(instr->value()); 2408 XMMRegister value = ToDoubleRegister(instr->value());
2409 XMMRegister xmm_scratch = double_scratch0(); 2409 XMMRegister xmm_scratch = double_scratch0();
2410 __ Xorpd(xmm_scratch, xmm_scratch); 2410 __ Xorpd(xmm_scratch, xmm_scratch);
2411 __ ucomisd(xmm_scratch, value); 2411 __ Ucomisd(xmm_scratch, value);
2412 EmitFalseBranch(instr, not_equal); 2412 EmitFalseBranch(instr, not_equal);
2413 __ Movmskpd(kScratchRegister, value); 2413 __ Movmskpd(kScratchRegister, value);
2414 __ testl(kScratchRegister, Immediate(1)); 2414 __ testl(kScratchRegister, Immediate(1));
2415 EmitBranch(instr, not_zero); 2415 EmitBranch(instr, not_zero);
2416 } else { 2416 } else {
2417 Register value = ToRegister(instr->value()); 2417 Register value = ToRegister(instr->value());
2418 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); 2418 Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
2419 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); 2419 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
2420 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset), 2420 __ cmpl(FieldOperand(value, HeapNumber::kExponentOffset),
2421 Immediate(0x1)); 2421 Immediate(0x1));
(...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after
3608 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); 3608 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero);
3609 } 3609 }
3610 __ roundsd(xmm_scratch, input_reg, kRoundDown); 3610 __ roundsd(xmm_scratch, input_reg, kRoundDown);
3611 __ Cvttsd2si(output_reg, xmm_scratch); 3611 __ Cvttsd2si(output_reg, xmm_scratch);
3612 __ cmpl(output_reg, Immediate(0x1)); 3612 __ cmpl(output_reg, Immediate(0x1));
3613 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3613 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
3614 } else { 3614 } else {
3615 Label negative_sign, done; 3615 Label negative_sign, done;
3616 // Deoptimize on unordered. 3616 // Deoptimize on unordered.
3617 __ Xorpd(xmm_scratch, xmm_scratch); // Zero the register. 3617 __ Xorpd(xmm_scratch, xmm_scratch); // Zero the register.
3618 __ ucomisd(input_reg, xmm_scratch); 3618 __ Ucomisd(input_reg, xmm_scratch);
3619 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); 3619 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
3620 __ j(below, &negative_sign, Label::kNear); 3620 __ j(below, &negative_sign, Label::kNear);
3621 3621
3622 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3622 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3623 // Check for negative zero. 3623 // Check for negative zero.
3624 Label positive_sign; 3624 Label positive_sign;
3625 __ j(above, &positive_sign, Label::kNear); 3625 __ j(above, &positive_sign, Label::kNear);
3626 __ Movmskpd(output_reg, input_reg); 3626 __ Movmskpd(output_reg, input_reg);
3627 __ testl(output_reg, Immediate(1)); 3627 __ testl(output_reg, Immediate(1));
3628 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 3628 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
3629 __ Set(output_reg, 0); 3629 __ Set(output_reg, 0);
3630 __ jmp(&done); 3630 __ jmp(&done);
3631 __ bind(&positive_sign); 3631 __ bind(&positive_sign);
3632 } 3632 }
3633 3633
3634 // Use truncating instruction (OK because input is positive). 3634 // Use truncating instruction (OK because input is positive).
3635 __ Cvttsd2si(output_reg, input_reg); 3635 __ Cvttsd2si(output_reg, input_reg);
3636 // Overflow is signalled with minint. 3636 // Overflow is signalled with minint.
3637 __ cmpl(output_reg, Immediate(0x1)); 3637 __ cmpl(output_reg, Immediate(0x1));
3638 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3638 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
3639 __ jmp(&done, Label::kNear); 3639 __ jmp(&done, Label::kNear);
3640 3640
3641 // Non-zero negative reaches here. 3641 // Non-zero negative reaches here.
3642 __ bind(&negative_sign); 3642 __ bind(&negative_sign);
3643 // Truncate, then compare and compensate. 3643 // Truncate, then compare and compensate.
3644 __ Cvttsd2si(output_reg, input_reg); 3644 __ Cvttsd2si(output_reg, input_reg);
3645 __ Cvtlsi2sd(xmm_scratch, output_reg); 3645 __ Cvtlsi2sd(xmm_scratch, output_reg);
3646 __ ucomisd(input_reg, xmm_scratch); 3646 __ Ucomisd(input_reg, xmm_scratch);
3647 __ j(equal, &done, Label::kNear); 3647 __ j(equal, &done, Label::kNear);
3648 __ subl(output_reg, Immediate(1)); 3648 __ subl(output_reg, Immediate(1));
3649 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3649 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
3650 3650
3651 __ bind(&done); 3651 __ bind(&done);
3652 } 3652 }
3653 } 3653 }
3654 3654
3655 3655
3656 void LCodeGen::DoMathRound(LMathRound* instr) { 3656 void LCodeGen::DoMathRound(LMathRound* instr) {
3657 const XMMRegister xmm_scratch = double_scratch0(); 3657 const XMMRegister xmm_scratch = double_scratch0();
3658 Register output_reg = ToRegister(instr->result()); 3658 Register output_reg = ToRegister(instr->result());
3659 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3659 XMMRegister input_reg = ToDoubleRegister(instr->value());
3660 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 3660 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3661 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 3661 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
3662 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 3662 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
3663 3663
3664 Label done, round_to_zero, below_one_half; 3664 Label done, round_to_zero, below_one_half;
3665 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3665 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3666 __ movq(kScratchRegister, one_half); 3666 __ movq(kScratchRegister, one_half);
3667 __ Movq(xmm_scratch, kScratchRegister); 3667 __ Movq(xmm_scratch, kScratchRegister);
3668 __ ucomisd(xmm_scratch, input_reg); 3668 __ Ucomisd(xmm_scratch, input_reg);
3669 __ j(above, &below_one_half, Label::kNear); 3669 __ j(above, &below_one_half, Label::kNear);
3670 3670
3671 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3671 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3672 __ addsd(xmm_scratch, input_reg); 3672 __ addsd(xmm_scratch, input_reg);
3673 __ Cvttsd2si(output_reg, xmm_scratch); 3673 __ Cvttsd2si(output_reg, xmm_scratch);
3674 // Overflow is signalled with minint. 3674 // Overflow is signalled with minint.
3675 __ cmpl(output_reg, Immediate(0x1)); 3675 __ cmpl(output_reg, Immediate(0x1));
3676 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3676 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
3677 __ jmp(&done, dist); 3677 __ jmp(&done, dist);
3678 3678
3679 __ bind(&below_one_half); 3679 __ bind(&below_one_half);
3680 __ movq(kScratchRegister, minus_one_half); 3680 __ movq(kScratchRegister, minus_one_half);
3681 __ Movq(xmm_scratch, kScratchRegister); 3681 __ Movq(xmm_scratch, kScratchRegister);
3682 __ ucomisd(xmm_scratch, input_reg); 3682 __ Ucomisd(xmm_scratch, input_reg);
3683 __ j(below_equal, &round_to_zero, Label::kNear); 3683 __ j(below_equal, &round_to_zero, Label::kNear);
3684 3684
3685 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3685 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3686 // compare and compensate. 3686 // compare and compensate.
3687 __ Movapd(input_temp, input_reg); // Do not alter input_reg. 3687 __ Movapd(input_temp, input_reg); // Do not alter input_reg.
3688 __ subsd(input_temp, xmm_scratch); 3688 __ subsd(input_temp, xmm_scratch);
3689 __ Cvttsd2si(output_reg, input_temp); 3689 __ Cvttsd2si(output_reg, input_temp);
3690 // Catch minint due to overflow, and to prevent overflow when compensating. 3690 // Catch minint due to overflow, and to prevent overflow when compensating.
3691 __ cmpl(output_reg, Immediate(0x1)); 3691 __ cmpl(output_reg, Immediate(0x1));
3692 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3692 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow);
3693 3693
3694 __ Cvtlsi2sd(xmm_scratch, output_reg); 3694 __ Cvtlsi2sd(xmm_scratch, output_reg);
3695 __ ucomisd(xmm_scratch, input_temp); 3695 __ Ucomisd(xmm_scratch, input_temp);
3696 __ j(equal, &done, dist); 3696 __ j(equal, &done, dist);
3697 __ subl(output_reg, Immediate(1)); 3697 __ subl(output_reg, Immediate(1));
3698 // No overflow because we already ruled out minint. 3698 // No overflow because we already ruled out minint.
3699 __ jmp(&done, dist); 3699 __ jmp(&done, dist);
3700 3700
3701 __ bind(&round_to_zero); 3701 __ bind(&round_to_zero);
3702 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3702 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3703 // we can ignore the difference between a result of -0 and +0. 3703 // we can ignore the difference between a result of -0 and +0.
3704 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3704 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3705 __ Movq(output_reg, input_reg); 3705 __ Movq(output_reg, input_reg);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3737 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); 3737 DCHECK(ToDoubleRegister(instr->result()).is(input_reg));
3738 3738
3739 // Note that according to ECMA-262 15.8.2.13: 3739 // Note that according to ECMA-262 15.8.2.13:
3740 // Math.pow(-Infinity, 0.5) == Infinity 3740 // Math.pow(-Infinity, 0.5) == Infinity
3741 // Math.sqrt(-Infinity) == NaN 3741 // Math.sqrt(-Infinity) == NaN
3742 Label done, sqrt; 3742 Label done, sqrt;
3743 // Check base for -Infinity. According to IEEE-754, double-precision 3743 // Check base for -Infinity. According to IEEE-754, double-precision
3744 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. 3744 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared.
3745 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); 3745 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000));
3746 __ Movq(xmm_scratch, kScratchRegister); 3746 __ Movq(xmm_scratch, kScratchRegister);
3747 __ ucomisd(xmm_scratch, input_reg); 3747 __ Ucomisd(xmm_scratch, input_reg);
3748 // Comparing -Infinity with NaN results in "unordered", which sets the 3748 // Comparing -Infinity with NaN results in "unordered", which sets the
3749 // zero flag as if both were equal. However, it also sets the carry flag. 3749 // zero flag as if both were equal. However, it also sets the carry flag.
3750 __ j(not_equal, &sqrt, Label::kNear); 3750 __ j(not_equal, &sqrt, Label::kNear);
3751 __ j(carry, &sqrt, Label::kNear); 3751 __ j(carry, &sqrt, Label::kNear);
3752 // If input is -Infinity, return Infinity. 3752 // If input is -Infinity, return Infinity.
3753 __ Xorpd(input_reg, input_reg); 3753 __ Xorpd(input_reg, input_reg);
3754 __ subsd(input_reg, xmm_scratch); 3754 __ subsd(input_reg, xmm_scratch);
3755 __ jmp(&done, Label::kNear); 3755 __ jmp(&done, Label::kNear);
3756 3756
3757 // Square root. 3757 // Square root.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3808 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); 3808 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2);
3809 } 3809 }
3810 3810
3811 3811
3812 void LCodeGen::DoMathLog(LMathLog* instr) { 3812 void LCodeGen::DoMathLog(LMathLog* instr) {
3813 DCHECK(instr->value()->Equals(instr->result())); 3813 DCHECK(instr->value()->Equals(instr->result()));
3814 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3814 XMMRegister input_reg = ToDoubleRegister(instr->value());
3815 XMMRegister xmm_scratch = double_scratch0(); 3815 XMMRegister xmm_scratch = double_scratch0();
3816 Label positive, done, zero; 3816 Label positive, done, zero;
3817 __ Xorpd(xmm_scratch, xmm_scratch); 3817 __ Xorpd(xmm_scratch, xmm_scratch);
3818 __ ucomisd(input_reg, xmm_scratch); 3818 __ Ucomisd(input_reg, xmm_scratch);
3819 __ j(above, &positive, Label::kNear); 3819 __ j(above, &positive, Label::kNear);
3820 __ j(not_carry, &zero, Label::kNear); 3820 __ j(not_carry, &zero, Label::kNear);
3821 __ pcmpeqd(input_reg, input_reg); 3821 __ pcmpeqd(input_reg, input_reg);
3822 __ jmp(&done, Label::kNear); 3822 __ jmp(&done, Label::kNear);
3823 __ bind(&zero); 3823 __ bind(&zero);
3824 ExternalReference ninf = 3824 ExternalReference ninf =
3825 ExternalReference::address_of_negative_infinity(); 3825 ExternalReference::address_of_negative_infinity();
3826 Operand ninf_operand = masm()->ExternalOperand(ninf); 3826 Operand ninf_operand = masm()->ExternalOperand(ninf);
3827 __ Movsd(input_reg, ninf_operand); 3827 __ Movsd(input_reg, ninf_operand);
3828 __ jmp(&done, Label::kNear); 3828 __ jmp(&done, Label::kNear);
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after
4917 4917
4918 if (can_convert_undefined_to_nan) { 4918 if (can_convert_undefined_to_nan) {
4919 __ j(not_equal, &convert, Label::kNear); 4919 __ j(not_equal, &convert, Label::kNear);
4920 } else { 4920 } else {
4921 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 4921 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
4922 } 4922 }
4923 4923
4924 if (deoptimize_on_minus_zero) { 4924 if (deoptimize_on_minus_zero) {
4925 XMMRegister xmm_scratch = double_scratch0(); 4925 XMMRegister xmm_scratch = double_scratch0();
4926 __ Xorpd(xmm_scratch, xmm_scratch); 4926 __ Xorpd(xmm_scratch, xmm_scratch);
4927 __ ucomisd(xmm_scratch, result_reg); 4927 __ Ucomisd(xmm_scratch, result_reg);
4928 __ j(not_equal, &done, Label::kNear); 4928 __ j(not_equal, &done, Label::kNear);
4929 __ Movmskpd(kScratchRegister, result_reg); 4929 __ Movmskpd(kScratchRegister, result_reg);
4930 __ testl(kScratchRegister, Immediate(1)); 4930 __ testl(kScratchRegister, Immediate(1));
4931 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 4931 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
4932 } 4932 }
4933 __ jmp(&done, Label::kNear); 4933 __ jmp(&done, Label::kNear);
4934 4934
4935 if (can_convert_undefined_to_nan) { 4935 if (can_convert_undefined_to_nan) {
4936 __ bind(&convert); 4936 __ bind(&convert);
4937 4937
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
4988 __ Set(input_reg, 0); 4988 __ Set(input_reg, 0);
4989 } else { 4989 } else {
4990 XMMRegister scratch = ToDoubleRegister(instr->temp()); 4990 XMMRegister scratch = ToDoubleRegister(instr->temp());
4991 DCHECK(!scratch.is(xmm0)); 4991 DCHECK(!scratch.is(xmm0));
4992 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 4992 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
4993 Heap::kHeapNumberMapRootIndex); 4993 Heap::kHeapNumberMapRootIndex);
4994 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 4994 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
4995 __ Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4995 __ Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
4996 __ Cvttsd2si(input_reg, xmm0); 4996 __ Cvttsd2si(input_reg, xmm0);
4997 __ Cvtlsi2sd(scratch, input_reg); 4997 __ Cvtlsi2sd(scratch, input_reg);
4998 __ ucomisd(xmm0, scratch); 4998 __ Ucomisd(xmm0, scratch);
4999 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); 4999 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
5000 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); 5000 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
5001 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 5001 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
5002 __ testl(input_reg, input_reg); 5002 __ testl(input_reg, input_reg);
5003 __ j(not_zero, done); 5003 __ j(not_zero, done);
5004 __ Movmskpd(input_reg, xmm0); 5004 __ Movmskpd(input_reg, xmm0);
5005 __ andl(input_reg, Immediate(1)); 5005 __ andl(input_reg, Immediate(1));
5006 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 5006 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
5007 } 5007 }
5008 } 5008 }
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
5904 RecordSafepoint(Safepoint::kNoLazyDeopt); 5904 RecordSafepoint(Safepoint::kNoLazyDeopt);
5905 } 5905 }
5906 5906
5907 5907
5908 #undef __ 5908 #undef __
5909 5909
5910 } // namespace internal 5910 } // namespace internal
5911 } // namespace v8 5911 } // namespace v8
5912 5912
5913 #endif // V8_TARGET_ARCH_X64 5913 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698