Index: src/compiler/simplified-lowering.cc |
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
index 20c8a567dba11c77fbe0fc824ce8ad204c12e729..a0cb0378dedc8f130051b30d8beebec478e61a40 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); |