Revision: 3487 Author: [email protected] Date: Thu Dec 17 22:38:12 2009 Log: -Inlined double variant of compare iff one of the sides is a constant smi and it is not a for loop condition.
Review URL: http://codereview.chromium.org/507040 http://code.google.com/p/v8/source/detail?r=3487 Modified: /branches/bleeding_edge/src/ast.h /branches/bleeding_edge/src/compiler.cc /branches/bleeding_edge/src/ia32/assembler-ia32.cc /branches/bleeding_edge/src/ia32/assembler-ia32.h /branches/bleeding_edge/src/ia32/codegen-ia32.cc /branches/bleeding_edge/src/ia32/codegen-ia32.h /branches/bleeding_edge/src/ia32/disasm-ia32.cc /branches/bleeding_edge/src/parser.cc ======================================= --- /branches/bleeding_edge/src/ast.h Wed Dec 16 22:21:50 2009 +++ /branches/bleeding_edge/src/ast.h Thu Dec 17 22:38:12 2009 @@ -139,6 +139,7 @@ virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; } virtual ObjectLiteral* AsObjectLiteral() { return NULL; } virtual ArrayLiteral* AsArrayLiteral() { return NULL; } + virtual CompareOperation* AsCompareOperation() { return NULL; } }; @@ -1185,7 +1186,7 @@ class CompareOperation: public Expression { public: CompareOperation(Token::Value op, Expression* left, Expression* right) - : op_(op), left_(left), right_(right) { + : op_(op), left_(left), right_(right), is_for_loop_condition_(false) { ASSERT(Token::IsCompareOp(op)); } @@ -1194,11 +1195,19 @@ Token::Value op() const { return op_; } Expression* left() const { return left_; } Expression* right() const { return right_; } + + // Accessors for flag whether this compare operation is hanging of a for loop. + bool is_for_loop_condition() const { return is_for_loop_condition_; } + void set_is_for_loop_condition() { is_for_loop_condition_ = true; } + + // Type testing & conversion + virtual CompareOperation* AsCompareOperation() { return this; } private: Token::Value op_; Expression* left_; Expression* right_; + bool is_for_loop_condition_; }; ======================================= --- /branches/bleeding_edge/src/compiler.cc Wed Dec 16 01:51:07 2009 +++ /branches/bleeding_edge/src/compiler.cc Thu Dec 17 22:38:12 2009 @@ -1101,9 +1101,9 @@ void CodeGenSelector::VisitCompareOperation(CompareOperation* expr) { - ProcessExpression(expr->left(), Expression::kValue); - CHECK_BAILOUT; - ProcessExpression(expr->right(), Expression::kValue); + ProcessExpression(expr->left(), Expression::kValue); + CHECK_BAILOUT; + ProcessExpression(expr->right(), Expression::kValue); } ======================================= --- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Tue Nov 17 00:35:43 2009 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Thu Dec 17 22:38:12 2009 @@ -2002,6 +2002,17 @@ EMIT(0x5E); emit_sse_operand(dst, src); } + + +void Assembler::xorpd(XMMRegister dst, XMMRegister src) { + ASSERT(CpuFeatures::IsEnabled(SSE2)); + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0x66); + EMIT(0x0F); + EMIT(0x57); + emit_sse_operand(dst, src); +} void Assembler::comisd(XMMRegister dst, XMMRegister src) { ======================================= --- /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Dec 10 04:52:28 2009 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Dec 17 22:38:12 2009 @@ -745,6 +745,7 @@ void subsd(XMMRegister dst, XMMRegister src); void mulsd(XMMRegister dst, XMMRegister src); void divsd(XMMRegister dst, XMMRegister src); + void xorpd(XMMRegister dst, XMMRegister src); void comisd(XMMRegister dst, XMMRegister src); ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Dec 17 17:43:50 2009 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Dec 17 22:38:12 2009 @@ -1865,7 +1865,8 @@ } -void CodeGenerator::Comparison(Condition cc, +void CodeGenerator::Comparison(AstNode* node, + Condition cc, bool strict, ControlDestination* dest) { // Strict only makes sense for equality comparisons. @@ -1912,7 +1913,8 @@ default: UNREACHABLE(); } - } else { // Only one side is a constant Smi. + } else { + // Only one side is a constant Smi. // If left side is a constant Smi, reverse the operands. // Since one side is a constant Smi, conversion order does not matter. if (left_side_constant_smi) { @@ -1926,6 +1928,8 @@ // Implement comparison against a constant Smi, inlining the case // where both sides are Smis. left_side.ToRegister(); + Register left_reg = left_side.reg(); + Handle<Object> right_val = right_side.handle(); // Here we split control flow to the stub call and inlined cases // before finally splitting it to the control destination. We use @@ -1933,10 +1937,49 @@ // the first split. We manually handle the off-frame references // by reconstituting them on the non-fall-through path. JumpTarget is_smi; - Register left_reg = left_side.reg(); - Handle<Object> right_val = right_side.handle(); __ test(left_side.reg(), Immediate(kSmiTagMask)); is_smi.Branch(zero, taken); + + bool is_for_loop_compare = (node->AsCompareOperation() != NULL) + && node->AsCompareOperation()->is_for_loop_condition(); + if (!is_for_loop_compare + && CpuFeatures::IsSupported(SSE2) + && right_val->IsSmi()) { + // Right side is a constant smi and left side has been checked + // not to be a smi. + CpuFeatures::Scope use_sse2(SSE2); + JumpTarget not_number; + __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset), + Immediate(Factory::heap_number_map())); + not_number.Branch(not_equal, &left_side); + __ movdbl(xmm1, + FieldOperand(left_reg, HeapNumber::kValueOffset)); + int value = Smi::cast(*right_val)->value(); + if (value == 0) { + __ xorpd(xmm0, xmm0); + } else { + Result temp = allocator()->Allocate(); + __ mov(temp.reg(), Immediate(value)); + __ cvtsi2sd(xmm0, Operand(temp.reg())); + temp.Unuse(); + } + __ comisd(xmm1, xmm0); + // Jump to builtin for NaN. + not_number.Branch(parity_even, &left_side); + left_side.Unuse(); + Condition double_cc = cc; + switch (cc) { + case less: double_cc = below; break; + case equal: double_cc = equal; break; + case less_equal: double_cc = below_equal; break; + case greater: double_cc = above; break; + case greater_equal: double_cc = above_equal; break; + default: UNREACHABLE(); + } + dest->true_target()->Branch(double_cc); + dest->false_target()->Jump(); + not_number.Bind(&left_side); + } // Setup and call the compare stub. CompareStub stub(cc, strict); @@ -1961,6 +2004,7 @@ right_side.Unuse(); dest->Split(cc); } + } else if (cc == equal && (left_side_constant_null || right_side_constant_null)) { // To make null checks efficient, we check if either the left side or @@ -1997,7 +2041,8 @@ operand.Unuse(); dest->Split(not_zero); } - } else { // Neither side is a constant Smi or null. + } else { + // Neither side is a constant Smi or null. // If either side is a non-smi constant, skip the smi check. bool known_non_smi = (left_side.is_constant() && !left_side.handle()->IsSmi()) || @@ -2664,7 +2709,7 @@ // Compare and branch to the body if true or the next test if // false. Prefer the next test as a fall through. ControlDestination dest(clause->body_target(), &next_test, false); - Comparison(equal, true, &dest); + Comparison(node, equal, true, &dest); // If the comparison fell through to the true target, jump to the // actual body. @@ -6077,7 +6122,7 @@ } Load(left); Load(right); - Comparison(cc, strict, destination()); + Comparison(node, cc, strict, destination()); } ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.h Wed Dec 16 22:21:50 2009 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Thu Dec 17 22:38:12 2009 @@ -459,7 +459,8 @@ Result* right, OverwriteMode overwrite_mode); - void Comparison(Condition cc, + void Comparison(AstNode* node, + Condition cc, bool strict, ControlDestination* destination); @@ -727,8 +728,8 @@ bool ArgsInRegistersSupported() { return ((op_ == Token::ADD) || (op_ == Token::SUB) - || (op_ == Token::MUL) || (op_ == Token::DIV)) - && flags_ != NO_SMI_CODE_IN_STUB; + || (op_ == Token::MUL) || (op_ == Token::DIV)) + && flags_ != NO_SMI_CODE_IN_STUB; } bool IsOperationCommutative() { return (op_ == Token::ADD) || (op_ == Token::MUL); ======================================= --- /branches/bleeding_edge/src/ia32/disasm-ia32.cc Tue Nov 17 02:24:27 2009 +++ /branches/bleeding_edge/src/ia32/disasm-ia32.cc Thu Dec 17 22:38:12 2009 @@ -1049,6 +1049,14 @@ NameOfXMMRegister(regop), NameOfXMMRegister(rm)); data++; + } if (*data == 0x57) { + data++; + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &rm); + AppendToBuffer("xorpd %s,%s", + NameOfXMMRegister(regop), + NameOfXMMRegister(rm)); + data++; } else { UnimplementedInstruction(); } ======================================= --- /branches/bleeding_edge/src/parser.cc Mon Nov 16 13:59:31 2009 +++ /branches/bleeding_edge/src/parser.cc Thu Dec 17 22:38:12 2009 @@ -2657,6 +2657,9 @@ Expression* cond = NULL; if (peek() != Token::SEMICOLON) { cond = ParseExpression(true, CHECK_OK); + if (cond && cond->AsCompareOperation()) { + cond->AsCompareOperation()->set_is_for_loop_condition(); + } } Expect(Token::SEMICOLON, CHECK_OK); -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev
