| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index 3e7071ab51236e0f23a60ef187e2c149b18c7d3f..97a82909ebc4b2be55b0fdd6c210c75188b15d38 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -761,17 +761,30 @@ class RepresentationSelector {
|
| // values {kTypeAny}.
|
| void VisitInputs(Node* node) {
|
| int tagged_count = node->op()->ValueInputCount() +
|
| - OperatorProperties::GetContextInputCount(node->op());
|
| - // Visit value and context inputs as tagged.
|
| + OperatorProperties::GetContextInputCount(node->op()) +
|
| + OperatorProperties::GetFrameStateInputCount(node->op());
|
| + // Visit value, context and frame state inputs as tagged.
|
| for (int i = 0; i < tagged_count; i++) {
|
| ProcessInput(node, i, UseInfo::AnyTagged());
|
| }
|
| - // Only enqueue other inputs (framestates, effects, control).
|
| + // Only enqueue other inputs (effects, control).
|
| for (int i = tagged_count; i < node->InputCount(); i++) {
|
| EnqueueInput(node, i);
|
| }
|
| }
|
|
|
| + // Helper for an unused node.
|
| + void VisitUnused(Node* node) {
|
| + int value_count = node->op()->ValueInputCount() +
|
| + OperatorProperties::GetContextInputCount(node->op()) +
|
| + OperatorProperties::GetFrameStateInputCount(node->op());
|
| + for (int i = 0; i < value_count; i++) {
|
| + ProcessInput(node, i, UseInfo::None());
|
| + }
|
| + ProcessRemainingInputs(node, value_count);
|
| + if (lower()) Kill(node);
|
| + }
|
| +
|
| // Helper for binops of the R x L -> O variety.
|
| void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
|
| MachineRepresentation output,
|
| @@ -934,18 +947,20 @@ class RepresentationSelector {
|
| void VisitCall(Node* node, SimplifiedLowering* lowering) {
|
| const CallDescriptor* desc = CallDescriptorOf(node->op());
|
| int params = static_cast<int>(desc->ParameterCount());
|
| + int value_input_count = node->op()->ValueInputCount();
|
| // Propagate representation information from call descriptor.
|
| - for (int i = 0; i < node->InputCount(); i++) {
|
| + for (int i = 0; i < value_input_count; i++) {
|
| if (i == 0) {
|
| // The target of the call.
|
| - ProcessInput(node, i, UseInfo::None());
|
| + ProcessInput(node, i, UseInfo::Any());
|
| } else if ((i - 1) < params) {
|
| ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
|
| desc->GetInputType(i).representation()));
|
| } else {
|
| - ProcessInput(node, i, UseInfo::None());
|
| + ProcessInput(node, i, UseInfo::AnyTagged());
|
| }
|
| }
|
| + ProcessRemainingInputs(node, value_input_count);
|
|
|
| if (desc->ReturnCount() > 0) {
|
| SetOutput(node, desc->GetReturnType(0).representation());
|
| @@ -1109,6 +1124,7 @@ class RepresentationSelector {
|
|
|
| void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
|
| SimplifiedLowering* lowering) {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) &&
|
| NodeProperties::GetType(node)->Is(Type::Signed32())) {
|
| // int32 + int32 = int32 ==> signed Int32Add/Sub
|
| @@ -1166,11 +1182,21 @@ class RepresentationSelector {
|
| // Depending on the operator, propagate new usage info to the inputs.
|
| void VisitNode(Node* node, Truncation truncation,
|
| SimplifiedLowering* lowering) {
|
| + // Unconditionally eliminate unused pure nodes (only relevant if there's
|
| + // a pure operation in between two effectful ones, where the last one
|
| + // is unused).
|
| + if (node->op()->HasProperty(Operator::kPure) && truncation.IsUnused()) {
|
| + return VisitUnused(node);
|
| + }
|
| switch (node->opcode()) {
|
| //------------------------------------------------------------------
|
| // Common operators.
|
| //------------------------------------------------------------------
|
| case IrOpcode::kStart:
|
| + // We use Start as a terminator for the frame state chain, so even
|
| + // tho Start doesn't really produce a value, we have to say Tagged
|
| + // here, otherwise the input conversion will fail.
|
| + return VisitLeaf(node, MachineRepresentation::kTagged);
|
| case IrOpcode::kDead:
|
| return VisitLeaf(node, MachineRepresentation::kNone);
|
| case IrOpcode::kParameter: {
|
| @@ -1284,6 +1310,7 @@ class RepresentationSelector {
|
| case IrOpcode::kSpeculativeNumberLessThan:
|
| case IrOpcode::kSpeculativeNumberLessThanOrEqual:
|
| case IrOpcode::kSpeculativeNumberEqual: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| // Number comparisons reduce to integer comparisons for integer inputs.
|
| if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
|
| TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
|
| @@ -1338,6 +1365,7 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberMultiply: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| if (BothInputsAre(node, Type::Integral32()) &&
|
| (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
|
| NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
|
| @@ -1412,6 +1440,7 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberDivide: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
|
| // => unsigned Uint32Div
|
| VisitWord32TruncatingBinop(node);
|
| @@ -1517,6 +1546,7 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberModulus: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
|
| // => unsigned Uint32Mod
|
| VisitWord32TruncatingBinop(node);
|
| @@ -1630,6 +1660,7 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kSpeculativeNumberShiftLeft: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| if (BothInputsAre(node, Type::NumberOrOddball())) {
|
| Type* rhs_type = GetUpperBound(node->InputAt(1));
|
| VisitBinop(node, UseInfo::TruncatingWord32(),
|
| @@ -1941,8 +1972,9 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kLoadField: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| FieldAccess access = FieldAccessOf(node->op());
|
| - MachineRepresentation representation =
|
| + MachineRepresentation const representation =
|
| access.machine_type.representation();
|
| // If we are loading from a Smi field and truncate the result to Word32,
|
| // we can instead just load the high word on 64-bit architectures, which
|
| @@ -1989,6 +2021,7 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kLoadBuffer: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| BufferAccess access = BufferAccessOf(node->op());
|
| ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
|
| ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
|
| @@ -2035,11 +2068,11 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kLoadElement: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| ElementAccess access = ElementAccessOf(node->op());
|
| - ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
|
| - ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
|
| - ProcessRemainingInputs(node, 2);
|
| - SetOutput(node, access.machine_type.representation());
|
| + VisitBinop(node, UseInfoForBasePointer(access),
|
| + UseInfo::TruncatingWord32(),
|
| + access.machine_type.representation());
|
| return;
|
| }
|
| case IrOpcode::kStoreElement: {
|
| @@ -2112,6 +2145,7 @@ class RepresentationSelector {
|
| return;
|
| }
|
| case IrOpcode::kCheckFloat64Hole: {
|
| + if (truncation.IsUnused()) return VisitUnused(node);
|
| CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
|
| ProcessInput(node, 0, UseInfo::TruncatingFloat64());
|
| ProcessRemainingInputs(node, 1);
|
| @@ -2348,6 +2382,27 @@ class RepresentationSelector {
|
| node->NullAllInputs(); // Node is now dead.
|
| }
|
|
|
| + void Kill(Node* node) {
|
| + TRACE("killing #%d:%s\n", node->id(), node->op()->mnemonic());
|
| +
|
| + if (node->op()->EffectInputCount() == 1) {
|
| + 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());
|
| + DCHECK_EQ(0, node->op()->EffectInputCount());
|
| + DCHECK_EQ(0, node->op()->ControlOutputCount());
|
| + DCHECK_EQ(0, node->op()->EffectOutputCount());
|
| + }
|
| +
|
| + node->ReplaceUses(jsgraph_->Dead());
|
| +
|
| + node->NullAllInputs(); // The {node} is now dead.
|
| + }
|
| +
|
| void PrintOutputInfo(NodeInfo* info) {
|
| if (FLAG_trace_representation) {
|
| OFStream os(stdout);
|
|
|