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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/codegen-ia32.cc
===================================================================
--- src/ia32/codegen-ia32.cc (revision 2860)
+++ src/ia32/codegen-ia32.cc (working copy)
@@ -768,6 +768,11 @@
static void CheckFloatOperands(MacroAssembler* masm,
Label* non_float,
Register scratch);
+ // Test if operands are numbers (smi or HeapNumber objects), and load
+ // them into xmm0 and xmm1 if they are. Jump to label not_numbers if
+ // either operand is not a number. Operands are in edx and eax.
+ // Leaves operands unchanged.
+ static void LoadSse2Operands(MacroAssembler* masm, Label* not_numbers);
// Allocate a heap number in new space with undefined value.
// Returns tagged pointer in eax, or jumps to need_gc if new space is full.
static void AllocateHeapNumber(MacroAssembler* masm,
@@ -6699,41 +6704,79 @@
case Token::DIV: {
// eax: y
// edx: x
- FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
- // Fast-case: Both operands are numbers.
- // Allocate a heap number, if needed.
- Label skip_allocation;
- switch (mode_) {
- case OVERWRITE_LEFT:
- __ mov(eax, Operand(edx));
- // Fall through!
- case OVERWRITE_RIGHT:
- // If the argument in eax is already an object, we skip the
- // allocation of a heap number.
- __ test(eax, Immediate(kSmiTagMask));
- __ j(not_zero, &skip_allocation, not_taken);
- // Fall through!
- case NO_OVERWRITE:
- FloatingPointHelper::AllocateHeapNumber(masm,
- &call_runtime,
- ecx,
- edx,
- eax);
- __ bind(&skip_allocation);
- break;
- default: UNREACHABLE();
- }
- FloatingPointHelper::LoadFloatOperands(masm, ecx);
- switch (op_) {
- case Token::ADD: __ faddp(1); break;
- case Token::SUB: __ fsubp(1); break;
- case Token::MUL: __ fmulp(1); break;
- case Token::DIV: __ fdivp(1); break;
- default: UNREACHABLE();
+ if (CpuFeatures::IsSupported(CpuFeatures::SSE2)) {
+ CpuFeatures::Scope use_sse2(CpuFeatures::SSE2);
+ FloatingPointHelper::LoadSse2Operands(masm, &call_runtime);
+
+ switch (op_) {
+ case Token::ADD: __ addsd(xmm0, xmm1); break;
+ case Token::SUB: __ subsd(xmm0, xmm1); break;
+ case Token::MUL: __ mulsd(xmm0, xmm1); break;
+ case Token::DIV: __ divsd(xmm0, xmm1); break;
+ default: UNREACHABLE();
+ }
+ // Allocate a heap number, if needed.
+ Label skip_allocation;
+ switch (mode_) {
+ case OVERWRITE_LEFT:
+ __ mov(eax, Operand(edx));
+ // Fall through!
+ case OVERWRITE_RIGHT:
+ // If the argument in eax is already an object, we skip the
+ // allocation of a heap number.
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(not_zero, &skip_allocation, not_taken);
+ // Fall through!
+ case NO_OVERWRITE:
+ FloatingPointHelper::AllocateHeapNumber(masm,
+ &call_runtime,
+ ecx,
+ edx,
+ eax);
+ __ bind(&skip_allocation);
+ break;
+ default: UNREACHABLE();
+ }
+ __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
+ __ ret(2 * kPointerSize);
+
+ } else { // SSE2 not available, use FPU.
+ 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
+ // 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
+ Label skip_allocation;
+ switch (mode_) {
+ case OVERWRITE_LEFT:
+ __ mov(eax, Operand(edx));
+ // Fall through!
+ case OVERWRITE_RIGHT:
+ // If the argument in eax is already an object, we skip the
+ // allocation of a heap number.
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(not_zero, &skip_allocation, not_taken);
+ // Fall through!
+ case NO_OVERWRITE:
+ FloatingPointHelper::AllocateHeapNumber(masm,
+ &call_runtime,
+ ecx,
+ edx,
+ eax);
+ __ bind(&skip_allocation);
+ break;
+ default: UNREACHABLE();
+ }
+ FloatingPointHelper::LoadFloatOperands(masm, ecx);
+
+ switch (op_) {
+ case Token::ADD: __ faddp(1); break;
+ case Token::SUB: __ fsubp(1); break;
+ case Token::MUL: __ fmulp(1); break;
+ case Token::DIV: __ fdivp(1); break;
+ default: UNREACHABLE();
+ }
+ __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
+ __ ret(2 * kPointerSize);
}
- __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
- __ ret(2 * kPointerSize);
}
case Token::MOD: {
// For MOD we go directly to runtime in the non-smi case.
@@ -6981,6 +7024,38 @@
}
+void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm,
+ Label* not_numbers) {
+ Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
+ // Load operand in edx into xmm0, or branch to not_numbers.
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
+ __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map());
+ __ j(not_equal, not_numbers); // Argument in edx is not a number.
+ __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
+ __ bind(&load_eax);
+ // Load operand in eax into xmm1, or branch to not_numbers.
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
+ __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map());
+ __ j(equal, &load_float_eax);
+ __ jmp(not_numbers); // Argument in eax is not a number.
+ __ bind(&load_smi_edx);
+ __ sar(edx, 1); // Untag smi before converting to float.
+ __ cvtsi2sd(xmm0, Operand(edx));
+ __ shl(edx, 1); // Retag smi for heap number overwriting test.
+ __ jmp(&load_eax);
+ __ bind(&load_smi_eax);
+ __ sar(eax, 1); // Untag smi before converting to float.
+ __ cvtsi2sd(xmm1, Operand(eax));
+ __ shl(eax, 1); // Retag smi for heap number overwriting test.
+ __ jmp(&done);
+ __ bind(&load_float_eax);
+ __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ bind(&done);
+}
+
+
void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
Register scratch) {
Label load_smi_1, load_smi_2, done_load_1, done;
@@ -7343,28 +7418,56 @@
// Inlined floating point compare.
// Call builtin if operands are not floating point or smi.
Label check_for_symbols;
- FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols, ebx);
- FloatingPointHelper::LoadFloatOperands(masm, ecx);
- __ FCmp();
+ Label unordered;
+ if (CpuFeatures::IsSupported(CpuFeatures::SSE2)) {
+ CpuFeatures::Scope use_sse2(CpuFeatures::SSE2);
+ CpuFeatures::Scope use_cmov(CpuFeatures::CMOV);
- // Jump to builtin for NaN.
- __ j(parity_even, &call_builtin, not_taken);
+ FloatingPointHelper::LoadSse2Operands(masm, &check_for_symbols);
+ __ comisd(xmm0, xmm1);
- // TODO(1243847): Use cmov below once CpuFeatures are properly hooked up.
- Label below_lbl, above_lbl;
- // use edx, eax to convert unsigned to signed comparison
- __ j(below, &below_lbl, not_taken);
- __ j(above, &above_lbl, not_taken);
+ // Jump to builtin for NaN.
+ __ j(parity_even, &unordered, not_taken);
+ __ mov(eax, 0); // equal
+ __ mov(ecx, Immediate(Smi::FromInt(1)));
+ __ cmov(above, eax, Operand(ecx));
+ __ mov(ecx, Immediate(Smi::FromInt(-1)));
+ __ cmov(below, eax, Operand(ecx));
+ __ ret(2 * kPointerSize);
+ } else {
+ FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols, ebx);
+ FloatingPointHelper::LoadFloatOperands(masm, ecx);
+ __ FCmp();
- __ xor_(eax, Operand(eax)); // equal
- __ ret(2 * kPointerSize);
+ // Jump to builtin for NaN.
+ __ j(parity_even, &unordered, not_taken);
- __ bind(&below_lbl);
- __ mov(eax, -1);
- __ ret(2 * kPointerSize);
+ Label below_lbl, above_lbl;
+ // Return a result of -1, 0, or 1, to indicate result of comparison.
+ __ j(below, &below_lbl, not_taken);
+ __ j(above, &above_lbl, not_taken);
- __ bind(&above_lbl);
- __ mov(eax, 1);
+ __ xor_(eax, Operand(eax)); // equal
+ // Both arguments were pushed in case a runtime call was needed.
+ __ ret(2 * kPointerSize);
+
+ __ bind(&below_lbl);
+ __ mov(eax, Immediate(Smi::FromInt(-1)));
+ __ ret(2 * kPointerSize);
+
+ __ bind(&above_lbl);
+ __ mov(eax, Immediate(Smi::FromInt(1)));
+ __ ret(2 * kPointerSize); // eax, edx were pushed
+ }
+ // If one of the numbers was NaN, then the result is always false.
+ // The cc is never not-equal.
+ __ bind(&unordered);
+ ASSERT(cc_ != not_equal);
+ if (cc_ == less || cc_ == less_equal) {
+ __ mov(eax, Immediate(Smi::FromInt(1)));
+ } else {
+ __ mov(eax, Immediate(Smi::FromInt(-1)));
+ }
__ ret(2 * kPointerSize); // eax, edx were pushed
// Fast negative check for symbol-to-symbol equality.
« 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