| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index c3b26c4006a9596a5503ca0072b8bfcd5000f4ef..c2c7457f3e5fd82438aedfd36fa62e516169dfdd 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -500,37 +500,39 @@ class RepresentationSelector {
|
| // 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.
|
| + Type* output_type = output_info.type();
|
| + if (NodeProperties::IsTyped(node)) {
|
| + output_type = Type::Intersect(NodeProperties::GetType(node),
|
| + output_info.type(), jsgraph_->zone());
|
| + }
|
| NodeInfo* info = GetInfo(node);
|
| + DCHECK(info->output_type()->Is(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()) ||
|
| + if (!output_type->Is(info->output_type()) ||
|
| output_info.representation() != info->representation()) {
|
| EnqueueUses(node);
|
| }
|
| - info->set_output_type(output_info);
|
| + info->set_output_type(
|
| + NodeOutputInfo(output_info.representation(), output_type));
|
| }
|
|
|
| bool BothInputsAreSigned32(Node* node) {
|
| DCHECK_EQ(2, node->InputCount());
|
| - return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Signed32()) ||
|
| - GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32())) &&
|
| - (NodeProperties::GetType(node->InputAt(1))->Is(Type::Signed32()) ||
|
| - GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32()));
|
| + return GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32()) &&
|
| + 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()->Is(Type::Unsigned32())) &&
|
| - (NodeProperties::GetType(node->InputAt(1))->Is(Type::Unsigned32()) ||
|
| - GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32()));
|
| + return GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32()) &&
|
| + GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32());
|
| }
|
|
|
| bool BothInputsAre(Node* node, Type* type) {
|
| DCHECK_EQ(2, node->InputCount());
|
| - return NodeProperties::GetType(node->InputAt(0))->Is(type) &&
|
| - NodeProperties::GetType(node->InputAt(1))->Is(type);
|
| + return GetInfo(node->InputAt(0))->output_type()->Is(type) &&
|
| + GetInfo(node->InputAt(1))->output_type()->Is(type);
|
| }
|
|
|
| void ConvertInput(Node* node, int index, UseInfo use) {
|
| @@ -661,48 +663,66 @@ class RepresentationSelector {
|
| }
|
|
|
| // Infer representation for phi-like nodes.
|
| - static MachineRepresentation GetRepresentationForPhi(Node* node,
|
| - Truncation use) {
|
| - // Phis adapt to the output representation their uses demand.
|
| - 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;
|
| + NodeOutputInfo GetOutputInfoForPhi(Node* node, Truncation use) {
|
| + // Compute the type.
|
| + Type* type = GetInfo(node->InputAt(0))->output_type();
|
| + for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
|
| + type = Type::Union(type, GetInfo(node->InputAt(i))->output_type(),
|
| + jsgraph_->zone());
|
| + }
|
| +
|
| + // Compute the representation.
|
| + MachineRepresentation rep = MachineRepresentation::kTagged;
|
| + if (type->Is(Type::None())) {
|
| + rep = MachineRepresentation::kNone;
|
| + } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
|
| + rep = MachineRepresentation::kWord32;
|
| } else if (use.TruncatesToWord32()) {
|
| - // We only use 32 bits.
|
| - return MachineRepresentation::kWord32;
|
| + rep = MachineRepresentation::kWord32;
|
| } else if (type->Is(Type::Boolean())) {
|
| - // multiple uses => pick kRepBit.
|
| - return MachineRepresentation::kBit;
|
| + rep = MachineRepresentation::kBit;
|
| } else if (type->Is(Type::Number())) {
|
| - // multiple uses => pick kRepFloat64.
|
| - return MachineRepresentation::kFloat64;
|
| + rep = MachineRepresentation::kFloat64;
|
| } else if (type->Is(Type::Internal())) {
|
| - return MachineType::PointerRepresentation();
|
| + // We mark (u)int64 as Type::Internal.
|
| + // TODO(jarin) This is a workaround for our lack of (u)int64
|
| + // types. This can be removed once we can represent (u)int64
|
| + // unambiguously. (At the moment internal objects, such as the hole,
|
| + // are also Type::Internal()).
|
| + bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
|
| + MachineRepresentation::kWord64;
|
| +#ifdef DEBUG
|
| + // Check that all the inputs agree on being Word64.
|
| + for (int i = 1; i < node->op()->ValueInputCount(); i++) {
|
| + DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
|
| + MachineRepresentation::kWord64);
|
| + }
|
| +#endif
|
| + rep = is_word64 ? MachineRepresentation::kWord64
|
| + : MachineRepresentation::kTagged;
|
| }
|
| - return MachineRepresentation::kTagged;
|
| + return NodeOutputInfo(rep, type);
|
| }
|
|
|
| // Helper for handling selects.
|
| void VisitSelect(Node* node, Truncation truncation,
|
| SimplifiedLowering* lowering) {
|
| ProcessInput(node, 0, UseInfo::Bool());
|
| - MachineRepresentation output = GetRepresentationForPhi(node, truncation);
|
|
|
| - Type* type = NodeProperties::GetType(node);
|
| - SetOutput(node, NodeOutputInfo(output, type));
|
| + NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
|
| + SetOutput(node, output);
|
|
|
| if (lower()) {
|
| // Update the select operator.
|
| SelectParameters p = SelectParametersOf(node->op());
|
| - if (output != p.representation()) {
|
| - NodeProperties::ChangeOp(node,
|
| - lowering->common()->Select(output, p.hint()));
|
| + if (output.representation() != p.representation()) {
|
| + NodeProperties::ChangeOp(node, lowering->common()->Select(
|
| + output.representation(), p.hint()));
|
| }
|
| }
|
| // Convert inputs to the output representation of this phi, pass the
|
| // truncation truncation along.
|
| - UseInfo input_use(output, truncation);
|
| + UseInfo input_use(output.representation(), truncation);
|
| ProcessInput(node, 1, input_use);
|
| ProcessInput(node, 2, input_use);
|
| }
|
| @@ -710,23 +730,21 @@ class RepresentationSelector {
|
| // Helper for handling phis.
|
| void VisitPhi(Node* node, Truncation truncation,
|
| SimplifiedLowering* lowering) {
|
| - MachineRepresentation output = GetRepresentationForPhi(node, truncation);
|
| -
|
| - Type* type = NodeProperties::GetType(node);
|
| - SetOutput(node, NodeOutputInfo(output, type));
|
| + NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
|
| + SetOutput(node, output);
|
|
|
| int values = node->op()->ValueInputCount();
|
| -
|
| if (lower()) {
|
| // Update the phi operator.
|
| - if (output != PhiRepresentationOf(node->op())) {
|
| - NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
|
| + if (output.representation() != PhiRepresentationOf(node->op())) {
|
| + NodeProperties::ChangeOp(
|
| + node, lowering->common()->Phi(output.representation(), values));
|
| }
|
| }
|
|
|
| // Convert inputs to the output representation of this phi, pass the
|
| // truncation truncation along.
|
| - UseInfo input_use(output, truncation);
|
| + UseInfo input_use(output.representation(), truncation);
|
| for (int i = 0; i < node->InputCount(); i++) {
|
| ProcessInput(node, i, i < values ? input_use : UseInfo::None());
|
| }
|
| @@ -780,9 +798,14 @@ class RepresentationSelector {
|
| ZoneVector<MachineType>(node->InputCount(), zone);
|
| for (int i = 0; i < node->InputCount(); i++) {
|
| NodeInfo* input_info = GetInfo(node->InputAt(i));
|
| - (*types)[i] =
|
| - MachineType(input_info->representation(),
|
| - DeoptValueSemanticOf(input_info->output_type()));
|
| + MachineType machine_type(
|
| + input_info->representation(),
|
| + DeoptValueSemanticOf(input_info->output_type()));
|
| + DCHECK(machine_type.representation() !=
|
| + MachineRepresentation::kWord32 ||
|
| + machine_type.semantic() == MachineSemantic::kInt32 ||
|
| + machine_type.semantic() == MachineSemantic::kUint32);
|
| + (*types)[i] = machine_type;
|
| }
|
| NodeProperties::ChangeOp(node,
|
| jsgraph_->common()->TypedStateValues(types));
|
| @@ -802,27 +825,6 @@ class RepresentationSelector {
|
| return changer_->Float64OperatorFor(node->opcode());
|
| }
|
|
|
| - bool CanLowerToInt32Binop(Node* node, Truncation use) {
|
| - return BothInputsAreSigned32(node) &&
|
| - NodeProperties::GetType(node)->Is(Type::Signed32());
|
| - }
|
| -
|
| - bool CanLowerToInt32AdditiveBinop(Node* node, Truncation use) {
|
| - // It is safe to lower to word32 operation if:
|
| - // - the inputs are safe integers (so the low bits are not discarded), and
|
| - // - the uses can only observe the lowest 32 bits.
|
| - // TODO(jarin): we could support the uint32 case here, but that would
|
| - // require setting kTypeUint32 as the output type. Eventually, we will want
|
| - // to use only the big types, then this should work automatically.
|
| - return BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
|
| - use.TruncatesToWord32();
|
| - }
|
| -
|
| - bool CanLowerToInt32MultiplicativeBinop(Node* node, Truncation use) {
|
| - return BothInputsAreSigned32(node) && use.TruncatesToWord32() &&
|
| - NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger);
|
| - }
|
| -
|
| // Dispatching routine for visiting the node {node} with the usage {use}.
|
| // Depending on the operator, propagate new usage info to the inputs.
|
| void VisitNode(Node* node, Truncation truncation,
|
|
|