| 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" |
| 11 #include "src/compiler/common-operator.h" | 11 #include "src/compiler/common-operator.h" |
| 12 #include "src/compiler/diamond.h" | 12 #include "src/compiler/diamond.h" |
| 13 #include "src/compiler/linkage.h" | 13 #include "src/compiler/linkage.h" |
| 14 #include "src/compiler/node-matchers.h" | 14 #include "src/compiler/node-matchers.h" |
| 15 #include "src/compiler/node-properties.h" | 15 #include "src/compiler/node-properties.h" |
| 16 #include "src/compiler/operator-properties.h" | 16 #include "src/compiler/operator-properties.h" |
| 17 #include "src/compiler/representation-change.h" | 17 #include "src/compiler/representation-change.h" |
| 18 #include "src/compiler/simplified-operator.h" | 18 #include "src/compiler/simplified-operator.h" |
| 19 #include "src/compiler/source-position.h" | 19 #include "src/compiler/source-position.h" |
| 20 #include "src/objects.h" | 20 #include "src/objects.h" |
| 21 #include "src/type-cache.h" |
| 21 | 22 |
| 22 namespace v8 { | 23 namespace v8 { |
| 23 namespace internal { | 24 namespace internal { |
| 24 namespace compiler { | 25 namespace compiler { |
| 25 | 26 |
| 26 // Macro for outputting trace information from representation inference. | 27 // Macro for outputting trace information from representation inference. |
| 27 #define TRACE(...) \ | 28 #define TRACE(...) \ |
| 28 do { \ | 29 do { \ |
| 29 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \ | 30 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \ |
| 30 } while (false) | 31 } while (false) |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 RepresentationChanger* changer, | 189 RepresentationChanger* changer, |
| 189 SourcePositionTable* source_positions) | 190 SourcePositionTable* source_positions) |
| 190 : jsgraph_(jsgraph), | 191 : jsgraph_(jsgraph), |
| 191 count_(jsgraph->graph()->NodeCount()), | 192 count_(jsgraph->graph()->NodeCount()), |
| 192 info_(count_, zone), | 193 info_(count_, zone), |
| 193 nodes_(zone), | 194 nodes_(zone), |
| 194 replacements_(zone), | 195 replacements_(zone), |
| 195 phase_(PROPAGATE), | 196 phase_(PROPAGATE), |
| 196 changer_(changer), | 197 changer_(changer), |
| 197 queue_(zone), | 198 queue_(zone), |
| 198 source_positions_(source_positions) { | 199 source_positions_(source_positions), |
| 199 safe_int_additive_range_ = | 200 type_cache_(TypeCache::Get()) {} |
| 200 Type::Range(-std::pow(2.0, 52.0), std::pow(2.0, 52.0), zone); | |
| 201 } | |
| 202 | 201 |
| 203 void Run(SimplifiedLowering* lowering) { | 202 void Run(SimplifiedLowering* lowering) { |
| 204 // Run propagation phase to a fixpoint. | 203 // Run propagation phase to a fixpoint. |
| 205 TRACE("--{Propagation phase}--\n"); | 204 TRACE("--{Propagation phase}--\n"); |
| 206 phase_ = PROPAGATE; | 205 phase_ = PROPAGATE; |
| 207 Enqueue(jsgraph_->graph()->end()); | 206 Enqueue(jsgraph_->graph()->end()); |
| 208 // Process nodes from the queue until it is empty. | 207 // Process nodes from the queue until it is empty. |
| 209 while (!queue_.empty()) { | 208 while (!queue_.empty()) { |
| 210 Node* node = queue_.front(); | 209 Node* node = queue_.front(); |
| 211 NodeInfo* info = GetInfo(node); | 210 NodeInfo* info = GetInfo(node); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 } | 559 } |
| 561 | 560 |
| 562 bool CanLowerToInt32AdditiveBinop(Node* node, Truncation use) { | 561 bool CanLowerToInt32AdditiveBinop(Node* node, Truncation use) { |
| 563 // It is safe to lower to word32 operation if: | 562 // It is safe to lower to word32 operation if: |
| 564 // - the inputs are safe integers (so the low bits are not discarded), and | 563 // - the inputs are safe integers (so the low bits are not discarded), and |
| 565 // - the uses can only observe the lowest 32 bits or they can recover the | 564 // - the uses can only observe the lowest 32 bits or they can recover the |
| 566 // the value from the type. | 565 // the value from the type. |
| 567 // TODO(jarin): we could support the uint32 case here, but that would | 566 // TODO(jarin): we could support the uint32 case here, but that would |
| 568 // require setting kTypeUint32 as the output type. Eventually, we will want | 567 // require setting kTypeUint32 as the output type. Eventually, we will want |
| 569 // to use only the big types, then this should work automatically. | 568 // to use only the big types, then this should work automatically. |
| 570 return BothInputsAre(node, safe_int_additive_range_) && | 569 return BothInputsAre(node, type_cache_.kAdditiveSafeInteger) && |
| 571 (use.TruncatesToWord32() || | 570 (use.TruncatesToWord32() || |
| 572 NodeProperties::GetType(node)->Is(Type::Signed32())); | 571 NodeProperties::GetType(node)->Is(Type::Signed32())); |
| 573 } | 572 } |
| 574 | 573 |
| 574 bool CanLowerToInt32MultiplicativeBinop(Node* node, Truncation use) { |
| 575 return BothInputsAre(node, Type::Signed32()) && |
| 576 (NodeProperties::GetType(node)->Is(Type::Signed32()) || |
| 577 (use.TruncatesToWord32() && |
| 578 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))); |
| 579 } |
| 580 |
| 575 // Dispatching routine for visiting the node {node} with the usage {use}. | 581 // Dispatching routine for visiting the node {node} with the usage {use}. |
| 576 // Depending on the operator, propagate new usage info to the inputs. | 582 // Depending on the operator, propagate new usage info to the inputs. |
| 577 void VisitNode(Node* node, Truncation truncation, | 583 void VisitNode(Node* node, Truncation truncation, |
| 578 SimplifiedLowering* lowering) { | 584 SimplifiedLowering* lowering) { |
| 579 switch (node->opcode()) { | 585 switch (node->opcode()) { |
| 580 //------------------------------------------------------------------ | 586 //------------------------------------------------------------------ |
| 581 // Common operators. | 587 // Common operators. |
| 582 //------------------------------------------------------------------ | 588 //------------------------------------------------------------------ |
| 583 case IrOpcode::kStart: | 589 case IrOpcode::kStart: |
| 584 case IrOpcode::kDead: | 590 case IrOpcode::kDead: |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 VisitInt32Binop(node); | 708 VisitInt32Binop(node); |
| 703 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 709 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 704 } else { | 710 } else { |
| 705 // => Float64Add/Sub | 711 // => Float64Add/Sub |
| 706 VisitFloat64Binop(node); | 712 VisitFloat64Binop(node); |
| 707 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 713 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
| 708 } | 714 } |
| 709 break; | 715 break; |
| 710 } | 716 } |
| 711 case IrOpcode::kNumberMultiply: { | 717 case IrOpcode::kNumberMultiply: { |
| 712 NumberMatcher right(node->InputAt(1)); | 718 // Multiply reduces to Int32Mul if the inputs are |
| 713 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. | 719 // already integers and all uses are truncating. |
| 714 if (CanLowerToInt32Binop(node, truncation)) { | 720 if (CanLowerToInt32MultiplicativeBinop(node, truncation)) { |
| 715 // => signed Int32Mul | 721 // => signed Int32Mul |
| 716 VisitInt32Binop(node); | 722 VisitInt32Binop(node); |
| 717 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 723 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 718 break; | 724 } else { |
| 719 } | 725 // => Float64Mul |
| 726 VisitFloat64Binop(node); |
| 727 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
| 720 } | 728 } |
| 721 // => Float64Mul | |
| 722 VisitFloat64Binop(node); | |
| 723 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | |
| 724 break; | 729 break; |
| 725 } | 730 } |
| 726 case IrOpcode::kNumberDivide: { | 731 case IrOpcode::kNumberDivide: { |
| 727 if (CanLowerToInt32Binop(node, truncation)) { | 732 if (CanLowerToInt32Binop(node, truncation)) { |
| 728 // => signed Int32Div | 733 // => signed Int32Div |
| 729 VisitInt32Binop(node); | 734 VisitInt32Binop(node); |
| 730 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 735 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
| 731 break; | 736 break; |
| 732 } | 737 } |
| 733 if (BothInputsAre(node, Type::Unsigned32()) && | 738 if (BothInputsAre(node, Type::Unsigned32()) && |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 NodeVector replacements_; // replacements to be done after lowering | 1158 NodeVector replacements_; // replacements to be done after lowering |
| 1154 Phase phase_; // current phase of algorithm | 1159 Phase phase_; // current phase of algorithm |
| 1155 RepresentationChanger* changer_; // for inserting representation changes | 1160 RepresentationChanger* changer_; // for inserting representation changes |
| 1156 ZoneQueue<Node*> queue_; // queue for traversing the graph | 1161 ZoneQueue<Node*> queue_; // queue for traversing the graph |
| 1157 // TODO(danno): RepresentationSelector shouldn't know anything about the | 1162 // TODO(danno): RepresentationSelector shouldn't know anything about the |
| 1158 // source positions table, but must for now since there currently is no other | 1163 // source positions table, but must for now since there currently is no other |
| 1159 // way to pass down source position information to nodes created during | 1164 // way to pass down source position information to nodes created during |
| 1160 // lowering. Once this phase becomes a vanilla reducer, it should get source | 1165 // lowering. Once this phase becomes a vanilla reducer, it should get source |
| 1161 // position information via the SourcePositionWrapper like all other reducers. | 1166 // position information via the SourcePositionWrapper like all other reducers. |
| 1162 SourcePositionTable* source_positions_; | 1167 SourcePositionTable* source_positions_; |
| 1163 Type* safe_int_additive_range_; | 1168 TypeCache const& type_cache_; |
| 1164 | 1169 |
| 1165 NodeInfo* GetInfo(Node* node) { | 1170 NodeInfo* GetInfo(Node* node) { |
| 1166 DCHECK(node->id() >= 0); | 1171 DCHECK(node->id() >= 0); |
| 1167 DCHECK(node->id() < count_); | 1172 DCHECK(node->id() < count_); |
| 1168 return &info_[node->id()]; | 1173 return &info_[node->id()]; |
| 1169 } | 1174 } |
| 1170 }; | 1175 }; |
| 1171 | 1176 |
| 1172 | 1177 |
| 1173 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, | 1178 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, |
| 1174 SourcePositionTable* source_positions) | 1179 SourcePositionTable* source_positions) |
| 1175 : jsgraph_(jsgraph), | 1180 : jsgraph_(jsgraph), |
| 1176 zone_(zone), | 1181 zone_(zone), |
| 1177 zero_thirtyone_range_(Type::Range(0, 31, zone)), | 1182 type_cache_(TypeCache::Get()), |
| 1178 source_positions_(source_positions) {} | 1183 source_positions_(source_positions) {} |
| 1179 | 1184 |
| 1180 | 1185 |
| 1181 void SimplifiedLowering::LowerAllNodes() { | 1186 void SimplifiedLowering::LowerAllNodes() { |
| 1182 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); | 1187 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); |
| 1183 RepresentationSelector selector(jsgraph(), zone_, &changer, | 1188 RepresentationSelector selector(jsgraph(), zone_, &changer, |
| 1184 source_positions_); | 1189 source_positions_); |
| 1185 selector.Run(this); | 1190 selector.Run(this); |
| 1186 } | 1191 } |
| 1187 | 1192 |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 Node* false0 = zero; | 1553 Node* false0 = zero; |
| 1549 | 1554 |
| 1550 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); | 1555 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0); |
| 1551 return graph()->NewNode(phi_op, true0, false0, merge0); | 1556 return graph()->NewNode(phi_op, true0, false0, merge0); |
| 1552 } | 1557 } |
| 1553 | 1558 |
| 1554 | 1559 |
| 1555 void SimplifiedLowering::DoShift(Node* node, Operator const* op) { | 1560 void SimplifiedLowering::DoShift(Node* node, Operator const* op) { |
| 1556 Node* const rhs = NodeProperties::GetValueInput(node, 1); | 1561 Node* const rhs = NodeProperties::GetValueInput(node, 1); |
| 1557 Type* const rhs_type = NodeProperties::GetType(rhs); | 1562 Type* const rhs_type = NodeProperties::GetType(rhs); |
| 1558 if (!rhs_type->Is(zero_thirtyone_range_)) { | 1563 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) { |
| 1559 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, | 1564 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs, |
| 1560 jsgraph()->Int32Constant(0x1f))); | 1565 jsgraph()->Int32Constant(0x1f))); |
| 1561 } | 1566 } |
| 1562 NodeProperties::ChangeOp(node, op); | 1567 NodeProperties::ChangeOp(node, op); |
| 1563 } | 1568 } |
| 1564 | 1569 |
| 1565 | 1570 |
| 1566 namespace { | 1571 namespace { |
| 1567 | 1572 |
| 1568 void ReplaceEffectUses(Node* node, Node* replacement) { | 1573 void ReplaceEffectUses(Node* node, Node* replacement) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 ReplaceEffectUses(node, comparison); | 1610 ReplaceEffectUses(node, comparison); |
| 1606 node->ReplaceInput(0, comparison); | 1611 node->ReplaceInput(0, comparison); |
| 1607 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1612 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 1608 node->TrimInputCount(2); | 1613 node->TrimInputCount(2); |
| 1609 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); | 1614 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual()); |
| 1610 } | 1615 } |
| 1611 | 1616 |
| 1612 } // namespace compiler | 1617 } // namespace compiler |
| 1613 } // namespace internal | 1618 } // namespace internal |
| 1614 } // namespace v8 | 1619 } // namespace v8 |
| OLD | NEW |