OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 : jsgraph_(jsgraph), | 67 : jsgraph_(jsgraph), |
68 count_(jsgraph->graph()->NodeCount()), | 68 count_(jsgraph->graph()->NodeCount()), |
69 info_(zone->NewArray<NodeInfo>(count_)), | 69 info_(zone->NewArray<NodeInfo>(count_)), |
70 nodes_(zone), | 70 nodes_(zone), |
71 replacements_(zone), | 71 replacements_(zone), |
72 contains_js_nodes_(false), | 72 contains_js_nodes_(false), |
73 phase_(PROPAGATE), | 73 phase_(PROPAGATE), |
74 changer_(changer), | 74 changer_(changer), |
75 queue_(zone) { | 75 queue_(zone) { |
76 memset(info_, 0, sizeof(NodeInfo) * count_); | 76 memset(info_, 0, sizeof(NodeInfo) * count_); |
| 77 |
| 78 Factory* f = zone->isolate()->factory(); |
| 79 safe_int_additive_range_ = |
| 80 Type::Range(f->NewNumber(-pow(2, 52)), f->NewNumber(pow(2, 52)), zone); |
77 } | 81 } |
78 | 82 |
79 void Run(SimplifiedLowering* lowering) { | 83 void Run(SimplifiedLowering* lowering) { |
80 // Run propagation phase to a fixpoint. | 84 // Run propagation phase to a fixpoint. |
81 TRACE(("--{Propagation phase}--\n")); | 85 TRACE(("--{Propagation phase}--\n")); |
82 phase_ = PROPAGATE; | 86 phase_ = PROPAGATE; |
83 Enqueue(jsgraph_->graph()->end()); | 87 Enqueue(jsgraph_->graph()->end()); |
84 // Process nodes from the queue until it is empty. | 88 // Process nodes from the queue until it is empty. |
85 while (!queue_.empty()) { | 89 while (!queue_.empty()) { |
86 Node* node = queue_.front(); | 90 Node* node = queue_.front(); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 base::bits::IsPowerOfTwo32(output & kRepMask)); | 164 base::bits::IsPowerOfTwo32(output & kRepMask)); |
161 GetInfo(node)->output = output; | 165 GetInfo(node)->output = output; |
162 } | 166 } |
163 | 167 |
164 bool BothInputsAre(Node* node, Type* type) { | 168 bool BothInputsAre(Node* node, Type* type) { |
165 DCHECK_EQ(2, node->InputCount()); | 169 DCHECK_EQ(2, node->InputCount()); |
166 return NodeProperties::GetBounds(node->InputAt(0)).upper->Is(type) && | 170 return NodeProperties::GetBounds(node->InputAt(0)).upper->Is(type) && |
167 NodeProperties::GetBounds(node->InputAt(1)).upper->Is(type); | 171 NodeProperties::GetBounds(node->InputAt(1)).upper->Is(type); |
168 } | 172 } |
169 | 173 |
| 174 void ProcessTruncateWord32Input(Node* node, int index, MachineTypeUnion use) { |
| 175 Node* input = node->InputAt(index); |
| 176 if (phase_ == PROPAGATE) { |
| 177 // In the propagate phase, propagate the usage information backward. |
| 178 Enqueue(input, use); |
| 179 } else { |
| 180 // In the change phase, insert a change before the use if necessary. |
| 181 MachineTypeUnion output = GetInfo(input)->output; |
| 182 if ((output & kRepWord32) == 0) { |
| 183 // Output representation doesn't match usage. |
| 184 TRACE((" truncate-to-int32: #%d:%s(@%d #%d:%s) ", node->id(), |
| 185 node->op()->mnemonic(), index, input->id(), |
| 186 input->op()->mnemonic())); |
| 187 TRACE((" from ")); |
| 188 PrintInfo(output); |
| 189 TRACE((" to ")); |
| 190 PrintInfo(use); |
| 191 TRACE(("\n")); |
| 192 Node* n = changer_->GetTruncatedWord32For(input, output); |
| 193 node->ReplaceInput(index, n); |
| 194 } |
| 195 } |
| 196 } |
| 197 |
170 void ProcessInput(Node* node, int index, MachineTypeUnion use) { | 198 void ProcessInput(Node* node, int index, MachineTypeUnion use) { |
171 Node* input = node->InputAt(index); | 199 Node* input = node->InputAt(index); |
172 if (phase_ == PROPAGATE) { | 200 if (phase_ == PROPAGATE) { |
173 // In the propagate phase, propagate the usage information backward. | 201 // In the propagate phase, propagate the usage information backward. |
174 Enqueue(input, use); | 202 Enqueue(input, use); |
175 } else { | 203 } else { |
176 // In the change phase, insert a change before the use if necessary. | 204 // In the change phase, insert a change before the use if necessary. |
177 if ((use & kRepMask) == 0) return; // No input requirement on the use. | 205 if ((use & kRepMask) == 0) return; // No input requirement on the use. |
178 MachineTypeUnion output = GetInfo(input)->output; | 206 MachineTypeUnion output = GetInfo(input)->output; |
179 if ((output & kRepMask & use) == 0) { | 207 if ((output & kRepMask & use) == 0) { |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 } | 392 } |
365 | 393 |
366 const Operator* Float64Op(Node* node) { | 394 const Operator* Float64Op(Node* node) { |
367 return changer_->Float64OperatorFor(node->opcode()); | 395 return changer_->Float64OperatorFor(node->opcode()); |
368 } | 396 } |
369 | 397 |
370 bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) { | 398 bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) { |
371 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); | 399 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); |
372 } | 400 } |
373 | 401 |
| 402 bool IsSafeIntAdditiveOperand(Node* node) { |
| 403 Type* type = NodeProperties::GetBounds(node).upper; |
| 404 // TODO(jarin): Unfortunately, bitset types are not subtypes of larger |
| 405 // range types, so we have to explicitly check for Integral32 here |
| 406 // (in addition to the safe integer range). Once we fix subtyping for |
| 407 // ranges, we should simplify this. |
| 408 return type->Is(safe_int_additive_range_) || type->Is(Type::Integral32()); |
| 409 } |
| 410 |
| 411 bool CanLowerToInt32AdditiveBinop(Node* node, MachineTypeUnion use) { |
| 412 return IsSafeIntAdditiveOperand(node->InputAt(0)) && |
| 413 IsSafeIntAdditiveOperand(node->InputAt(1)) && |
| 414 !CanObserveNonInt32(use); |
| 415 } |
| 416 |
374 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { | 417 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { |
375 return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use); | 418 return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use); |
376 } | 419 } |
377 | 420 |
| 421 bool CanLowerToUint32AdditiveBinop(Node* node, MachineTypeUnion use) { |
| 422 return IsSafeIntAdditiveOperand(node->InputAt(0)) && |
| 423 IsSafeIntAdditiveOperand(node->InputAt(1)) && |
| 424 !CanObserveNonUint32(use); |
| 425 } |
| 426 |
378 bool CanObserveNonInt32(MachineTypeUnion use) { | 427 bool CanObserveNonInt32(MachineTypeUnion use) { |
379 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; | 428 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; |
380 } | 429 } |
381 | 430 |
382 bool CanObserveMinusZero(MachineTypeUnion use) { | 431 bool CanObserveMinusZero(MachineTypeUnion use) { |
383 // TODO(turbofan): technically Uint32 cannot observe minus zero either. | 432 // TODO(turbofan): technically Uint32 cannot observe minus zero either. |
384 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; | 433 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; |
385 } | 434 } |
386 | 435 |
387 bool CanObserveNonUint32(MachineTypeUnion use) { | 436 bool CanObserveNonUint32(MachineTypeUnion use) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 break; | 558 break; |
510 } | 559 } |
511 case IrOpcode::kNumberAdd: | 560 case IrOpcode::kNumberAdd: |
512 case IrOpcode::kNumberSubtract: { | 561 case IrOpcode::kNumberSubtract: { |
513 // Add and subtract reduce to Int32Add/Sub if the inputs | 562 // Add and subtract reduce to Int32Add/Sub if the inputs |
514 // are already integers and all uses are truncating. | 563 // are already integers and all uses are truncating. |
515 if (CanLowerToInt32Binop(node, use)) { | 564 if (CanLowerToInt32Binop(node, use)) { |
516 // => signed Int32Add/Sub | 565 // => signed Int32Add/Sub |
517 VisitInt32Binop(node); | 566 VisitInt32Binop(node); |
518 if (lower()) node->set_op(Int32Op(node)); | 567 if (lower()) node->set_op(Int32Op(node)); |
| 568 } else if (CanLowerToInt32AdditiveBinop(node, use)) { |
| 569 // => signed Int32Add/Sub, truncating inputs |
| 570 ProcessTruncateWord32Input(node, 0, kTypeInt32); |
| 571 ProcessTruncateWord32Input(node, 1, kTypeInt32); |
| 572 SetOutput(node, kMachInt32); |
| 573 if (lower()) node->set_op(Int32Op(node)); |
519 } else if (CanLowerToUint32Binop(node, use)) { | 574 } else if (CanLowerToUint32Binop(node, use)) { |
520 // => unsigned Int32Add/Sub | 575 // => unsigned Int32Add/Sub |
521 VisitUint32Binop(node); | 576 VisitUint32Binop(node); |
522 if (lower()) node->set_op(Uint32Op(node)); | 577 if (lower()) node->set_op(Uint32Op(node)); |
| 578 } else if (CanLowerToUint32AdditiveBinop(node, use)) { |
| 579 // => signed Int32Add/Sub, truncating inputs |
| 580 ProcessTruncateWord32Input(node, 0, kTypeUint32); |
| 581 ProcessTruncateWord32Input(node, 1, kTypeUint32); |
| 582 SetOutput(node, kMachUint32); |
| 583 if (lower()) node->set_op(Uint32Op(node)); |
523 } else { | 584 } else { |
524 // => Float64Add/Sub | 585 // => Float64Add/Sub |
525 VisitFloat64Binop(node); | 586 VisitFloat64Binop(node); |
526 if (lower()) node->set_op(Float64Op(node)); | 587 if (lower()) node->set_op(Float64Op(node)); |
527 } | 588 } |
528 break; | 589 break; |
529 } | 590 } |
530 case IrOpcode::kNumberMultiply: { | 591 case IrOpcode::kNumberMultiply: { |
531 NumberMatcher right(node->InputAt(1)); | 592 NumberMatcher right(node->InputAt(1)); |
532 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. | 593 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 private: | 969 private: |
909 JSGraph* jsgraph_; | 970 JSGraph* jsgraph_; |
910 int count_; // number of nodes in the graph | 971 int count_; // number of nodes in the graph |
911 NodeInfo* info_; // node id -> usage information | 972 NodeInfo* info_; // node id -> usage information |
912 NodeVector nodes_; // collected nodes | 973 NodeVector nodes_; // collected nodes |
913 NodeVector replacements_; // replacements to be done after lowering | 974 NodeVector replacements_; // replacements to be done after lowering |
914 bool contains_js_nodes_; // {true} if a JS operator was seen | 975 bool contains_js_nodes_; // {true} if a JS operator was seen |
915 Phase phase_; // current phase of algorithm | 976 Phase phase_; // current phase of algorithm |
916 RepresentationChanger* changer_; // for inserting representation changes | 977 RepresentationChanger* changer_; // for inserting representation changes |
917 ZoneQueue<Node*> queue_; // queue for traversing the graph | 978 ZoneQueue<Node*> queue_; // queue for traversing the graph |
| 979 Type* safe_int_additive_range_; |
918 | 980 |
919 NodeInfo* GetInfo(Node* node) { | 981 NodeInfo* GetInfo(Node* node) { |
920 DCHECK(node->id() >= 0); | 982 DCHECK(node->id() >= 0); |
921 DCHECK(node->id() < count_); | 983 DCHECK(node->id() < count_); |
922 return &info_[node->id()]; | 984 return &info_[node->id()]; |
923 } | 985 } |
924 | 986 |
925 MachineTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; } | 987 MachineTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; } |
926 }; | 988 }; |
927 | 989 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1230 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
1169 node->set_op(machine()->IntLessThanOrEqual()); | 1231 node->set_op(machine()->IntLessThanOrEqual()); |
1170 node->ReplaceInput(0, StringComparison(node, true)); | 1232 node->ReplaceInput(0, StringComparison(node, true)); |
1171 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1233 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
1172 } | 1234 } |
1173 | 1235 |
1174 | 1236 |
1175 } // namespace compiler | 1237 } // namespace compiler |
1176 } // namespace internal | 1238 } // namespace internal |
1177 } // namespace v8 | 1239 } // namespace v8 |
OLD | NEW |