Chromium Code Reviews| Index: src/compiler/simplified-lowering.cc |
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
| index cc7279ece0a0b3d2443d1188936e5eea22dde1ed..654698549028970d0cc94bbcb853b7db236db4fb 100644 |
| --- a/src/compiler/simplified-lowering.cc |
| +++ b/src/compiler/simplified-lowering.cc |
| @@ -183,7 +183,7 @@ class InputUseInfos { |
| class RepresentationSelector { |
| public: |
| // Information for each node tracked during the fixpoint. |
| - class NodeInfo { |
| + class NodeInfo final { |
| public: |
| // Adds new use to the node. Returns true if something has changed |
| // and the node has to be requeued. |
| @@ -207,11 +207,11 @@ class RepresentationSelector { |
| // Helpers for feedback typing. |
| void set_feedback_type(Type* type) { feedback_type_ = type; } |
| - Type* feedback_type() { return feedback_type_; } |
| + Type* feedback_type() const { return feedback_type_; } |
| void set_weakened() { weakened_ = true; } |
| - bool weakened() { return weakened_; } |
| - TypeCheckKind type_check() { return type_check_; } |
| - void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; } |
| + bool weakened() const { return weakened_; } |
| + void set_restriction_type(Type* type) { restriction_type_ = type; } |
| + Type* restriction_type() const { return restriction_type_; } |
| private: |
| enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; |
| @@ -219,8 +219,8 @@ class RepresentationSelector { |
| MachineRepresentation representation_ = |
| MachineRepresentation::kNone; // Output representation. |
| Truncation truncation_ = Truncation::None(); // Information about uses. |
| - TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind. |
| + Type* restriction_type_ = Type::Any(); |
| Type* feedback_type_ = nullptr; |
| bool weakened_ = false; |
| }; |
| @@ -343,23 +343,6 @@ class RepresentationSelector { |
| FeedbackTypeOf(node->InputAt(2))); |
| } |
| - static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) { |
| - switch (type_check) { |
| - case TypeCheckKind::kNone: |
| - return Type::Any(); |
| - case TypeCheckKind::kSigned32: |
| - return Type::Signed32(); |
| - case TypeCheckKind::kNumber: |
| - return Type::Number(); |
| - // Unexpected cases. |
| - case TypeCheckKind::kNumberOrUndefined: |
| - FATAL("Unexpected checked type."); |
| - break; |
| - } |
| - UNREACHABLE(); |
| - return nullptr; |
| - } |
| - |
| bool UpdateFeedbackType(Node* node) { |
| if (node->op()->ValueOutputCount() == 0) return false; |
| @@ -379,6 +362,7 @@ class RepresentationSelector { |
| } |
| switch (node->opcode()) { |
| + case IrOpcode::kNumberAdd: |
| case IrOpcode::kSpeculativeNumberAdd: { |
| // TODO(jarin) The ToNumber conversion is too conservative here, |
| // e.g. it will treat true as 1 even though the number check will |
| @@ -386,16 +370,13 @@ class RepresentationSelector { |
| // computes a more precise type. |
| Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| - Type* static_type = op_typer_.NumberAdd(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()); |
| - } |
| + Type* computed_type = op_typer_.NumberAdd(lhs, rhs); |
| + new_type = Type::Intersect(computed_type, info->restriction_type(), |
| + graph_zone()); |
| break; |
| } |
| + case IrOpcode::kNumberSubtract: |
| case IrOpcode::kSpeculativeNumberSubtract: { |
| // TODO(jarin) The ToNumber conversion is too conservative here, |
| // e.g. it will treat true as 1 even though the number check will |
| @@ -403,16 +384,13 @@ class RepresentationSelector { |
| // computes a more precise type. |
| Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| - Type* static_type = op_typer_.NumberSubtract(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()); |
| - } |
| + Type* computed_type = op_typer_.NumberSubtract(lhs, rhs); |
| + new_type = Type::Intersect(computed_type, info->restriction_type(), |
| + graph_zone()); |
| break; |
| } |
| + case IrOpcode::kNumberMultiply: |
| case IrOpcode::kSpeculativeNumberMultiply: { |
| // TODO(jarin) The ToNumber conversion is too conservative here, |
| // e.g. it will treat true as 1 even though the number check will |
| @@ -420,16 +398,13 @@ class RepresentationSelector { |
| // computes a more precise type. |
| Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| - Type* static_type = op_typer_.NumberMultiply(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()); |
| - } |
| + Type* computed_type = op_typer_.NumberMultiply(lhs, rhs); |
| + new_type = Type::Intersect(computed_type, info->restriction_type(), |
| + graph_zone()); |
| break; |
| } |
| + case IrOpcode::kNumberDivide: |
| case IrOpcode::kSpeculativeNumberDivide: { |
| // TODO(jarin) The ToNumber conversion is too conservative here, |
| // e.g. it will treat true as 1 even though the number check will |
| @@ -437,16 +412,13 @@ class RepresentationSelector { |
| // computes a more precise type. |
| Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| - Type* static_type = op_typer_.NumberDivide(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()); |
| - } |
| + Type* computed_type = op_typer_.NumberDivide(lhs, rhs); |
| + new_type = Type::Intersect(computed_type, info->restriction_type(), |
| + graph_zone()); |
| break; |
| } |
| + case IrOpcode::kNumberModulus: |
| case IrOpcode::kSpeculativeNumberModulus: { |
| // TODO(jarin) The ToNumber conversion is too conservative here, |
| // e.g. it will treat true as 1 even though the number check will |
| @@ -454,13 +426,9 @@ class RepresentationSelector { |
| // computes a more precise type. |
| Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| - Type* static_type = op_typer_.NumberModulus(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()); |
| - } |
| + Type* computed_type = op_typer_.NumberModulus(lhs, rhs); |
| + new_type = Type::Intersect(computed_type, info->restriction_type(), |
| + graph_zone()); |
| break; |
| } |
| @@ -657,30 +625,25 @@ class RepresentationSelector { |
| bool propagate() const { return phase_ == PROPAGATE; } |
| void SetOutput(Node* node, MachineRepresentation representation, |
| - TypeCheckKind type_check = TypeCheckKind::kNone) { |
| + Type* restriction_type = Type::Any()) { |
| NodeInfo* const info = GetInfo(node); |
| switch (phase_) { |
| case PROPAGATE: |
| - info->set_type_check(type_check); |
| + info->set_restriction_type(restriction_type); |
| break; |
| case RETYPE: |
| - DCHECK_EQ(info->type_check(), type_check); |
| + DCHECK(info->restriction_type()->Is(restriction_type)); |
| + DCHECK(restriction_type->Is(info->restriction_type())); |
| info->set_output(representation); |
| break; |
| case LOWER: |
| - DCHECK_EQ(info->type_check(), type_check); |
| DCHECK_EQ(info->representation(), representation); |
| + DCHECK(info->restriction_type()->Is(restriction_type)); |
| + DCHECK(restriction_type->Is(info->restriction_type())); |
| break; |
| } |
| } |
| - void ResetOutput(Node* node, MachineRepresentation representation, |
| - TypeCheckKind type_check = TypeCheckKind::kNone) { |
| - NodeInfo* info = GetInfo(node); |
| - info->set_output(representation); |
| - info->set_type_check(type_check); |
| - } |
| - |
| Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } |
| bool InputCannotBe(Node* node, Type* type) { |
| @@ -777,20 +740,20 @@ class RepresentationSelector { |
| // Helper for binops of the R x L -> O variety. |
| void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, |
| MachineRepresentation output, |
| - TypeCheckKind type_check = TypeCheckKind::kNone) { |
| + Type* restriction_type = Type::Any()) { |
| DCHECK_EQ(2, node->op()->ValueInputCount()); |
| ProcessInput(node, 0, left_use); |
| ProcessInput(node, 1, right_use); |
| for (int i = 2; i < node->InputCount(); i++) { |
| EnqueueInput(node, i); |
| } |
| - SetOutput(node, output, type_check); |
| + SetOutput(node, output, restriction_type); |
| } |
| // Helper for binops of the I x I -> O variety. |
| void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, |
| - TypeCheckKind type_check = TypeCheckKind::kNone) { |
| - VisitBinop(node, input_use, input_use, output, type_check); |
| + Type* restriction_type = Type::Any()) { |
| + VisitBinop(node, input_use, input_use, output, restriction_type); |
| } |
| // Helper for unops of the I -> O variety. |
| @@ -1006,6 +969,10 @@ class RepresentationSelector { |
| return changer_->Uint32OperatorFor(node->opcode()); |
| } |
| + const Operator* Uint32OverflowOp(Node* node) { |
| + return changer_->Uint32OverflowOperatorFor(node->opcode()); |
| + } |
| + |
| const Operator* Float64Op(Node* node) { |
| return changer_->Float64OperatorFor(node->opcode()); |
| } |
| @@ -1108,8 +1075,12 @@ class RepresentationSelector { |
| NodeProperties::ChangeOp(node, new_op); |
| } |
| - void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) { |
| - NodeProperties::ChangeOp(node, new_op); |
| + void ChangeToInt32OverflowOp(Node* node) { |
| + NodeProperties::ChangeOp(node, Int32OverflowOp(node)); |
| + } |
| + |
| + void ChangeToUint32OverflowOp(Node* node) { |
| + NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); |
| } |
| void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
| @@ -1144,10 +1115,8 @@ class RepresentationSelector { |
| if (hint == BinaryOperationHints::kSignedSmall || |
| hint == BinaryOperationHints::kSigned32) { |
| VisitBinop(node, UseInfo::TruncatingWord32(), |
| - MachineRepresentation::kWord32, TypeCheckKind::kSigned32); |
| - if (lower()) { |
| - ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| - } |
| + MachineRepresentation::kWord32, Type::Signed32()); |
| + if (lower()) ChangeToInt32OverflowOp(node); |
| return; |
| } |
| } |
| @@ -1155,16 +1124,14 @@ class RepresentationSelector { |
| if (hint == BinaryOperationHints::kSignedSmall || |
| hint == BinaryOperationHints::kSigned32) { |
| VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| - MachineRepresentation::kWord32, TypeCheckKind::kSigned32); |
| - if (lower()) { |
| - ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| - } |
| + MachineRepresentation::kWord32, Type::Signed32()); |
| + if (lower()) ChangeToInt32OverflowOp(node); |
| return; |
| } |
| // default case => Float64Add/Sub |
| VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| - MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| + MachineRepresentation::kFloat64, Type::Number()); |
| if (lower()) { |
| ChangeToPureOp(node, Float64Op(node)); |
| } |
| @@ -1348,6 +1315,25 @@ class RepresentationSelector { |
| } |
| case IrOpcode::kSpeculativeNumberMultiply: |
| case IrOpcode::kNumberMultiply: { |
| + if (BothInputsAreUnsigned32(node)) { |
| + if (NodeProperties::GetType(node)->Is(Type::Unsigned32())) { |
|
Jarin
2016/07/13 07:25:38
As discussed offline, it might be the right time t
Benedikt Meurer
2016/07/13 07:54:00
Done.
|
| + // Multiply reduces to Int32Mul if the inputs and the output |
| + // are unsigned integers. |
| + VisitUint32Binop(node); |
| + if (lower()) ChangeToPureOp(node, Uint32Op(node)); |
| + return; |
| + } |
| + if (truncation.TruncatesToWord32() && |
| + NodeProperties::GetType(node)->Is( |
| + type_cache_.kSafeIntegerOrMinusZero)) { |
| + // Multiply reduces to Int32Mul if the inputs are unsigned |
| + // integers, the uses are truncating and the result is in |
| + // the safe integer range. |
| + VisitWord32TruncatingBinop(node); |
| + if (lower()) ChangeToPureOp(node, Uint32Op(node)); |
| + return; |
| + } |
| + } |
| if (BothInputsAreSigned32(node)) { |
| if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
| // Multiply reduces to Int32Mul if the inputs and the output |
| @@ -1376,7 +1362,7 @@ class RepresentationSelector { |
| // Checked float64 x float64 => float64 |
| DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); |
| VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| - MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| + MachineRepresentation::kFloat64, Type::Number()); |
| if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| return; |
| } |
| @@ -1405,16 +1391,27 @@ class RepresentationSelector { |
| // Try to use type feedback. |
| BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
| + // Handle the case when no uint32 checks on inputs are necessary |
| + // (but an overflow check is needed on the output). |
| + if (BothInputsAreUnsigned32(node)) { |
| + if (hint == BinaryOperationHints::kSignedSmall || |
| + hint == BinaryOperationHints::kSigned32) { |
| + VisitBinop(node, UseInfo::TruncatingWord32(), |
| + MachineRepresentation::kWord32, Type::Unsigned32()); |
| + if (lower()) ChangeToUint32OverflowOp(node); |
| + return; |
| + } |
| + } |
| + |
| // Handle the case when no int32 checks on inputs are necessary |
| // (but an overflow check is needed on the output). |
| - if (BothInputsAre(node, Type::Signed32())) { |
| + if (BothInputsAreSigned32(node)) { |
| // If both the inputs the feedback are int32, use the overflow op. |
| if (hint == BinaryOperationHints::kSignedSmall || |
| hint == BinaryOperationHints::kSigned32) { |
| VisitBinop(node, UseInfo::TruncatingWord32(), |
| - MachineRepresentation::kWord32, |
| - TypeCheckKind::kSigned32); |
| - if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| + MachineRepresentation::kWord32, Type::Signed32()); |
| + if (lower()) ChangeToInt32OverflowOp(node); |
| return; |
| } |
| } |
| @@ -1428,16 +1425,15 @@ class RepresentationSelector { |
| if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
| } else { |
| VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| - MachineRepresentation::kWord32, |
| - TypeCheckKind::kSigned32); |
| - if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| + MachineRepresentation::kWord32, Type::Signed32()); |
| + if (lower()) ChangeToInt32OverflowOp(node); |
| } |
| return; |
| } |
| // default case => Float64Div |
| VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| - MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| + MachineRepresentation::kFloat64, Type::Number()); |
| if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| return; |
| } |
| @@ -1471,7 +1467,7 @@ class RepresentationSelector { |
| // Checked float64 x float64 => float64 |
| DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); |
| VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| - MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| + MachineRepresentation::kFloat64, Type::Number()); |
| if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| return; |
| } |
| @@ -1500,6 +1496,18 @@ class RepresentationSelector { |
| // Try to use type feedback. |
| BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
| + // Handle the case when no uint32 checks on inputs are necessary |
| + // (but an overflow check is needed on the output). |
| + if (BothInputsAreUnsigned32(node)) { |
| + if (hint == BinaryOperationHints::kSignedSmall || |
| + hint == BinaryOperationHints::kSigned32) { |
| + VisitBinop(node, UseInfo::TruncatingWord32(), |
| + MachineRepresentation::kWord32, Type::Unsigned32()); |
| + if (lower()) ChangeToUint32OverflowOp(node); |
| + return; |
| + } |
| + } |
| + |
| // Handle the case when no int32 checks on inputs are necessary |
| // (but an overflow check is needed on the output). |
| if (BothInputsAre(node, Type::Signed32())) { |
| @@ -1507,9 +1515,8 @@ class RepresentationSelector { |
| if (hint == BinaryOperationHints::kSignedSmall || |
| hint == BinaryOperationHints::kSigned32) { |
| VisitBinop(node, UseInfo::TruncatingWord32(), |
| - MachineRepresentation::kWord32, |
| - TypeCheckKind::kSigned32); |
| - if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| + MachineRepresentation::kWord32, Type::Signed32()); |
| + if (lower()) ChangeToInt32OverflowOp(node); |
| return; |
| } |
| } |
| @@ -1523,16 +1530,15 @@ class RepresentationSelector { |
| if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| } else { |
| VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| - MachineRepresentation::kWord32, |
| - TypeCheckKind::kSigned32); |
| - if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| + MachineRepresentation::kWord32, Type::Signed32()); |
| + if (lower()) ChangeToInt32OverflowOp(node); |
| } |
| return; |
| } |
| // default case => Float64Mod |
| VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| - MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| + MachineRepresentation::kFloat64, Type::Number()); |
| if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| return; |
| } |