| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index 8d4ca9f18e1d1557517fe35182efc19d1ac559ee..c3b26c4006a9596a5503ca0072b8bfcd5000f4ef 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -162,34 +162,6 @@ UseInfo UseInfoForBasePointer(const ElementAccess& access) {
|
|
|
| #ifdef DEBUG
|
| // Helpers for monotonicity checking.
|
| -
|
| -bool MachineTypeIsSubtype(MachineSemantic t1, MachineSemantic t2) {
|
| - switch (t1) {
|
| - case MachineSemantic::kNone:
|
| - return true;
|
| - case MachineSemantic::kBool:
|
| - return t2 == MachineSemantic::kBool || t2 == MachineSemantic::kNumber ||
|
| - t2 == MachineSemantic::kAny;
|
| - case MachineSemantic::kInt32:
|
| - return t2 == MachineSemantic::kInt32 || t2 == MachineSemantic::kNumber ||
|
| - t2 == MachineSemantic::kAny;
|
| - case MachineSemantic::kUint32:
|
| - return t2 == MachineSemantic::kUint32 || t2 == MachineSemantic::kNumber ||
|
| - t2 == MachineSemantic::kAny;
|
| - case MachineSemantic::kInt64:
|
| - return t2 == MachineSemantic::kInt64;
|
| - case MachineSemantic::kUint64:
|
| - return t2 == MachineSemantic::kUint64;
|
| - case MachineSemantic::kNumber:
|
| - return t2 == MachineSemantic::kNumber || t2 == MachineSemantic::kAny;
|
| - case MachineSemantic::kAny:
|
| - return t2 == MachineSemantic::kAny;
|
| - }
|
| - UNREACHABLE();
|
| - return false;
|
| -}
|
| -
|
| -
|
| bool MachineRepresentationIsSubtype(MachineRepresentation r1,
|
| MachineRepresentation r2) {
|
| switch (r1) {
|
| @@ -235,13 +207,6 @@ bool MachineRepresentationIsSubtype(MachineRepresentation r1,
|
| }
|
|
|
|
|
| -bool MachineTypeRepIsSubtype(MachineType m1, MachineType m2) {
|
| - return MachineTypeIsSubtype(m1.semantic(), m2.semantic()) &&
|
| - MachineRepresentationIsSubtype(m1.representation(),
|
| - m2.representation());
|
| -}
|
| -
|
| -
|
| class InputUseInfos {
|
| public:
|
| explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
|
| @@ -273,6 +238,71 @@ class InputUseInfos {
|
| class RepresentationSelector {
|
| public:
|
| // Information for each node tracked during the fixpoint.
|
| + class NodeOutputInfo {
|
| + public:
|
| + NodeOutputInfo(MachineRepresentation representation, Type* type)
|
| + : type_(type), representation_(representation) {}
|
| + NodeOutputInfo()
|
| + : type_(Type::None()), representation_(MachineRepresentation::kNone) {}
|
| +
|
| + MachineRepresentation representation() const { return representation_; }
|
| + Type* type() const { return type_; }
|
| +
|
| + static NodeOutputInfo None() {
|
| + return NodeOutputInfo(MachineRepresentation::kNone, Type::None());
|
| + }
|
| +
|
| + static NodeOutputInfo Float32() {
|
| + return NodeOutputInfo(MachineRepresentation::kFloat32, Type::Number());
|
| + }
|
| +
|
| + static NodeOutputInfo Float64() {
|
| + return NodeOutputInfo(MachineRepresentation::kFloat64, Type::Number());
|
| + }
|
| +
|
| + static NodeOutputInfo NumberTruncatedToWord32() {
|
| + return NodeOutputInfo(MachineRepresentation::kWord32, Type::Number());
|
| + }
|
| +
|
| + static NodeOutputInfo Int32() {
|
| + return NodeOutputInfo(MachineRepresentation::kWord32, Type::Signed32());
|
| + }
|
| +
|
| + static NodeOutputInfo Uint32() {
|
| + return NodeOutputInfo(MachineRepresentation::kWord32, Type::Unsigned32());
|
| + }
|
| +
|
| + static NodeOutputInfo Bool() {
|
| + return NodeOutputInfo(MachineRepresentation::kBit, Type::Boolean());
|
| + }
|
| +
|
| + static NodeOutputInfo Int64() {
|
| + // TODO(jarin) Fix once we have a real int64 type.
|
| + return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
|
| + }
|
| +
|
| + static NodeOutputInfo Uint64() {
|
| + // TODO(jarin) Fix once we have a real uint64 type.
|
| + return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
|
| + }
|
| +
|
| + static NodeOutputInfo AnyTagged() {
|
| + return NodeOutputInfo(MachineRepresentation::kTagged, Type::Any());
|
| + }
|
| +
|
| + static NodeOutputInfo NumberTagged() {
|
| + return NodeOutputInfo(MachineRepresentation::kTagged, Type::Number());
|
| + }
|
| +
|
| + static NodeOutputInfo Pointer() {
|
| + return NodeOutputInfo(MachineType::PointerRepresentation(), Type::Any());
|
| + }
|
| +
|
| + private:
|
| + Type* type_;
|
| + MachineRepresentation representation_;
|
| + };
|
| +
|
| class NodeInfo {
|
| public:
|
| // Adds new use to the node. Returns true if something has changed
|
| @@ -288,13 +318,17 @@ class RepresentationSelector {
|
| void set_visited() { visited_ = true; }
|
| bool visited() const { return visited_; }
|
| Truncation truncation() const { return truncation_; }
|
| - void set_output_type(MachineType type) { output_ = type; }
|
| - MachineType output_type() const { return output_; }
|
| + void set_output_type(NodeOutputInfo output) { output_ = output; }
|
| +
|
| + Type* output_type() const { return output_.type(); }
|
| + MachineRepresentation representation() const {
|
| + return output_.representation();
|
| + }
|
|
|
| private:
|
| bool queued_ = false; // Bookkeeping for the traversal.
|
| bool visited_ = false; // Bookkeeping for the traversal.
|
| - MachineType output_ = MachineType::None(); // Output type of the node.
|
| + NodeOutputInfo output_; // Output type and representation.
|
| Truncation truncation_ = Truncation::None(); // Information about uses.
|
| };
|
|
|
| @@ -330,7 +364,7 @@ class RepresentationSelector {
|
| TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
|
| VisitNode(node, info->truncation(), nullptr);
|
| TRACE(" ==> output ");
|
| - PrintInfo(info->output_type());
|
| + PrintOutputInfo(info);
|
| TRACE("\n");
|
| }
|
|
|
| @@ -429,36 +463,68 @@ class RepresentationSelector {
|
| }
|
| }
|
|
|
| - void SetOutput(Node* node, MachineType output) {
|
| + void SetOutputFromMachineType(Node* node, MachineType machine_type) {
|
| + Type* type = Type::None();
|
| + switch (machine_type.semantic()) {
|
| + case MachineSemantic::kNone:
|
| + type = Type::None();
|
| + break;
|
| + case MachineSemantic::kBool:
|
| + type = Type::Boolean();
|
| + break;
|
| + case MachineSemantic::kInt32:
|
| + type = Type::Signed32();
|
| + break;
|
| + case MachineSemantic::kUint32:
|
| + type = Type::Unsigned32();
|
| + break;
|
| + case MachineSemantic::kInt64:
|
| + // TODO(jarin) Fix once we have proper int64.
|
| + type = Type::Internal();
|
| + break;
|
| + case MachineSemantic::kUint64:
|
| + // TODO(jarin) Fix once we have proper uint64.
|
| + type = Type::Internal();
|
| + break;
|
| + case MachineSemantic::kNumber:
|
| + type = Type::Number();
|
| + break;
|
| + case MachineSemantic::kAny:
|
| + type = Type::Any();
|
| + break;
|
| + }
|
| + return SetOutput(node, NodeOutputInfo(machine_type.representation(), type));
|
| + }
|
| +
|
| + void SetOutput(Node* node, NodeOutputInfo output_info) {
|
| // Every node should have at most one output representation. Note that
|
| // phis can have 0, if they have not been used in a representation-inducing
|
| // instruction.
|
| NodeInfo* info = GetInfo(node);
|
| - DCHECK(MachineTypeRepIsSubtype(info->output_type(), output));
|
| - if (output != info->output_type()) {
|
| + DCHECK(MachineRepresentationIsSubtype(info->representation(),
|
| + output_info.representation()));
|
| + DCHECK(info->output_type()->Is(output_info.type()));
|
| + if (!output_info.type()->Is(info->output_type()) ||
|
| + output_info.representation() != info->representation()) {
|
| EnqueueUses(node);
|
| }
|
| - info->set_output_type(output);
|
| + info->set_output_type(output_info);
|
| }
|
|
|
| bool BothInputsAreSigned32(Node* node) {
|
| DCHECK_EQ(2, node->InputCount());
|
| return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Signed32()) ||
|
| - (GetInfo(node->InputAt(0))->output_type().semantic() ==
|
| - MachineSemantic::kInt32)) &&
|
| + GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32())) &&
|
| (NodeProperties::GetType(node->InputAt(1))->Is(Type::Signed32()) ||
|
| - (GetInfo(node->InputAt(1))->output_type().semantic() ==
|
| - MachineSemantic::kInt32));
|
| + GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32()));
|
| }
|
|
|
| bool BothInputsAreUnsigned32(Node* node) {
|
| DCHECK_EQ(2, node->InputCount());
|
| return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Unsigned32()) ||
|
| - GetInfo(node->InputAt(0))->output_type().semantic() ==
|
| - MachineSemantic::kUint32) &&
|
| + GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32())) &&
|
| (NodeProperties::GetType(node->InputAt(1))->Is(Type::Unsigned32()) ||
|
| - GetInfo(node->InputAt(1))->output_type().semantic() ==
|
| - MachineSemantic::kUint32);
|
| + GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32()));
|
| }
|
|
|
| bool BothInputsAre(Node* node, Type* type) {
|
| @@ -472,18 +538,20 @@ class RepresentationSelector {
|
| // In the change phase, insert a change before the use if necessary.
|
| if (use.preferred() == MachineRepresentation::kNone)
|
| return; // No input requirement on the use.
|
| - MachineType output = GetInfo(input)->output_type();
|
| - if (output.representation() != use.preferred()) {
|
| + NodeInfo* input_info = GetInfo(input);
|
| + MachineRepresentation input_rep = input_info->representation();
|
| + if (input_rep != use.preferred()) {
|
| // Output representation doesn't match usage.
|
| TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
|
| index, input->id(), input->op()->mnemonic());
|
| TRACE(" from ");
|
| - PrintInfo(output);
|
| + PrintOutputInfo(input_info);
|
| TRACE(" to ");
|
| PrintUseInfo(use);
|
| TRACE("\n");
|
| - Node* n = changer_->GetRepresentationFor(input, output, use.preferred(),
|
| - use.truncation());
|
| + Node* n = changer_->GetRepresentationFor(
|
| + input, input_info->representation(), input_info->output_type(),
|
| + use.preferred(), use.truncation());
|
| node->ReplaceInput(index, n);
|
| }
|
| }
|
| @@ -528,7 +596,7 @@ class RepresentationSelector {
|
|
|
| // Helper for binops of the R x L -> O variety.
|
| void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
|
| - MachineType output) {
|
| + NodeOutputInfo output) {
|
| DCHECK_EQ(2, node->op()->ValueInputCount());
|
| ProcessInput(node, 0, left_use);
|
| ProcessInput(node, 1, right_use);
|
| @@ -539,78 +607,77 @@ class RepresentationSelector {
|
| }
|
|
|
| // Helper for binops of the I x I -> O variety.
|
| - void VisitBinop(Node* node, UseInfo input_use, MachineType output) {
|
| + void VisitBinop(Node* node, UseInfo input_use, NodeOutputInfo output) {
|
| VisitBinop(node, input_use, input_use, output);
|
| }
|
|
|
| // Helper for unops of the I -> O variety.
|
| - void VisitUnop(Node* node, UseInfo input_use, MachineType output) {
|
| + void VisitUnop(Node* node, UseInfo input_use, NodeOutputInfo output) {
|
| DCHECK_EQ(1, node->InputCount());
|
| ProcessInput(node, 0, input_use);
|
| SetOutput(node, output);
|
| }
|
|
|
| // Helper for leaf nodes.
|
| - void VisitLeaf(Node* node, MachineType output) {
|
| + void VisitLeaf(Node* node, NodeOutputInfo output) {
|
| DCHECK_EQ(0, node->InputCount());
|
| SetOutput(node, output);
|
| }
|
|
|
| // Helpers for specific types of binops.
|
| void VisitFloat64Binop(Node* node) {
|
| - VisitBinop(node, UseInfo::Float64(), MachineType::Float64());
|
| + VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
|
| }
|
| void VisitInt32Binop(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Int32());
|
| + VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
|
| }
|
| void VisitWord32TruncatingBinop(Node* node) {
|
| - VisitBinop(
|
| - node, UseInfo::TruncatingWord32(),
|
| - MachineType(MachineRepresentation::kWord32, MachineSemantic::kNumber));
|
| + VisitBinop(node, UseInfo::TruncatingWord32(),
|
| + NodeOutputInfo::NumberTruncatedToWord32());
|
| }
|
| void VisitUint32Binop(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Uint32());
|
| + VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
|
| }
|
| void VisitInt64Binop(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Int64());
|
| + VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Int64());
|
| }
|
| void VisitUint64Binop(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Uint64());
|
| + VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Uint64());
|
| }
|
| void VisitFloat64Cmp(Node* node) {
|
| - VisitBinop(node, UseInfo::Float64(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
|
| }
|
| void VisitInt32Cmp(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
|
| }
|
| void VisitUint32Cmp(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
|
| }
|
| void VisitInt64Cmp(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
|
| }
|
| void VisitUint64Cmp(Node* node) {
|
| - VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
|
| }
|
|
|
| // Infer representation for phi-like nodes.
|
| static MachineRepresentation GetRepresentationForPhi(Node* node,
|
| Truncation use) {
|
| // Phis adapt to the output representation their uses demand.
|
| - Type* upper = NodeProperties::GetType(node);
|
| - if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
|
| + Type* type = NodeProperties::GetType(node);
|
| + if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
|
| // We are within 32 bits range => pick kRepWord32.
|
| return MachineRepresentation::kWord32;
|
| } else if (use.TruncatesToWord32()) {
|
| // We only use 32 bits.
|
| return MachineRepresentation::kWord32;
|
| - } else if (upper->Is(Type::Boolean())) {
|
| + } else if (type->Is(Type::Boolean())) {
|
| // multiple uses => pick kRepBit.
|
| return MachineRepresentation::kBit;
|
| - } else if (upper->Is(Type::Number())) {
|
| + } else if (type->Is(Type::Number())) {
|
| // multiple uses => pick kRepFloat64.
|
| return MachineRepresentation::kFloat64;
|
| - } else if (upper->Is(Type::Internal())) {
|
| + } else if (type->Is(Type::Internal())) {
|
| return MachineType::PointerRepresentation();
|
| }
|
| return MachineRepresentation::kTagged;
|
| @@ -622,10 +689,8 @@ class RepresentationSelector {
|
| ProcessInput(node, 0, UseInfo::Bool());
|
| MachineRepresentation output = GetRepresentationForPhi(node, truncation);
|
|
|
| - Type* upper = NodeProperties::GetType(node);
|
| - MachineType output_type =
|
| - MachineType(output, changer_->TypeFromUpperBound(upper));
|
| - SetOutput(node, output_type);
|
| + Type* type = NodeProperties::GetType(node);
|
| + SetOutput(node, NodeOutputInfo(output, type));
|
|
|
| if (lower()) {
|
| // Update the select operator.
|
| @@ -647,10 +712,8 @@ class RepresentationSelector {
|
| SimplifiedLowering* lowering) {
|
| MachineRepresentation output = GetRepresentationForPhi(node, truncation);
|
|
|
| - Type* upper = NodeProperties::GetType(node);
|
| - MachineType output_type =
|
| - MachineType(output, changer_->TypeFromUpperBound(upper));
|
| - SetOutput(node, output_type);
|
| + Type* type = NodeProperties::GetType(node);
|
| + SetOutput(node, NodeOutputInfo(output, type));
|
|
|
| int values = node->op()->ValueInputCount();
|
|
|
| @@ -687,9 +750,21 @@ class RepresentationSelector {
|
| }
|
|
|
| if (sig->return_count() > 0) {
|
| - SetOutput(node, desc->GetMachineSignature()->GetReturn());
|
| + SetOutputFromMachineType(node, desc->GetMachineSignature()->GetReturn());
|
| } else {
|
| - SetOutput(node, MachineType::AnyTagged());
|
| + SetOutput(node, NodeOutputInfo::AnyTagged());
|
| + }
|
| + }
|
| +
|
| + MachineSemantic DeoptValueSemanticOf(Type* type) {
|
| + CHECK(!type->Is(Type::None()));
|
| + // We only need signedness to do deopt correctly.
|
| + if (type->Is(Type::Signed32())) {
|
| + return MachineSemantic::kInt32;
|
| + } else if (type->Is(Type::Unsigned32())) {
|
| + return MachineSemantic::kUint32;
|
| + } else {
|
| + return MachineSemantic::kAny;
|
| }
|
| }
|
|
|
| @@ -704,13 +779,15 @@ class RepresentationSelector {
|
| new (zone->New(sizeof(ZoneVector<MachineType>)))
|
| ZoneVector<MachineType>(node->InputCount(), zone);
|
| for (int i = 0; i < node->InputCount(); i++) {
|
| - MachineType input_type = GetInfo(node->InputAt(i))->output_type();
|
| - (*types)[i] = input_type;
|
| + NodeInfo* input_info = GetInfo(node->InputAt(i));
|
| + (*types)[i] =
|
| + MachineType(input_info->representation(),
|
| + DeoptValueSemanticOf(input_info->output_type()));
|
| }
|
| NodeProperties::ChangeOp(node,
|
| jsgraph_->common()->TypedStateValues(types));
|
| }
|
| - SetOutput(node, MachineType::AnyTagged());
|
| + SetOutput(node, NodeOutputInfo::AnyTagged());
|
| }
|
|
|
| const Operator* Int32Op(Node* node) {
|
| @@ -756,29 +833,28 @@ class RepresentationSelector {
|
| //------------------------------------------------------------------
|
| case IrOpcode::kStart:
|
| case IrOpcode::kDead:
|
| - return VisitLeaf(node, MachineType::None());
|
| + return VisitLeaf(node, NodeOutputInfo::None());
|
| case IrOpcode::kParameter: {
|
| // TODO(titzer): use representation from linkage.
|
| - Type* upper = NodeProperties::GetType(node);
|
| + Type* type = NodeProperties::GetType(node);
|
| ProcessInput(node, 0, UseInfo::None());
|
| - SetOutput(node, MachineType(MachineRepresentation::kTagged,
|
| - changer_->TypeFromUpperBound(upper)));
|
| + SetOutput(node, NodeOutputInfo(MachineRepresentation::kTagged, type));
|
| return;
|
| }
|
| case IrOpcode::kInt32Constant:
|
| - return VisitLeaf(node, MachineType::RepWord32());
|
| + return VisitLeaf(node, NodeOutputInfo::Int32());
|
| case IrOpcode::kInt64Constant:
|
| - return VisitLeaf(node, MachineType::RepWord64());
|
| + return VisitLeaf(node, NodeOutputInfo::Int64());
|
| case IrOpcode::kFloat32Constant:
|
| - return VisitLeaf(node, MachineType::RepFloat32());
|
| + return VisitLeaf(node, NodeOutputInfo::Float32());
|
| case IrOpcode::kFloat64Constant:
|
| - return VisitLeaf(node, MachineType::RepFloat64());
|
| + return VisitLeaf(node, NodeOutputInfo::Float64());
|
| case IrOpcode::kExternalConstant:
|
| - return VisitLeaf(node, MachineType::Pointer());
|
| + return VisitLeaf(node, NodeOutputInfo::Pointer());
|
| case IrOpcode::kNumberConstant:
|
| - return VisitLeaf(node, MachineType::RepTagged());
|
| + return VisitLeaf(node, NodeOutputInfo::NumberTagged());
|
| case IrOpcode::kHeapConstant:
|
| - return VisitLeaf(node, MachineType::RepTagged());
|
| + return VisitLeaf(node, NodeOutputInfo::AnyTagged());
|
|
|
| case IrOpcode::kBranch:
|
| ProcessInput(node, 0, UseInfo::Bool());
|
| @@ -807,15 +883,15 @@ class RepresentationSelector {
|
| JS_OP_LIST(DEFINE_JS_CASE)
|
| #undef DEFINE_JS_CASE
|
| VisitInputs(node);
|
| - return SetOutput(node, MachineType::RepTagged());
|
| + return SetOutput(node, NodeOutputInfo::AnyTagged());
|
|
|
| //------------------------------------------------------------------
|
| // Simplified operators.
|
| //------------------------------------------------------------------
|
| case IrOpcode::kBooleanNot: {
|
| if (lower()) {
|
| - MachineType input = GetInfo(node->InputAt(0))->output_type();
|
| - if (input.representation() == MachineRepresentation::kBit) {
|
| + NodeInfo* input_info = GetInfo(node->InputAt(0));
|
| + if (input_info->representation() == MachineRepresentation::kBit) {
|
| // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
|
| node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
|
| NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
|
| @@ -827,14 +903,14 @@ class RepresentationSelector {
|
| } else {
|
| // No input representation requirement; adapt during lowering.
|
| ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
|
| - SetOutput(node, MachineType::RepBit());
|
| + SetOutput(node, NodeOutputInfo::Bool());
|
| }
|
| break;
|
| }
|
| case IrOpcode::kBooleanToNumber: {
|
| if (lower()) {
|
| - MachineType input = GetInfo(node->InputAt(0))->output_type();
|
| - if (input.representation() == MachineRepresentation::kBit) {
|
| + NodeInfo* input_info = GetInfo(node->InputAt(0));
|
| + if (input_info->representation() == MachineRepresentation::kBit) {
|
| // BooleanToNumber(x: kRepBit) => x
|
| DeferReplacement(node, node->InputAt(0));
|
| } else {
|
| @@ -845,7 +921,7 @@ class RepresentationSelector {
|
| } else {
|
| // No input representation requirement; adapt during lowering.
|
| ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
|
| - SetOutput(node, MachineType::Int32());
|
| + SetOutput(node, NodeOutputInfo::Int32());
|
| }
|
| break;
|
| }
|
| @@ -875,7 +951,7 @@ class RepresentationSelector {
|
| if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
|
| truncation.TruncatesToWord32()) {
|
| // => signed Int32Add/Sub
|
| - VisitInt32Binop(node);
|
| + VisitWord32TruncatingBinop(node);
|
| if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
|
| } else {
|
| // => Float64Add/Sub
|
| @@ -969,36 +1045,36 @@ class RepresentationSelector {
|
| }
|
| case IrOpcode::kNumberShiftLeft: {
|
| VisitBinop(node, UseInfo::TruncatingWord32(),
|
| - UseInfo::TruncatingWord32(), MachineType::Int32());
|
| + UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
|
| if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl());
|
| break;
|
| }
|
| case IrOpcode::kNumberShiftRight: {
|
| VisitBinop(node, UseInfo::TruncatingWord32(),
|
| - UseInfo::TruncatingWord32(), MachineType::Int32());
|
| + UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
|
| if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar());
|
| break;
|
| }
|
| case IrOpcode::kNumberShiftRightLogical: {
|
| VisitBinop(node, UseInfo::TruncatingWord32(),
|
| - UseInfo::TruncatingWord32(), MachineType::Uint32());
|
| + UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
|
| if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr());
|
| break;
|
| }
|
| case IrOpcode::kNumberToInt32: {
|
| // Just change representation if necessary.
|
| - VisitUnop(node, UseInfo::TruncatingWord32(), MachineType::Int32());
|
| + VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
|
| if (lower()) DeferReplacement(node, node->InputAt(0));
|
| break;
|
| }
|
| case IrOpcode::kNumberToUint32: {
|
| // Just change representation if necessary.
|
| - VisitUnop(node, UseInfo::TruncatingWord32(), MachineType::Uint32());
|
| + VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
|
| if (lower()) DeferReplacement(node, node->InputAt(0));
|
| break;
|
| }
|
| case IrOpcode::kNumberIsHoleNaN: {
|
| - VisitUnop(node, UseInfo::Float64(), MachineType::Bool());
|
| + VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
|
| if (lower()) {
|
| // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
|
| // #HoleNaNLower32)
|
| @@ -1013,9 +1089,7 @@ class RepresentationSelector {
|
| break;
|
| }
|
| case IrOpcode::kPlainPrimitiveToNumber: {
|
| - VisitUnop(node, UseInfo::AnyTagged(),
|
| - MachineType(MachineRepresentation::kTagged,
|
| - MachineSemantic::kNumber));
|
| + VisitUnop(node, UseInfo::AnyTagged(), NodeOutputInfo::NumberTagged());
|
| if (lower()) {
|
| // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
|
| Operator::Properties properties = node->op()->properties();
|
| @@ -1032,38 +1106,38 @@ class RepresentationSelector {
|
| break;
|
| }
|
| case IrOpcode::kReferenceEqual: {
|
| - VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
|
| if (lower()) {
|
| NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
|
| }
|
| break;
|
| }
|
| case IrOpcode::kStringEqual: {
|
| - VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
|
| if (lower()) lowering->DoStringEqual(node);
|
| break;
|
| }
|
| case IrOpcode::kStringLessThan: {
|
| - VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
|
| if (lower()) lowering->DoStringLessThan(node);
|
| break;
|
| }
|
| case IrOpcode::kStringLessThanOrEqual: {
|
| - VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
|
| + VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
|
| if (lower()) lowering->DoStringLessThanOrEqual(node);
|
| break;
|
| }
|
| case IrOpcode::kAllocate: {
|
| ProcessInput(node, 0, UseInfo::AnyTagged());
|
| ProcessRemainingInputs(node, 1);
|
| - SetOutput(node, MachineType::AnyTagged());
|
| + SetOutput(node, NodeOutputInfo::AnyTagged());
|
| break;
|
| }
|
| case IrOpcode::kLoadField: {
|
| FieldAccess access = FieldAccessOf(node->op());
|
| ProcessInput(node, 0, UseInfoForBasePointer(access));
|
| ProcessRemainingInputs(node, 1);
|
| - SetOutput(node, access.machine_type);
|
| + SetOutputFromMachineType(node, access.machine_type);
|
| break;
|
| }
|
| case IrOpcode::kStoreField: {
|
| @@ -1072,7 +1146,7 @@ class RepresentationSelector {
|
| ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
|
| access.machine_type.representation()));
|
| ProcessRemainingInputs(node, 2);
|
| - SetOutput(node, MachineType::None());
|
| + SetOutput(node, NodeOutputInfo::None());
|
| break;
|
| }
|
| case IrOpcode::kLoadBuffer: {
|
| @@ -1082,30 +1156,34 @@ class RepresentationSelector {
|
| ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
|
| ProcessRemainingInputs(node, 3);
|
|
|
| - MachineType output_type;
|
| + NodeOutputInfo output_info;
|
| if (truncation.TruncatesUndefinedToZeroOrNaN()) {
|
| if (truncation.TruncatesNaNToZero()) {
|
| // If undefined is truncated to a non-NaN number, we can use
|
| // the load's representation.
|
| - output_type = access.machine_type();
|
| + output_info = NodeOutputInfo(access.machine_type().representation(),
|
| + NodeProperties::GetType(node));
|
| } else {
|
| // If undefined is truncated to a number, but the use can
|
| // observe NaN, we need to output at least the float32
|
| // representation.
|
| if (access.machine_type().representation() ==
|
| MachineRepresentation::kFloat32) {
|
| - output_type = access.machine_type();
|
| + output_info =
|
| + NodeOutputInfo(access.machine_type().representation(),
|
| + NodeProperties::GetType(node));
|
| } else {
|
| - output_type = MachineType::Float64();
|
| + output_info = NodeOutputInfo::Float64();
|
| }
|
| }
|
| } else {
|
| // If undefined is not truncated away, we need to have the tagged
|
| // representation.
|
| - output_type = MachineType::AnyTagged();
|
| + output_info = NodeOutputInfo::AnyTagged();
|
| }
|
| - SetOutput(node, output_type);
|
| - if (lower()) lowering->DoLoadBuffer(node, output_type, changer_);
|
| + SetOutput(node, output_info);
|
| + if (lower())
|
| + lowering->DoLoadBuffer(node, output_info.representation(), changer_);
|
| break;
|
| }
|
| case IrOpcode::kStoreBuffer: {
|
| @@ -1117,7 +1195,7 @@ class RepresentationSelector {
|
| TruncatingUseInfoFromRepresentation(
|
| access.machine_type().representation())); // value
|
| ProcessRemainingInputs(node, 4);
|
| - SetOutput(node, MachineType::None());
|
| + SetOutput(node, NodeOutputInfo::None());
|
| if (lower()) lowering->DoStoreBuffer(node);
|
| break;
|
| }
|
| @@ -1126,7 +1204,7 @@ class RepresentationSelector {
|
| ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
|
| ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
|
| ProcessRemainingInputs(node, 2);
|
| - SetOutput(node, access.machine_type);
|
| + SetOutputFromMachineType(node, access.machine_type);
|
| break;
|
| }
|
| case IrOpcode::kStoreElement: {
|
| @@ -1137,18 +1215,18 @@ class RepresentationSelector {
|
| TruncatingUseInfoFromRepresentation(
|
| access.machine_type.representation())); // value
|
| ProcessRemainingInputs(node, 3);
|
| - SetOutput(node, MachineType::None());
|
| + SetOutput(node, NodeOutputInfo::None());
|
| break;
|
| }
|
| case IrOpcode::kObjectIsNumber: {
|
| ProcessInput(node, 0, UseInfo::AnyTagged());
|
| - SetOutput(node, MachineType::Bool());
|
| + SetOutput(node, NodeOutputInfo::Bool());
|
| if (lower()) lowering->DoObjectIsNumber(node);
|
| break;
|
| }
|
| case IrOpcode::kObjectIsSmi: {
|
| ProcessInput(node, 0, UseInfo::AnyTagged());
|
| - SetOutput(node, MachineType::Bool());
|
| + SetOutput(node, NodeOutputInfo::Bool());
|
| if (lower()) lowering->DoObjectIsSmi(node);
|
| break;
|
| }
|
| @@ -1163,7 +1241,7 @@ class RepresentationSelector {
|
| ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
|
| ProcessInput(node, 1, UseInfo::PointerInt()); // index
|
| ProcessRemainingInputs(node, 2);
|
| - SetOutput(node, rep);
|
| + SetOutputFromMachineType(node, rep);
|
| break;
|
| }
|
| case IrOpcode::kStore: {
|
| @@ -1175,13 +1253,13 @@ class RepresentationSelector {
|
| ProcessInput(node, 2,
|
| TruncatingUseInfoFromRepresentation(rep.representation()));
|
| ProcessRemainingInputs(node, 3);
|
| - SetOutput(node, MachineType::None());
|
| + SetOutput(node, NodeOutputInfo::None());
|
| break;
|
| }
|
| case IrOpcode::kWord32Shr:
|
| // We output unsigned int32 for shift right because JavaScript.
|
| return VisitBinop(node, UseInfo::TruncatingWord32(),
|
| - MachineType::Uint32());
|
| + NodeOutputInfo::Uint32());
|
| case IrOpcode::kWord32And:
|
| case IrOpcode::kWord32Or:
|
| case IrOpcode::kWord32Xor:
|
| @@ -1191,14 +1269,14 @@ class RepresentationSelector {
|
| // though the machine bits are the same for either signed or unsigned,
|
| // because JavaScript considers the result from these operations signed.
|
| return VisitBinop(node, UseInfo::TruncatingWord32(),
|
| - MachineType::Int32());
|
| + NodeOutputInfo::Int32());
|
| case IrOpcode::kWord32Equal:
|
| return VisitBinop(node, UseInfo::TruncatingWord32(),
|
| - MachineType::Bool());
|
| + NodeOutputInfo::Bool());
|
|
|
| case IrOpcode::kWord32Clz:
|
| return VisitUnop(node, UseInfo::TruncatingWord32(),
|
| - MachineType::Uint32());
|
| + NodeOutputInfo::Uint32());
|
|
|
| case IrOpcode::kInt32Add:
|
| case IrOpcode::kInt32Sub:
|
| @@ -1243,45 +1321,44 @@ class RepresentationSelector {
|
| case IrOpcode::kWord64Shr:
|
| case IrOpcode::kWord64Sar:
|
| return VisitBinop(node, UseInfo::TruncatingWord64(),
|
| - MachineType(MachineRepresentation::kWord64,
|
| - MachineSemantic::kNone));
|
| + NodeOutputInfo::Int64());
|
| case IrOpcode::kWord64Equal:
|
| return VisitBinop(node, UseInfo::TruncatingWord64(),
|
| - MachineType::Bool());
|
| + NodeOutputInfo::Bool());
|
|
|
| case IrOpcode::kChangeInt32ToInt64:
|
| - return VisitUnop(node, UseInfo::TruncatingWord32(),
|
| - MachineType(MachineRepresentation::kWord64,
|
| - MachineSemantic::kInt32));
|
| + return VisitUnop(
|
| + node, UseInfo::TruncatingWord32(),
|
| + NodeOutputInfo(MachineRepresentation::kWord64, Type::Signed32()));
|
| case IrOpcode::kChangeUint32ToUint64:
|
| - return VisitUnop(node, UseInfo::TruncatingWord32(),
|
| - MachineType(MachineRepresentation::kWord64,
|
| - MachineSemantic::kUint32));
|
| + return VisitUnop(
|
| + node, UseInfo::TruncatingWord32(),
|
| + NodeOutputInfo(MachineRepresentation::kWord64, Type::Unsigned32()));
|
| case IrOpcode::kTruncateFloat64ToFloat32:
|
| - return VisitUnop(node, UseInfo::Float64(), MachineType::Float32());
|
| + return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float32());
|
| case IrOpcode::kTruncateFloat64ToInt32:
|
| - return VisitUnop(node, UseInfo::Float64(), MachineType::Int32());
|
| + return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
|
| case IrOpcode::kTruncateInt64ToInt32:
|
| // TODO(titzer): Is kTypeInt32 correct here?
|
| return VisitUnop(node, UseInfo::Word64TruncatingToWord32(),
|
| - MachineType::Int32());
|
| + NodeOutputInfo::Int32());
|
|
|
| case IrOpcode::kChangeFloat32ToFloat64:
|
| - return VisitUnop(node, UseInfo::Float32(), MachineType::Float64());
|
| + return VisitUnop(node, UseInfo::Float32(), NodeOutputInfo::Float64());
|
| case IrOpcode::kChangeInt32ToFloat64:
|
| - return VisitUnop(node, UseInfo::TruncatingWord32(),
|
| - MachineType(MachineRepresentation::kFloat64,
|
| - MachineSemantic::kInt32));
|
| + return VisitUnop(
|
| + node, UseInfo::TruncatingWord32(),
|
| + NodeOutputInfo(MachineRepresentation::kFloat64, Type::Signed32()));
|
| case IrOpcode::kChangeUint32ToFloat64:
|
| return VisitUnop(node, UseInfo::TruncatingWord32(),
|
| - MachineType(MachineRepresentation::kFloat64,
|
| - MachineSemantic::kUint32));
|
| + NodeOutputInfo(MachineRepresentation::kFloat64,
|
| + Type::Unsigned32()));
|
| case IrOpcode::kChangeFloat64ToInt32:
|
| return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
|
| - MachineType::Int32());
|
| + NodeOutputInfo::Int32());
|
| case IrOpcode::kChangeFloat64ToUint32:
|
| return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
|
| - MachineType::Uint32());
|
| + NodeOutputInfo::Uint32());
|
|
|
| case IrOpcode::kFloat64Add:
|
| case IrOpcode::kFloat64Sub:
|
| @@ -1295,28 +1372,28 @@ class RepresentationSelector {
|
| case IrOpcode::kFloat64RoundDown:
|
| case IrOpcode::kFloat64RoundTruncate:
|
| case IrOpcode::kFloat64RoundTiesAway:
|
| - return VisitUnop(node, UseInfo::Float64(), MachineType::Float64());
|
| + return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
|
| case IrOpcode::kFloat64Equal:
|
| case IrOpcode::kFloat64LessThan:
|
| case IrOpcode::kFloat64LessThanOrEqual:
|
| return VisitFloat64Cmp(node);
|
| case IrOpcode::kFloat64ExtractLowWord32:
|
| case IrOpcode::kFloat64ExtractHighWord32:
|
| - return VisitUnop(node, UseInfo::Float64(), MachineType::Int32());
|
| + return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
|
| case IrOpcode::kFloat64InsertLowWord32:
|
| case IrOpcode::kFloat64InsertHighWord32:
|
| return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
|
| - MachineType::Float64());
|
| + NodeOutputInfo::Float64());
|
| case IrOpcode::kLoadStackPointer:
|
| case IrOpcode::kLoadFramePointer:
|
| - return VisitLeaf(node, MachineType::Pointer());
|
| + return VisitLeaf(node, NodeOutputInfo::Pointer());
|
| case IrOpcode::kStateValues:
|
| VisitStateValues(node);
|
| break;
|
| default:
|
| VisitInputs(node);
|
| // Assume the output is tagged.
|
| - SetOutput(node, MachineType::AnyTagged());
|
| + SetOutput(node, NodeOutputInfo::AnyTagged());
|
| break;
|
| }
|
| }
|
| @@ -1342,10 +1419,19 @@ class RepresentationSelector {
|
| node->NullAllInputs(); // Node is now dead.
|
| }
|
|
|
| - void PrintInfo(MachineType info) {
|
| + void PrintOutputInfo(NodeInfo* info) {
|
| + if (FLAG_trace_representation) {
|
| + OFStream os(stdout);
|
| + os << info->representation() << " (";
|
| + info->output_type()->PrintTo(os, Type::SEMANTIC_DIM);
|
| + os << ")";
|
| + }
|
| + }
|
| +
|
| + void PrintRepresentation(MachineRepresentation rep) {
|
| if (FLAG_trace_representation) {
|
| OFStream os(stdout);
|
| - os << info;
|
| + os << rep;
|
| }
|
| }
|
|
|
| @@ -1408,12 +1494,13 @@ void SimplifiedLowering::LowerAllNodes() {
|
| }
|
|
|
|
|
| -void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type,
|
| +void SimplifiedLowering::DoLoadBuffer(Node* node,
|
| + MachineRepresentation output_rep,
|
| RepresentationChanger* changer) {
|
| DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
|
| - DCHECK_NE(MachineRepresentation::kNone, output_type.representation());
|
| - MachineType const type = BufferAccessOf(node->op()).machine_type();
|
| - if (output_type != type) {
|
| + DCHECK_NE(MachineRepresentation::kNone, output_rep);
|
| + MachineType const access_type = BufferAccessOf(node->op()).machine_type();
|
| + if (output_rep != access_type.representation()) {
|
| Node* const buffer = node->InputAt(0);
|
| Node* const offset = node->InputAt(1);
|
| Node* const length = node->InputAt(2);
|
| @@ -1429,22 +1516,21 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type,
|
| graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
|
|
|
| Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
| - Node* etrue =
|
| - graph()->NewNode(machine()->Load(type), buffer, index, effect, if_true);
|
| + Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
|
| + effect, if_true);
|
| Node* vtrue = changer->GetRepresentationFor(
|
| - etrue, type, output_type.representation(), Truncation::None());
|
| + etrue, access_type.representation(), NodeProperties::GetType(node),
|
| + output_rep, Truncation::None());
|
|
|
| Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
| Node* efalse = effect;
|
| Node* vfalse;
|
| - if (output_type.representation() == MachineRepresentation::kTagged) {
|
| + if (output_rep == MachineRepresentation::kTagged) {
|
| vfalse = jsgraph()->UndefinedConstant();
|
| - } else if (output_type.representation() ==
|
| - MachineRepresentation::kFloat64) {
|
| + } else if (output_rep == MachineRepresentation::kFloat64) {
|
| vfalse =
|
| jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
|
| - } else if (output_type.representation() ==
|
| - MachineRepresentation::kFloat32) {
|
| + } else if (output_rep == MachineRepresentation::kFloat32) {
|
| vfalse =
|
| jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
|
| } else {
|
| @@ -1462,10 +1548,9 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type,
|
| node->ReplaceInput(1, vfalse);
|
| node->ReplaceInput(2, merge);
|
| node->TrimInputCount(3);
|
| - NodeProperties::ChangeOp(node,
|
| - common()->Phi(output_type.representation(), 2));
|
| + NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
|
| } else {
|
| - NodeProperties::ChangeOp(node, machine()->CheckedLoad(type));
|
| + NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
|
| }
|
| }
|
|
|
|
|