Index: src/compiler/simplified-lowering.cc |
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
index 9ce76688c9ad8df2686d10d6a230b60bac41b272..80ed7a61be8f83793cd33608f090bdbf209f2e73 100644 |
--- a/src/compiler/simplified-lowering.cc |
+++ b/src/compiler/simplified-lowering.cc |
@@ -398,6 +398,66 @@ class RepresentationSelector { |
break; |
} |
+ case IrOpcode::kSpeculativeNumberMultiply: { |
+ Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
+ Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
+ if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
+ // TODO(jarin) The ToNumber conversion is too conservative here, |
+ // e.g. it will treat true as 1 even though the number check will |
+ // fail on a boolean. OperationTyper should have a function that |
+ // computes a more precise type. |
+ lhs = op_typer_.ToNumber(lhs); |
+ rhs = op_typer_.ToNumber(rhs); |
+ Type* static_type = op_typer_.NumericMultiply(lhs, rhs); |
+ if (info->type_check() == TypeCheckKind::kNone) { |
+ new_type = static_type; |
+ } else { |
+ Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
+ new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
+ } |
+ break; |
+ } |
+ |
+ case IrOpcode::kSpeculativeNumberDivide: { |
+ Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
+ Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
+ if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
+ // TODO(jarin) The ToNumber conversion is too conservative here, |
+ // e.g. it will treat true as 1 even though the number check will |
+ // fail on a boolean. OperationTyper should have a function that |
+ // computes a more precise type. |
+ lhs = op_typer_.ToNumber(lhs); |
+ rhs = op_typer_.ToNumber(rhs); |
+ Type* static_type = op_typer_.NumericDivide(lhs, rhs); |
+ if (info->type_check() == TypeCheckKind::kNone) { |
+ new_type = static_type; |
+ } else { |
+ Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
+ new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
+ } |
+ break; |
+ } |
+ |
+ case IrOpcode::kSpeculativeNumberModulus: { |
+ Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
+ Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
+ if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
+ // TODO(jarin) The ToNumber conversion is too conservative here, |
+ // e.g. it will treat true as 1 even though the number check will |
+ // fail on a boolean. OperationTyper should have a function that |
+ // computes a more precise type. |
+ lhs = op_typer_.ToNumber(lhs); |
+ rhs = op_typer_.ToNumber(rhs); |
+ Type* static_type = op_typer_.NumericModulus(lhs, rhs); |
+ if (info->type_check() == TypeCheckKind::kNone) { |
+ new_type = static_type; |
+ } else { |
+ Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
+ new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
+ } |
+ break; |
+ } |
+ |
case IrOpcode::kPhi: { |
new_type = TypePhi(node); |
if (type != nullptr) { |
@@ -1003,10 +1063,7 @@ class RepresentationSelector { |
return jsgraph_->simplified(); |
} |
- void ChangeToPureOp(Node* node, const Operator* new_op) { |
- // Disconnect the node from effect and control chains. |
- Node* control = NodeProperties::GetControlInput(node); |
- Node* effect = NodeProperties::GetEffectInput(node); |
+ void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { |
for (Edge edge : node->use_edges()) { |
if (NodeProperties::IsControlEdge(edge)) { |
edge.UpdateTo(control); |
@@ -1016,21 +1073,21 @@ class RepresentationSelector { |
DCHECK(NodeProperties::IsValueEdge(edge)); |
} |
} |
- |
- node->TrimInputCount(new_op->ValueInputCount()); |
- NodeProperties::ChangeOp(node, new_op); |
} |
- void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { |
- for (Edge edge : node->use_edges()) { |
- if (NodeProperties::IsControlEdge(edge)) { |
- edge.UpdateTo(control); |
- } else if (NodeProperties::IsEffectEdge(edge)) { |
- edge.UpdateTo(effect); |
- } else { |
- DCHECK(NodeProperties::IsValueEdge(edge)); |
- } |
+ void ChangeToPureOp(Node* node, const Operator* new_op) { |
+ if (node->op()->EffectInputCount() > 0) { |
+ DCHECK_LT(0, node->op()->ControlInputCount()); |
+ // Disconnect the node from effect and control chains. |
+ Node* control = NodeProperties::GetControlInput(node); |
+ Node* effect = NodeProperties::GetEffectInput(node); |
+ ReplaceEffectControlUses(node, effect, control); |
+ node->TrimInputCount(new_op->ValueInputCount()); |
+ } else { |
+ DCHECK_EQ(0, node->op()->ControlInputCount()); |
} |
+ |
+ NodeProperties::ChangeOp(node, new_op); |
} |
void ChangeToInt32OverflowOp(Node* node, const Operator* op) { |
@@ -1295,13 +1352,14 @@ class RepresentationSelector { |
} |
return; |
} |
+ case IrOpcode::kSpeculativeNumberMultiply: |
case IrOpcode::kNumberMultiply: { |
if (BothInputsAreSigned32(node)) { |
if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
// Multiply reduces to Int32Mul if the inputs and the output |
// are integers. |
VisitInt32Binop(node); |
- if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
+ if (lower()) ChangeToPureOp(node, Int32Op(node)); |
return; |
} |
if (truncation.TruncatesToWord32() && |
@@ -1310,15 +1368,24 @@ class RepresentationSelector { |
// the uses are truncating and the result is in the safe |
// integer range. |
VisitWord32TruncatingBinop(node); |
- if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
+ if (lower()) ChangeToPureOp(node, Int32Op(node)); |
return; |
} |
} |
- // => Float64Mul |
- VisitFloat64Binop(node); |
- if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
+ // Number x Number => Float64Mul |
+ if (BothInputsAre(node, Type::NumberOrUndefined())) { |
+ VisitFloat64Binop(node); |
+ if (lower()) ChangeToPureOp(node, Float64Op(node)); |
+ return; |
+ } |
+ // Checked float64 x float64 => float64 |
+ DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); |
+ VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
+ MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
+ if (lower()) ChangeToPureOp(node, Float64Op(node)); |
return; |
} |
+ case IrOpcode::kSpeculativeNumberDivide: |
case IrOpcode::kNumberDivide: { |
if (BothInputsAreSigned32(node)) { |
if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
@@ -1340,11 +1407,20 @@ class RepresentationSelector { |
if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); |
return; |
} |
- // => Float64Div |
- VisitFloat64Binop(node); |
- if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
+ // Number x Number => Float64Div |
+ if (BothInputsAre(node, Type::NumberOrUndefined())) { |
+ VisitFloat64Binop(node); |
+ if (lower()) ChangeToPureOp(node, Float64Op(node)); |
+ return; |
+ } |
+ // Checked float64 x float64 => float64 |
+ DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); |
+ VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
+ MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
+ if (lower()) ChangeToPureOp(node, Float64Op(node)); |
return; |
} |
+ case IrOpcode::kSpeculativeNumberModulus: |
case IrOpcode::kNumberModulus: { |
if (BothInputsAreSigned32(node)) { |
if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
@@ -1366,9 +1442,18 @@ class RepresentationSelector { |
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
return; |
} |
- // => Float64Mod |
- VisitFloat64Binop(node); |
- if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
+ // Number x Number => Float64Mod |
+ if (BothInputsAre(node, Type::NumberOrUndefined())) { |
+ // => Float64Mod |
+ VisitFloat64Binop(node); |
+ if (lower()) ChangeToPureOp(node, Float64Op(node)); |
+ return; |
+ } |
+ // Checked float64 x float64 => float64 |
+ DCHECK_EQ(IrOpcode::kSpeculativeNumberModulus, node->opcode()); |
+ VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
+ MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
+ if (lower()) ChangeToPureOp(node, Float64Op(node)); |
return; |
} |
case IrOpcode::kNumberBitwiseOr: |
@@ -1933,6 +2018,17 @@ class RepresentationSelector { |
node->op()->mnemonic(), replacement->id(), |
replacement->op()->mnemonic()); |
+ // Disconnect the node from effect and control chains, if necessary. |
+ if (node->op()->EffectInputCount() > 0) { |
+ DCHECK_LT(0, node->op()->ControlInputCount()); |
+ // Disconnect the node from effect and control chains. |
+ Node* control = NodeProperties::GetControlInput(node); |
+ Node* effect = NodeProperties::GetEffectInput(node); |
+ ReplaceEffectControlUses(node, effect, control); |
+ } else { |
+ DCHECK_EQ(0, node->op()->ControlInputCount()); |
+ } |
+ |
if (replacement->id() < count_ && |
GetUpperBound(node)->Is(GetUpperBound(replacement)) && |
TypeOf(node)->Is(TypeOf(replacement))) { |