| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index cc7279ece0a0b3d2443d1188936e5eea22dde1ed..c9d592c282aae49ad57806111d54a3db16af8d5f 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,24 +1315,20 @@ class RepresentationSelector {
|
| }
|
| 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()) ChangeToPureOp(node, Int32Op(node));
|
| - return;
|
| - }
|
| - if (truncation.TruncatesToWord32() &&
|
| + if (BothInputsAre(node, Type::Integral32()) &&
|
| + (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
|
| + NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
|
| + (truncation.TruncatesToWord32() &&
|
| NodeProperties::GetType(node)->Is(
|
| - type_cache_.kSafeIntegerOrMinusZero)) {
|
| - // Multiply reduces to Int32Mul if the inputs are integers,
|
| - // the uses are truncating and the result is in the safe
|
| - // integer range.
|
| - VisitWord32TruncatingBinop(node);
|
| - if (lower()) ChangeToPureOp(node, Int32Op(node));
|
| - return;
|
| - }
|
| + type_cache_.kSafeIntegerOrMinusZero)))) {
|
| + // Multiply reduces to Int32Mul if the inputs are integers, and
|
| + // (a) the output is either known to be Signed32, or
|
| + // (b) the output is known to be Unsigned32, or
|
| + // (c) the uses are truncating and the result is in the safe
|
| + // integer range.
|
| + VisitWord32TruncatingBinop(node);
|
| + if (lower()) ChangeToPureOp(node, Int32Op(node));
|
| + return;
|
| }
|
| // Number x Number => Float64Mul
|
| if (BothInputsAre(node, Type::NumberOrUndefined())) {
|
| @@ -1376,7 +1339,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 +1368,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 +1402,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 +1444,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 +1473,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 +1492,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 +1507,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;
|
| }
|
|
|