Replaced unary negation by multiplication with -1.
This fixes a deopt loop in the Epic Citadel demo and removes some code. Apart from that, this change is performance-neutral. When we do something similar for BIT_NOT, the whole UnaryOp stuff can go away. R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/21782002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16029 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1e296936eb
commit
bf71023ba5
@ -4349,10 +4349,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SUB:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
|
||||
break;
|
||||
|
||||
case Token::BIT_NOT:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
|
||||
break;
|
||||
@ -4365,6 +4361,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
||||
const char* comment) {
|
||||
ASSERT_EQ(Token::BIT_NOT, expr->op());
|
||||
// TODO(svenpanne): Allowing format strings in Comment would be nice here...
|
||||
Comment cmt(masm_, comment);
|
||||
UnaryOpStub stub(expr->op());
|
||||
|
@ -804,6 +804,7 @@ Handle<Code> CompareNilICStub::GenerateCode() {
|
||||
template <>
|
||||
HValue* CodeStubGraphBuilder<UnaryOpStub>::BuildCodeInitializedStub() {
|
||||
UnaryOpStub* stub = casted_stub();
|
||||
ASSERT_EQ(Token::BIT_NOT, stub->operation());
|
||||
Handle<Type> type = stub->GetType(graph()->isolate());
|
||||
HValue* input = GetParameter(0);
|
||||
|
||||
|
@ -1718,33 +1718,14 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
|
||||
|
||||
HInstruction* HGraphBuilder::BuildUnaryMathOp(
|
||||
HValue* input, Handle<Type> type, Token::Value operation) {
|
||||
ASSERT_EQ(Token::BIT_NOT, operation);
|
||||
// We only handle the numeric cases here
|
||||
type = handle(
|
||||
Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
|
||||
|
||||
switch (operation) {
|
||||
default:
|
||||
UNREACHABLE();
|
||||
case Token::SUB: {
|
||||
HInstruction* instr =
|
||||
NewUncasted<HMul>(input, graph()->GetConstantMinus1());
|
||||
Representation rep = Representation::FromType(type);
|
||||
if (type->Is(Type::None())) {
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
if (instr->IsBinaryOperation()) {
|
||||
HBinaryOperation* binop = HBinaryOperation::cast(instr);
|
||||
binop->set_observed_input_representation(1, rep);
|
||||
binop->set_observed_input_representation(2, rep);
|
||||
}
|
||||
return instr;
|
||||
}
|
||||
case Token::BIT_NOT:
|
||||
if (type->Is(Type::None())) {
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
return New<HBitNot>(input);
|
||||
if (type->Is(Type::None())) {
|
||||
Add<HDeoptimize>(Deoptimizer::SOFT);
|
||||
}
|
||||
return New<HBitNot>(input);
|
||||
}
|
||||
|
||||
|
||||
@ -7220,7 +7201,6 @@ void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
case Token::DELETE: return VisitDelete(expr);
|
||||
case Token::VOID: return VisitVoid(expr);
|
||||
case Token::TYPEOF: return VisitTypeof(expr);
|
||||
case Token::SUB: return VisitSub(expr);
|
||||
case Token::BIT_NOT: return VisitBitNot(expr);
|
||||
case Token::NOT: return VisitNot(expr);
|
||||
default: UNREACHABLE();
|
||||
@ -7283,15 +7263,6 @@ void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
|
||||
CHECK_ALIVE(VisitForValue(expr->expression()));
|
||||
Handle<Type> operand_type = expr->expression()->bounds().lower;
|
||||
HValue* value = TruncateToNumber(Pop(), &operand_type);
|
||||
HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
|
||||
return ast_context()->ReturnInstruction(instr, expr->id());
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
|
||||
CHECK_ALIVE(VisitForValue(expr->expression()));
|
||||
Handle<Type> operand_type = expr->expression()->bounds().lower;
|
||||
|
@ -4347,10 +4347,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SUB:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
|
||||
break;
|
||||
|
||||
case Token::BIT_NOT:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
|
||||
break;
|
||||
@ -4363,6 +4359,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
||||
const char* comment) {
|
||||
ASSERT_EQ(Token::BIT_NOT, expr->op());
|
||||
Comment cmt(masm_, comment);
|
||||
UnaryOpStub stub(expr->op());
|
||||
// UnaryOpStub expects the argument to be in the
|
||||
|
@ -4382,10 +4382,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SUB:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
|
||||
break;
|
||||
|
||||
case Token::BIT_NOT:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
|
||||
break;
|
||||
@ -4398,6 +4394,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
||||
const char* comment) {
|
||||
ASSERT_EQ(Token::BIT_NOT, expr->op());
|
||||
// TODO(svenpanne): Allowing format strings in Comment would be nice here...
|
||||
Comment cmt(masm_, comment);
|
||||
UnaryOpStub stub(expr->op());
|
||||
|
@ -3197,6 +3197,13 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
||||
factory()->NewNumberLiteral(1),
|
||||
position);
|
||||
}
|
||||
// The same idea for '-foo' => 'foo*(-1)'.
|
||||
if (op == Token::SUB) {
|
||||
return factory()->NewBinaryOperation(Token::MUL,
|
||||
expression,
|
||||
factory()->NewNumberLiteral(-1),
|
||||
position);
|
||||
}
|
||||
|
||||
return factory()->NewUnaryOperation(op, expression, position);
|
||||
|
||||
|
@ -419,13 +419,6 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
case Token::VOID:
|
||||
NarrowType(expr, Bounds(Type::Undefined(), isolate_));
|
||||
break;
|
||||
case Token::ADD:
|
||||
case Token::SUB: {
|
||||
Type* upper = *expr->expression()->bounds().upper;
|
||||
if (!upper->Is(Type::Number())) upper = Type::Number();
|
||||
NarrowType(expr, Bounds(Type::Smi(), upper, isolate_));
|
||||
break;
|
||||
}
|
||||
case Token::BIT_NOT:
|
||||
NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
|
||||
break;
|
||||
|
@ -4335,10 +4335,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SUB:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
|
||||
break;
|
||||
|
||||
case Token::BIT_NOT:
|
||||
EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
|
||||
break;
|
||||
@ -4351,6 +4347,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
|
||||
const char* comment) {
|
||||
ASSERT_EQ(Token::BIT_NOT, expr->op());
|
||||
// TODO(svenpanne): Allowing format strings in Comment would be nice here...
|
||||
Comment cmt(masm_, comment);
|
||||
UnaryOpStub stub(expr->op());
|
||||
|
55
test/mjsunit/unary-minus-deopt.js
Normal file
55
test/mjsunit/unary-minus-deopt.js
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
// This is a boiled-down example happening in the Epic Citadel demo:
|
||||
// After deopting, the multiplication for unary minus stayed in Smi
|
||||
// mode instead of going to double mode, leading to deopt loops.
|
||||
|
||||
function unaryMinusTest(x) {
|
||||
var g = (1 << x) | 0;
|
||||
// Optimized code will contain a LMulI with -1 as right operand.
|
||||
return (g & -g) - 1 | 0;
|
||||
}
|
||||
|
||||
unaryMinusTest(3);
|
||||
unaryMinusTest(3);
|
||||
%OptimizeFunctionOnNextCall(unaryMinusTest);
|
||||
unaryMinusTest(3);
|
||||
assertOptimized(unaryMinusTest);
|
||||
|
||||
// Deopt on kMinInt
|
||||
unaryMinusTest(31);
|
||||
// The following is normally true, but not with --stress-opt. :-/
|
||||
// assertUnoptimized(unaryMinusTest);
|
||||
|
||||
// We should have learned something from the deopt.
|
||||
unaryMinusTest(31);
|
||||
%OptimizeFunctionOnNextCall(unaryMinusTest);
|
||||
unaryMinusTest(31);
|
||||
assertOptimized(unaryMinusTest);
|
Loading…
Reference in New Issue
Block a user