| Index: src/compiler/simplified-lowering.cc
|
| diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
| index 26b6bd35df8ed83fcf986408de3a8cf0057de532..fb0a41fb27a2351c62017bb17c4cfde67cf6b291 100644
|
| --- a/src/compiler/simplified-lowering.cc
|
| +++ b/src/compiler/simplified-lowering.cc
|
| @@ -74,6 +74,10 @@ class RepresentationSelector {
|
| changer_(changer),
|
| queue_(zone) {
|
| memset(info_, 0, sizeof(NodeInfo) * count_);
|
| +
|
| + Factory* f = zone->isolate()->factory();
|
| + safe_int_additive_range_ =
|
| + Type::Range(f->NewNumber(-pow(2, 52)), f->NewNumber(pow(2, 52)), zone);
|
| }
|
|
|
| void Run(SimplifiedLowering* lowering) {
|
| @@ -167,6 +171,30 @@ class RepresentationSelector {
|
| NodeProperties::GetBounds(node->InputAt(1)).upper->Is(type);
|
| }
|
|
|
| + void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) {
|
| + Node* input = node->InputAt(index);
|
| + if (phase_ == PROPAGATE) {
|
| + // In the propagate phase, propagate the usage information backward.
|
| + Enqueue(input, use);
|
| + } else {
|
| + // In the change phase, insert a change before the use if necessary.
|
| + MachineTypeUnion output = GetInfo(input)->output;
|
| + if ((output & kRepWord32) == 0) {
|
| + // Output representation doesn't match usage.
|
| + TRACE((" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(),
|
| + node->op()->mnemonic(), index, input->id(),
|
| + input->op()->mnemonic()));
|
| + TRACE((" from "));
|
| + PrintInfo(output);
|
| + TRACE((" to "));
|
| + PrintInfo(use);
|
| + TRACE(("\n"));
|
| + Node* n = changer_->GetTruncatedWord32For(input, output);
|
| + node->ReplaceInput(index, n);
|
| + }
|
| + }
|
| + }
|
| +
|
| void ProcessInput(Node* node, int index, MachineTypeUnion use) {
|
| Node* input = node->InputAt(index);
|
| if (phase_ == PROPAGATE) {
|
| @@ -371,10 +399,31 @@ class RepresentationSelector {
|
| return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use);
|
| }
|
|
|
| + bool IsSafeIntAdditiveOperand(Node* node) {
|
| + Type* type = NodeProperties::GetBounds(node).upper;
|
| + // TODO(jarin): Unfortunately, bitset types are not subtypes of larger
|
| + // range types, so we have to explicitly check for Integral32 here
|
| + // (in addition to the safe integer range). Once we fix subtyping for
|
| + // ranges, we should simplify this.
|
| + return type->Is(safe_int_additive_range_) || type->Is(Type::Integral32());
|
| + }
|
| +
|
| + bool CanLowerToInt32AdditiveBinop(Node* node, MachineTypeUnion use) {
|
| + return IsSafeIntAdditiveOperand(node->InputAt(0)) &&
|
| + IsSafeIntAdditiveOperand(node->InputAt(1)) &&
|
| + !CanObserveNonInt32(use);
|
| + }
|
| +
|
| bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) {
|
| return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use);
|
| }
|
|
|
| + bool CanLowerToUint32AdditiveBinop(Node* node, MachineTypeUnion use) {
|
| + return IsSafeIntAdditiveOperand(node->InputAt(0)) &&
|
| + IsSafeIntAdditiveOperand(node->InputAt(1)) &&
|
| + !CanObserveNonUint32(use);
|
| + }
|
| +
|
| bool CanObserveNonInt32(MachineTypeUnion use) {
|
| return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0;
|
| }
|
| @@ -516,10 +565,22 @@ class RepresentationSelector {
|
| // => signed Int32Add/Sub
|
| VisitInt32Binop(node);
|
| if (lower()) node->set_op(Int32Op(node));
|
| + } else if (CanLowerToInt32AdditiveBinop(node, use)) {
|
| + // => signed Int32Add/Sub, truncating inputs
|
| + ProcessTruncateWord32Input(node, 0, kTypeInt32);
|
| + ProcessTruncateWord32Input(node, 1, kTypeInt32);
|
| + SetOutput(node, kMachInt32);
|
| + if (lower()) node->set_op(Int32Op(node));
|
| } else if (CanLowerToUint32Binop(node, use)) {
|
| // => unsigned Int32Add/Sub
|
| VisitUint32Binop(node);
|
| if (lower()) node->set_op(Uint32Op(node));
|
| + } else if (CanLowerToUint32AdditiveBinop(node, use)) {
|
| + // => signed Int32Add/Sub, truncating inputs
|
| + ProcessTruncateWord32Input(node, 0, kTypeUint32);
|
| + ProcessTruncateWord32Input(node, 1, kTypeUint32);
|
| + SetOutput(node, kMachUint32);
|
| + if (lower()) node->set_op(Uint32Op(node));
|
| } else {
|
| // => Float64Add/Sub
|
| VisitFloat64Binop(node);
|
| @@ -915,6 +976,7 @@ class RepresentationSelector {
|
| Phase phase_; // current phase of algorithm
|
| RepresentationChanger* changer_; // for inserting representation changes
|
| ZoneQueue<Node*> queue_; // queue for traversing the graph
|
| + Type* safe_int_additive_range_;
|
|
|
| NodeInfo* GetInfo(Node* node) {
|
| DCHECK(node->id() >= 0);
|
|
|