Add support for unary plus in hydrogen compiler.

Also strength-reduction of unary minus.
Fixes issue 1248.

BUG=1248

Review URL: http://codereview.chromium.org/6685045

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7217 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2011-03-17 10:37:29 +00:00
parent 1a343b3004
commit 2038178fbe
2 changed files with 55 additions and 11 deletions

View File

@ -4552,7 +4552,13 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
VisitForEffect(expr->expression());
}
} else if (op == Token::BIT_NOT || op == Token::SUB) {
} else if (op == Token::TYPEOF) {
VisitForTypeOf(expr->expression());
if (HasStackOverflow()) return;
HValue* value = Pop();
ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
} else {
VISIT_FOR_VALUE(expr->expression());
HValue* value = Pop();
HInstruction* instr = NULL;
@ -4561,20 +4567,16 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
instr = new HBitNot(value);
break;
case Token::SUB:
instr = new HMul(graph_->GetConstantMinus1(), value);
instr = new HMul(value, graph_->GetConstantMinus1());
break;
case Token::ADD:
instr = new HMul(value, graph_->GetConstant1());
break;
default:
UNREACHABLE();
BAILOUT("Value: unsupported unary operation");
break;
}
ast_context()->ReturnInstruction(instr, expr->id());
} else if (op == Token::TYPEOF) {
VisitForTypeOf(expr->expression());
if (HasStackOverflow()) return;
HValue* value = Pop();
ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
} else {
BAILOUT("Value: unsupported unary operation");
}
}

View File

@ -893,7 +893,49 @@ void LCodeGen::DoMulI(LMulI* instr) {
}
if (right->IsConstantOperand()) {
__ imul(left, left, ToInteger32(LConstantOperand::cast(right)));
// Try strength reductions on the multiplication.
// All replacement instructions are at most as long as the imul
// and have better latency.
int constant = ToInteger32(LConstantOperand::cast(right));
if (constant == -1) {
__ neg(left);
} else if (constant == 0) {
__ xor_(left, Operand(left));
} else if (constant == 2) {
__ add(left, Operand(left));
} else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
// If we know that the multiplication can't overflow, it's safe to
// use instructions that don't set the overflow flag for the
// multiplication.
switch (constant) {
case 1:
// Do nothing.
break;
case 3:
__ lea(left, Operand(left, left, times_2, 0));
break;
case 4:
__ shl(left, 2);
break;
case 5:
__ lea(left, Operand(left, left, times_4, 0));
break;
case 8:
__ shl(left, 3);
break;
case 9:
__ lea(left, Operand(left, left, times_8, 0));
break;
case 16:
__ shl(left, 4);
break;
default:
__ imul(left, left, constant);
break;
}
} else {
__ imul(left, left, constant);
}
} else {
__ imul(left, ToOperand(right));
}