| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index 4619d25d5db638500a592ef04947571390ae8035..3fc735a09c0ff00c5b1507de49159a22a104b34f 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -8,6 +8,7 @@
|
| #include "src/code-factory.h"
|
| #include "src/compiler/common-operator.h"
|
| #include "src/compiler/graph-inl.h"
|
| +#include "src/compiler/node-matchers.h"
|
| #include "src/compiler/node-properties-inl.h"
|
| #include "src/compiler/representation-change.h"
|
| #include "src/compiler/simplified-lowering.h"
|
| @@ -354,6 +355,27 @@ class RepresentationSelector {
|
| return changer_->Float64OperatorFor(node->opcode());
|
| }
|
|
|
| + bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) {
|
| + return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use);
|
| + }
|
| +
|
| + bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) {
|
| + return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use);
|
| + }
|
| +
|
| + bool CanObserveNonInt32(MachineTypeUnion use) {
|
| + return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0;
|
| + }
|
| +
|
| + bool CanObserveMinusZero(MachineTypeUnion use) {
|
| + // TODO(turbofan): technically Uint32 cannot observe minus zero either.
|
| + return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0;
|
| + }
|
| +
|
| + bool CanObserveNonUint32(MachineTypeUnion use) {
|
| + return (use & (kTypeInt32 | kTypeNumber | kTypeAny)) != 0;
|
| + }
|
| +
|
| // 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, MachineTypeUnion use,
|
| @@ -478,13 +500,11 @@ class RepresentationSelector {
|
| case IrOpcode::kNumberSubtract: {
|
| // Add and subtract reduce to Int32Add/Sub if the inputs
|
| // are already integers and all uses are truncating.
|
| - if (BothInputsAre(node, Type::Signed32()) &&
|
| - (use & (kTypeUint32 | kTypeNumber | kTypeAny)) == 0) {
|
| + if (CanLowerToInt32Binop(node, use)) {
|
| // => signed Int32Add/Sub
|
| VisitInt32Binop(node);
|
| if (lower()) node->set_op(Int32Op(node));
|
| - } else if (BothInputsAre(node, Type::Unsigned32()) &&
|
| - (use & (kTypeInt32 | kTypeNumber | kTypeAny)) == 0) {
|
| + } else if (CanLowerToUint32Binop(node, use)) {
|
| // => unsigned Int32Add/Sub
|
| VisitUint32Binop(node);
|
| if (lower()) node->set_op(Uint32Op(node));
|
| @@ -495,10 +515,58 @@ class RepresentationSelector {
|
| }
|
| break;
|
| }
|
| - case IrOpcode::kNumberMultiply:
|
| - case IrOpcode::kNumberDivide:
|
| + case IrOpcode::kNumberMultiply: {
|
| + NumberMatcher right(node->InputAt(1));
|
| + if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa.
|
| + if (CanLowerToInt32Binop(node, use)) {
|
| + // => signed Int32Mul
|
| + VisitInt32Binop(node);
|
| + if (lower()) node->set_op(Int32Op(node));
|
| + break;
|
| + }
|
| + }
|
| + // => Float64Mul
|
| + VisitFloat64Binop(node);
|
| + if (lower()) node->set_op(Float64Op(node));
|
| + break;
|
| + }
|
| + case IrOpcode::kNumberDivide: {
|
| + NumberMatcher right(node->InputAt(1));
|
| + if (right.HasValue() && !right.Is(0) && !right.Is(-1)) {
|
| + if (CanLowerToInt32Binop(node, use)) {
|
| + // => signed Int32Div
|
| + VisitInt32Binop(node);
|
| + if (lower()) node->set_op(Int32Op(node));
|
| + break;
|
| + } else if (CanLowerToUint32Binop(node, use)) {
|
| + // => unsigned Uint32Div
|
| + VisitUint32Binop(node);
|
| + if (lower()) node->set_op(Uint32Op(node));
|
| + break;
|
| + }
|
| + }
|
| + // => Float64Div
|
| + VisitFloat64Binop(node);
|
| + if (lower()) node->set_op(Float64Op(node));
|
| + break;
|
| + }
|
| case IrOpcode::kNumberModulus: {
|
| - // Float64Mul/Div/Mod
|
| + NumberMatcher right(node->InputAt(1));
|
| + if (right.HasValue() && !right.Is(0) && !right.Is(-1)) {
|
| + if (BothInputsAre(node, Type::Signed32()) &&
|
| + !CanObserveMinusZero(use)) {
|
| + // => signed Int32Mod
|
| + VisitInt32Binop(node);
|
| + if (lower()) node->set_op(Int32Op(node));
|
| + break;
|
| + } else if (BothInputsAre(node, Type::Unsigned32())) {
|
| + // => unsigned Uint32Mod
|
| + VisitUint32Binop(node);
|
| + if (lower()) node->set_op(Uint32Op(node));
|
| + break;
|
| + }
|
| + }
|
| + // => Float64Mod
|
| VisitFloat64Binop(node);
|
| if (lower()) node->set_op(Float64Op(node));
|
| break;
|
| @@ -507,12 +575,16 @@ class RepresentationSelector {
|
| MachineTypeUnion use_rep = use & kRepMask;
|
| Node* input = node->InputAt(0);
|
| MachineTypeUnion in = GetInfo(input)->output;
|
| - if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32()) ||
|
| - (in & kTypeMask) == kTypeInt32 || (in & kRepMask) == kRepWord32) {
|
| - // If the input has type int32, or is already a word32, just change
|
| - // representation if necessary.
|
| + if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) {
|
| + // If the input has type int32, pass through representation.
|
| VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep);
|
| if (lower()) DeferReplacement(node, node->InputAt(0));
|
| + } else if ((in & kTypeMask) == kTypeUint32 ||
|
| + (in & kTypeMask) == kTypeInt32 ||
|
| + (in & kRepMask) == kRepWord32) {
|
| + // Just change representation if necessary.
|
| + VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32);
|
| + if (lower()) DeferReplacement(node, node->InputAt(0));
|
| } else {
|
| // Require the input in float64 format and perform truncation.
|
| // TODO(turbofan): avoid a truncation with a smi check.
|
| @@ -526,11 +598,16 @@ class RepresentationSelector {
|
| MachineTypeUnion use_rep = use & kRepMask;
|
| Node* input = node->InputAt(0);
|
| MachineTypeUnion in = GetInfo(input)->output;
|
| - if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32()) ||
|
| - (in & kTypeMask) == kTypeUint32) {
|
| - // If the input has type uint32, just change representation.
|
| + if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) {
|
| + // If the input has type uint32, pass through representation.
|
| VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep);
|
| if (lower()) DeferReplacement(node, node->InputAt(0));
|
| + } else if ((in & kTypeMask) == kTypeUint32 ||
|
| + (in & kTypeMask) == kTypeInt32 ||
|
| + (in & kRepMask) == kRepWord32) {
|
| + // Just change representation if necessary.
|
| + VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32);
|
| + if (lower()) DeferReplacement(node, node->InputAt(0));
|
| } else {
|
| // Require the input in float64 format and perform truncation.
|
| // TODO(turbofan): avoid a truncation with a smi check.
|
| @@ -744,6 +821,11 @@ class RepresentationSelector {
|
| }
|
|
|
| void DeferReplacement(Node* node, Node* replacement) {
|
| + if (FLAG_trace_representation) {
|
| + TRACE(("defer replacement #%d:%s with #%d:%s\n", node->id(),
|
| + node->op()->mnemonic(), replacement->id(),
|
| + replacement->op()->mnemonic()));
|
| + }
|
| if (replacement->id() < count_) {
|
| // Replace with a previously existing node eagerly.
|
| node->ReplaceUses(replacement);
|
|
|