| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index e6f0e1b1ea5f01e4b947021a25cfdf9b60c0cc1a..edff4268b139168a8ab3447488018a1c925bb40e 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -411,15 +411,56 @@ class RepresentationSelector {
|
|
|
| bool lower() { return phase_ == LOWER; }
|
|
|
| + void EnqueueUses(Node* node) {
|
| + for (Edge edge : node->use_edges()) {
|
| + if (NodeProperties::IsValueEdge(edge)) {
|
| + Node* const user = edge.from();
|
| + if (user->id() < count_) {
|
| + // New type information for the node is available.
|
| + NodeInfo* info = GetInfo(user);
|
| + // Enqueue the node only if we are sure it is reachable from
|
| + // the end and it has not been queued yet.
|
| + if (info->visited() && !info->queued()) {
|
| + queue_.push(user);
|
| + info->set_queued(true);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| void SetOutput(Node* node, MachineType output) {
|
| // 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()) {
|
| + EnqueueUses(node);
|
| + }
|
| info->set_output_type(output);
|
| }
|
|
|
| + 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)) &&
|
| + (NodeProperties::GetType(node->InputAt(1))->Is(Type::Signed32()) ||
|
| + (GetInfo(node->InputAt(1))->output_type().semantic() ==
|
| + MachineSemantic::kInt32));
|
| + }
|
| +
|
| + 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) &&
|
| + (NodeProperties::GetType(node->InputAt(1))->Is(Type::Unsigned32()) ||
|
| + GetInfo(node->InputAt(1))->output_type().semantic() ==
|
| + MachineSemantic::kUint32);
|
| + }
|
| +
|
| bool BothInputsAre(Node* node, Type* type) {
|
| DCHECK_EQ(2, node->InputCount());
|
| return NodeProperties::GetType(node->InputAt(0))->Is(type) &&
|
| @@ -522,6 +563,11 @@ class RepresentationSelector {
|
| void VisitInt32Binop(Node* node) {
|
| VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Int32());
|
| }
|
| + void VisitWord32TruncatingBinop(Node* node) {
|
| + VisitBinop(
|
| + node, UseInfo::TruncatingWord32(),
|
| + MachineType(MachineRepresentation::kWord32, MachineSemantic::kNumber));
|
| + }
|
| void VisitUint32Binop(Node* node) {
|
| VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Uint32());
|
| }
|
| @@ -680,29 +726,24 @@ class RepresentationSelector {
|
| }
|
|
|
| bool CanLowerToInt32Binop(Node* node, Truncation use) {
|
| - return BothInputsAre(node, Type::Signed32()) &&
|
| - (use.TruncatesToWord32() ||
|
| - NodeProperties::GetType(node)->Is(Type::Signed32()));
|
| + 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 or they can recover the
|
| - // the value from the type.
|
| + // - 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() ||
|
| - NodeProperties::GetType(node)->Is(Type::Signed32()));
|
| + use.TruncatesToWord32();
|
| }
|
|
|
| bool CanLowerToInt32MultiplicativeBinop(Node* node, Truncation use) {
|
| - return BothInputsAre(node, Type::Signed32()) &&
|
| - (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
|
| - (use.TruncatesToWord32() &&
|
| - NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)));
|
| + return BothInputsAreSigned32(node) && use.TruncatesToWord32() &&
|
| + NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger);
|
| }
|
|
|
| // Dispatching routine for visiting the node {node} with the usage {use}.
|
| @@ -812,11 +853,11 @@ class RepresentationSelector {
|
| case IrOpcode::kNumberLessThan:
|
| case IrOpcode::kNumberLessThanOrEqual: {
|
| // Number comparisons reduce to integer comparisons for integer inputs.
|
| - if (BothInputsAre(node, Type::Signed32())) {
|
| + if (BothInputsAreSigned32(node)) {
|
| // => signed Int32Cmp
|
| VisitInt32Cmp(node);
|
| if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
|
| - } else if (BothInputsAre(node, Type::Unsigned32())) {
|
| + } else if (BothInputsAreUnsigned32(node)) {
|
| // => unsigned Int32Cmp
|
| VisitUint32Cmp(node);
|
| if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
|
| @@ -830,8 +871,9 @@ class RepresentationSelector {
|
| case IrOpcode::kNumberAdd:
|
| case IrOpcode::kNumberSubtract: {
|
| // Add and subtract reduce to Int32Add/Sub if the inputs
|
| - // are already integers and all uses are truncating.
|
| - if (CanLowerToInt32AdditiveBinop(node, truncation)) {
|
| + // are safe integers and all uses are truncating.
|
| + if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
|
| + truncation.TruncatesToWord32()) {
|
| // => signed Int32Add/Sub
|
| VisitInt32Binop(node);
|
| if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
|
| @@ -843,30 +885,47 @@ class RepresentationSelector {
|
| break;
|
| }
|
| case IrOpcode::kNumberMultiply: {
|
| - // Multiply reduces to Int32Mul if the inputs are
|
| - // already integers and all uses are truncating.
|
| - if (CanLowerToInt32MultiplicativeBinop(node, truncation)) {
|
| - // => signed Int32Mul
|
| - VisitInt32Binop(node);
|
| - if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
|
| - } else {
|
| - // => Float64Mul
|
| - VisitFloat64Binop(node);
|
| - if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
|
| + 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()) NodeProperties::ChangeOp(node, Int32Op(node));
|
| + break;
|
| + }
|
| + if (truncation.TruncatesToWord32() &&
|
| + NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
|
| + // 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()) NodeProperties::ChangeOp(node, Int32Op(node));
|
| + break;
|
| + }
|
| }
|
| + // => Float64Mul
|
| + VisitFloat64Binop(node);
|
| + if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
|
| break;
|
| }
|
| case IrOpcode::kNumberDivide: {
|
| - if (CanLowerToInt32Binop(node, truncation)) {
|
| + if (BothInputsAreSigned32(node)) {
|
| + if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
|
| // => signed Int32Div
|
| VisitInt32Binop(node);
|
| if (lower()) DeferReplacement(node, lowering->Int32Div(node));
|
| break;
|
| + }
|
| + if (truncation.TruncatesToWord32()) {
|
| + // => signed Int32Div
|
| + VisitWord32TruncatingBinop(node);
|
| + if (lower()) DeferReplacement(node, lowering->Int32Div(node));
|
| + break;
|
| + }
|
| }
|
| - if (BothInputsAre(node, Type::Unsigned32()) &&
|
| - truncation.TruncatesNaNToZero()) {
|
| + if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
|
| // => unsigned Uint32Div
|
| - VisitUint32Binop(node);
|
| + VisitWord32TruncatingBinop(node);
|
| if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
|
| break;
|
| }
|
| @@ -876,16 +935,23 @@ class RepresentationSelector {
|
| break;
|
| }
|
| case IrOpcode::kNumberModulus: {
|
| - if (CanLowerToInt32Binop(node, truncation)) {
|
| - // => signed Int32Mod
|
| - VisitInt32Binop(node);
|
| - if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
|
| - break;
|
| + if (BothInputsAreSigned32(node)) {
|
| + if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
|
| + // => signed Int32Mod
|
| + VisitInt32Binop(node);
|
| + if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
|
| + break;
|
| + }
|
| + if (truncation.TruncatesToWord32()) {
|
| + // => signed Int32Mod
|
| + VisitWord32TruncatingBinop(node);
|
| + if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
|
| + break;
|
| + }
|
| }
|
| - if (BothInputsAre(node, Type::Unsigned32()) &&
|
| - truncation.TruncatesNaNToZero()) {
|
| + if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
|
| // => unsigned Uint32Mod
|
| - VisitUint32Binop(node);
|
| + VisitWord32TruncatingBinop(node);
|
| if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
|
| break;
|
| }
|
|
|