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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 197057: Use SSE2 instructions when available on ia32 platform. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 // be either smi or heap number objects (fp values). Requirements: 761 // be either smi or heap number objects (fp values). Requirements:
762 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as 762 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as
763 // floating point numbers on FPU stack. 763 // floating point numbers on FPU stack.
764 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); 764 static void LoadFloatOperands(MacroAssembler* masm, Register scratch);
765 // Test if operands are smi or number objects (fp). Requirements: 765 // Test if operands are smi or number objects (fp). Requirements:
766 // operand_1 in eax, operand_2 in edx; falls through on float 766 // operand_1 in eax, operand_2 in edx; falls through on float
767 // operands, jumps to the non_float label otherwise. 767 // operands, jumps to the non_float label otherwise.
768 static void CheckFloatOperands(MacroAssembler* masm, 768 static void CheckFloatOperands(MacroAssembler* masm,
769 Label* non_float, 769 Label* non_float,
770 Register scratch); 770 Register scratch);
771 // Test if operands are numbers (smi or HeapNumber objects), and load
772 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if
773 // either operand is not a number. Operands are in edx and eax.
774 // Leaves operands unchanged.
775 static void LoadSse2Operands(MacroAssembler* masm, Label* not_numbers);
771 // Allocate a heap number in new space with undefined value. 776 // Allocate a heap number in new space with undefined value.
772 // Returns tagged pointer in eax, or jumps to need_gc if new space is full. 777 // Returns tagged pointer in eax, or jumps to need_gc if new space is full.
773 static void AllocateHeapNumber(MacroAssembler* masm, 778 static void AllocateHeapNumber(MacroAssembler* masm,
774 Label* need_gc, 779 Label* need_gc,
775 Register scratch1, 780 Register scratch1,
776 Register scratch2, 781 Register scratch2,
777 Register result); 782 Register result);
778 }; 783 };
779 784
780 785
(...skipping 5911 matching lines...) Expand 10 before | Expand all | Expand 10 after
6692 __ mov(edx, Operand(esp, 2 * kPointerSize)); // get x 6697 __ mov(edx, Operand(esp, 2 * kPointerSize)); // get x
6693 6698
6694 // Floating point case. 6699 // Floating point case.
6695 switch (op_) { 6700 switch (op_) {
6696 case Token::ADD: 6701 case Token::ADD:
6697 case Token::SUB: 6702 case Token::SUB:
6698 case Token::MUL: 6703 case Token::MUL:
6699 case Token::DIV: { 6704 case Token::DIV: {
6700 // eax: y 6705 // eax: y
6701 // edx: x 6706 // edx: x
6702 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 6707
6703 // Fast-case: Both operands are numbers. 6708 if (CpuFeatures::IsSupported(CpuFeatures::SSE2)) {
6704 // Allocate a heap number, if needed. 6709 CpuFeatures::Scope use_sse2(CpuFeatures::SSE2);
6705 Label skip_allocation; 6710 FloatingPointHelper::LoadSse2Operands(masm, &call_runtime);
6706 switch (mode_) { 6711
6707 case OVERWRITE_LEFT: 6712 switch (op_) {
6708 __ mov(eax, Operand(edx)); 6713 case Token::ADD: __ addsd(xmm0, xmm1); break;
6709 // Fall through! 6714 case Token::SUB: __ subsd(xmm0, xmm1); break;
6710 case OVERWRITE_RIGHT: 6715 case Token::MUL: __ mulsd(xmm0, xmm1); break;
6711 // If the argument in eax is already an object, we skip the 6716 case Token::DIV: __ divsd(xmm0, xmm1); break;
6712 // allocation of a heap number. 6717 default: UNREACHABLE();
6713 __ test(eax, Immediate(kSmiTagMask)); 6718 }
6714 __ j(not_zero, &skip_allocation, not_taken); 6719 // Allocate a heap number, if needed.
6715 // Fall through! 6720 Label skip_allocation;
6716 case NO_OVERWRITE: 6721 switch (mode_) {
6717 FloatingPointHelper::AllocateHeapNumber(masm, 6722 case OVERWRITE_LEFT:
6718 &call_runtime, 6723 __ mov(eax, Operand(edx));
6719 ecx, 6724 // Fall through!
6720 edx, 6725 case OVERWRITE_RIGHT:
6721 eax); 6726 // If the argument in eax is already an object, we skip the
6722 __ bind(&skip_allocation); 6727 // allocation of a heap number.
6723 break; 6728 __ test(eax, Immediate(kSmiTagMask));
6724 default: UNREACHABLE(); 6729 __ j(not_zero, &skip_allocation, not_taken);
6730 // Fall through!
6731 case NO_OVERWRITE:
6732 FloatingPointHelper::AllocateHeapNumber(masm,
6733 &call_runtime,
6734 ecx,
6735 edx,
6736 eax);
6737 __ bind(&skip_allocation);
6738 break;
6739 default: UNREACHABLE();
6740 }
6741 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
6742 __ ret(2 * kPointerSize);
6743
6744 } else { // SSE2 not available, use FPU.
6745 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
Mark Mentovai 2009/09/09 15:09:55 Shouldn't this be done for both SSE2 and x87, or s
William Hesse 2009/09/10 07:27:37 The checking and the loading are combined into one
6746 // Allocate a heap number, if needed.
Mark Mentovai 2009/09/09 15:09:55 Is there a reason that this is done before the x87
William Hesse 2009/09/10 07:27:37 This code has to go after the check, but before th
6747 Label skip_allocation;
6748 switch (mode_) {
6749 case OVERWRITE_LEFT:
6750 __ mov(eax, Operand(edx));
6751 // Fall through!
6752 case OVERWRITE_RIGHT:
6753 // If the argument in eax is already an object, we skip the
6754 // allocation of a heap number.
6755 __ test(eax, Immediate(kSmiTagMask));
6756 __ j(not_zero, &skip_allocation, not_taken);
6757 // Fall through!
6758 case NO_OVERWRITE:
6759 FloatingPointHelper::AllocateHeapNumber(masm,
6760 &call_runtime,
6761 ecx,
6762 edx,
6763 eax);
6764 __ bind(&skip_allocation);
6765 break;
6766 default: UNREACHABLE();
6767 }
6768 FloatingPointHelper::LoadFloatOperands(masm, ecx);
6769
6770 switch (op_) {
6771 case Token::ADD: __ faddp(1); break;
6772 case Token::SUB: __ fsubp(1); break;
6773 case Token::MUL: __ fmulp(1); break;
6774 case Token::DIV: __ fdivp(1); break;
6775 default: UNREACHABLE();
6776 }
6777 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
6778 __ ret(2 * kPointerSize);
6725 } 6779 }
6726 FloatingPointHelper::LoadFloatOperands(masm, ecx);
6727
6728 switch (op_) {
6729 case Token::ADD: __ faddp(1); break;
6730 case Token::SUB: __ fsubp(1); break;
6731 case Token::MUL: __ fmulp(1); break;
6732 case Token::DIV: __ fdivp(1); break;
6733 default: UNREACHABLE();
6734 }
6735 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
6736 __ ret(2 * kPointerSize);
6737 } 6780 }
6738 case Token::MOD: { 6781 case Token::MOD: {
6739 // For MOD we go directly to runtime in the non-smi case. 6782 // For MOD we go directly to runtime in the non-smi case.
6740 break; 6783 break;
6741 } 6784 }
6742 case Token::BIT_OR: 6785 case Token::BIT_OR:
6743 case Token::BIT_AND: 6786 case Token::BIT_AND:
6744 case Token::BIT_XOR: 6787 case Token::BIT_XOR:
6745 case Token::SAR: 6788 case Token::SAR:
6746 case Token::SHL: 6789 case Token::SHL:
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
6974 __ bind(&load_smi); 7017 __ bind(&load_smi);
6975 __ sar(number, kSmiTagSize); 7018 __ sar(number, kSmiTagSize);
6976 __ push(number); 7019 __ push(number);
6977 __ fild_s(Operand(esp, 0)); 7020 __ fild_s(Operand(esp, 0));
6978 __ pop(number); 7021 __ pop(number);
6979 7022
6980 __ bind(&done); 7023 __ bind(&done);
6981 } 7024 }
6982 7025
6983 7026
7027 void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm,
7028 Label* not_numbers) {
7029 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
7030 // Load operand in edx into xmm0, or branch to not_numbers.
7031 __ test(edx, Immediate(kSmiTagMask));
7032 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
7033 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map());
7034 __ j(not_equal, not_numbers); // Argument in edx is not a number.
7035 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
7036 __ bind(&load_eax);
7037 // Load operand in eax into xmm1, or branch to not_numbers.
7038 __ test(eax, Immediate(kSmiTagMask));
7039 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
7040 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map());
7041 __ j(equal, &load_float_eax);
7042 __ jmp(not_numbers); // Argument in eax is not a number.
7043 __ bind(&load_smi_edx);
7044 __ sar(edx, 1); // Untag smi before converting to float.
7045 __ cvtsi2sd(xmm0, Operand(edx));
7046 __ shl(edx, 1); // Retag smi for heap number overwriting test.
7047 __ jmp(&load_eax);
7048 __ bind(&load_smi_eax);
7049 __ sar(eax, 1); // Untag smi before converting to float.
7050 __ cvtsi2sd(xmm1, Operand(eax));
7051 __ shl(eax, 1); // Retag smi for heap number overwriting test.
7052 __ jmp(&done);
7053 __ bind(&load_float_eax);
7054 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
7055 __ bind(&done);
7056 }
7057
7058
6984 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 7059 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
6985 Register scratch) { 7060 Register scratch) {
6986 Label load_smi_1, load_smi_2, done_load_1, done; 7061 Label load_smi_1, load_smi_2, done_load_1, done;
6987 __ mov(scratch, Operand(esp, 2 * kPointerSize)); 7062 __ mov(scratch, Operand(esp, 2 * kPointerSize));
6988 __ test(scratch, Immediate(kSmiTagMask)); 7063 __ test(scratch, Immediate(kSmiTagMask));
6989 __ j(zero, &load_smi_1, not_taken); 7064 __ j(zero, &load_smi_1, not_taken);
6990 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); 7065 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
6991 __ bind(&done_load_1); 7066 __ bind(&done_load_1);
6992 7067
6993 __ mov(scratch, Operand(esp, 1 * kPointerSize)); 7068 __ mov(scratch, Operand(esp, 1 * kPointerSize));
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
7336 7411
7337 // Push arguments below the return address. 7412 // Push arguments below the return address.
7338 __ pop(ecx); 7413 __ pop(ecx);
7339 __ push(eax); 7414 __ push(eax);
7340 __ push(edx); 7415 __ push(edx);
7341 __ push(ecx); 7416 __ push(ecx);
7342 7417
7343 // Inlined floating point compare. 7418 // Inlined floating point compare.
7344 // Call builtin if operands are not floating point or smi. 7419 // Call builtin if operands are not floating point or smi.
7345 Label check_for_symbols; 7420 Label check_for_symbols;
7346 FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols, ebx); 7421 Label unordered;
7347 FloatingPointHelper::LoadFloatOperands(masm, ecx); 7422 if (CpuFeatures::IsSupported(CpuFeatures::SSE2)) {
7348 __ FCmp(); 7423 CpuFeatures::Scope use_sse2(CpuFeatures::SSE2);
7424 CpuFeatures::Scope use_cmov(CpuFeatures::CMOV);
7349 7425
7350 // Jump to builtin for NaN. 7426 FloatingPointHelper::LoadSse2Operands(masm, &check_for_symbols);
7351 __ j(parity_even, &call_builtin, not_taken); 7427 __ comisd(xmm0, xmm1);
7352 7428
7353 // TODO(1243847): Use cmov below once CpuFeatures are properly hooked up. 7429 // Jump to builtin for NaN.
7354 Label below_lbl, above_lbl; 7430 __ j(parity_even, &unordered, not_taken);
7355 // use edx, eax to convert unsigned to signed comparison 7431 __ mov(eax, 0); // equal
7356 __ j(below, &below_lbl, not_taken); 7432 __ mov(ecx, Immediate(Smi::FromInt(1)));
7357 __ j(above, &above_lbl, not_taken); 7433 __ cmov(above, eax, Operand(ecx));
7434 __ mov(ecx, Immediate(Smi::FromInt(-1)));
7435 __ cmov(below, eax, Operand(ecx));
7436 __ ret(2 * kPointerSize);
7437 } else {
7438 FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols, ebx);
7439 FloatingPointHelper::LoadFloatOperands(masm, ecx);
7440 __ FCmp();
7358 7441
7359 __ xor_(eax, Operand(eax)); // equal 7442 // Jump to builtin for NaN.
7360 __ ret(2 * kPointerSize); 7443 __ j(parity_even, &unordered, not_taken);
7361 7444
7362 __ bind(&below_lbl); 7445 Label below_lbl, above_lbl;
7363 __ mov(eax, -1); 7446 // Return a result of -1, 0, or 1, to indicate result of comparison.
7364 __ ret(2 * kPointerSize); 7447 __ j(below, &below_lbl, not_taken);
7448 __ j(above, &above_lbl, not_taken);
7365 7449
7366 __ bind(&above_lbl); 7450 __ xor_(eax, Operand(eax)); // equal
7367 __ mov(eax, 1); 7451 // Both arguments were pushed in case a runtime call was needed.
7452 __ ret(2 * kPointerSize);
7453
7454 __ bind(&below_lbl);
7455 __ mov(eax, Immediate(Smi::FromInt(-1)));
7456 __ ret(2 * kPointerSize);
7457
7458 __ bind(&above_lbl);
7459 __ mov(eax, Immediate(Smi::FromInt(1)));
7460 __ ret(2 * kPointerSize); // eax, edx were pushed
7461 }
7462 // If one of the numbers was NaN, then the result is always false.
7463 // The cc is never not-equal.
7464 __ bind(&unordered);
7465 ASSERT(cc_ != not_equal);
7466 if (cc_ == less || cc_ == less_equal) {
7467 __ mov(eax, Immediate(Smi::FromInt(1)));
7468 } else {
7469 __ mov(eax, Immediate(Smi::FromInt(-1)));
7470 }
7368 __ ret(2 * kPointerSize); // eax, edx were pushed 7471 __ ret(2 * kPointerSize); // eax, edx were pushed
7369 7472
7370 // Fast negative check for symbol-to-symbol equality. 7473 // Fast negative check for symbol-to-symbol equality.
7371 __ bind(&check_for_symbols); 7474 __ bind(&check_for_symbols);
7372 if (cc_ == equal) { 7475 if (cc_ == equal) {
7373 BranchIfNonSymbol(masm, &call_builtin, eax, ecx); 7476 BranchIfNonSymbol(masm, &call_builtin, eax, ecx);
7374 BranchIfNonSymbol(masm, &call_builtin, edx, ecx); 7477 BranchIfNonSymbol(masm, &call_builtin, edx, ecx);
7375 7478
7376 // We've already checked for object identity, so if both operands 7479 // We've already checked for object identity, so if both operands
7377 // are symbols they aren't equal. Register eax already holds a 7480 // are symbols they aren't equal. Register eax already holds a
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
7876 7979
7877 int CompareStub::MinorKey() { 7980 int CompareStub::MinorKey() {
7878 // Encode the two parameters in a unique 16 bit value. 7981 // Encode the two parameters in a unique 16 bit value.
7879 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7982 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7880 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7983 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7881 } 7984 }
7882 7985
7883 #undef __ 7986 #undef __
7884 7987
7885 } } // namespace v8::internal 7988 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698