| 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 count_(jsgraph->graph()->NodeCount()), | 70 count_(jsgraph->graph()->NodeCount()), |
| 71 info_(zone->NewArray<NodeInfo>(count_)), | 71 info_(zone->NewArray<NodeInfo>(count_)), |
| 72 nodes_(zone), | 72 nodes_(zone), |
| 73 replacements_(zone), | 73 replacements_(zone), |
| 74 phase_(PROPAGATE), | 74 phase_(PROPAGATE), |
| 75 changer_(changer), | 75 changer_(changer), |
| 76 queue_(zone) { | 76 queue_(zone) { |
| 77 memset(info_, 0, sizeof(NodeInfo) * count_); | 77 memset(info_, 0, sizeof(NodeInfo) * count_); |
| 78 | 78 |
| 79 Factory* f = zone->isolate()->factory(); | 79 Factory* f = zone->isolate()->factory(); |
| 80 safe_bit_range_ = |
| 81 Type::Union(Type::Boolean(), |
| 82 Type::Range(f->NewNumber(0), f->NewNumber(1), zone), zone); |
| 80 safe_int_additive_range_ = | 83 safe_int_additive_range_ = |
| 81 Type::Range(f->NewNumber(-std::pow(2.0, 52.0)), | 84 Type::Range(f->NewNumber(-std::pow(2.0, 52.0)), |
| 82 f->NewNumber(std::pow(2.0, 52.0)), zone); | 85 f->NewNumber(std::pow(2.0, 52.0)), zone); |
| 83 } | 86 } |
| 84 | 87 |
| 85 void Run(SimplifiedLowering* lowering) { | 88 void Run(SimplifiedLowering* lowering) { |
| 86 // Run propagation phase to a fixpoint. | 89 // Run propagation phase to a fixpoint. |
| 87 TRACE(("--{Propagation phase}--\n")); | 90 TRACE(("--{Propagation phase}--\n")); |
| 88 phase_ = PROPAGATE; | 91 phase_ = PROPAGATE; |
| 89 Enqueue(jsgraph_->graph()->end()); | 92 Enqueue(jsgraph_->graph()->end()); |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 // multiple uses, but we are within 32 bits range => pick kRepWord32. | 316 // multiple uses, but we are within 32 bits range => pick kRepWord32. |
| 314 return kRepWord32; | 317 return kRepWord32; |
| 315 } else if ((use & kRepMask) == kRepWord32 || | 318 } else if ((use & kRepMask) == kRepWord32 || |
| 316 (use & kTypeMask) == kTypeInt32 || | 319 (use & kTypeMask) == kTypeInt32 || |
| 317 (use & kTypeMask) == kTypeUint32) { | 320 (use & kTypeMask) == kTypeUint32) { |
| 318 // The type is a safe integer, but we only use 32 bits. | 321 // The type is a safe integer, but we only use 32 bits. |
| 319 return kRepWord32; | 322 return kRepWord32; |
| 320 } else { | 323 } else { |
| 321 return kRepFloat64; | 324 return kRepFloat64; |
| 322 } | 325 } |
| 323 } else if (upper->Is(Type::Boolean())) { | 326 } else if (IsSafeBitOperand(node)) { |
| 324 // multiple uses => pick kRepBit. | 327 // multiple uses => pick kRepBit. |
| 325 return kRepBit; | 328 return kRepBit; |
| 326 } else if (upper->Is(Type::Number())) { | 329 } else if (upper->Is(Type::Number())) { |
| 327 // multiple uses => pick kRepFloat64. | 330 // multiple uses => pick kRepFloat64. |
| 328 return kRepFloat64; | 331 return kRepFloat64; |
| 329 } | 332 } |
| 330 return kRepTagged; | 333 return kRepTagged; |
| 331 } | 334 } |
| 332 | 335 |
| 333 // Helper for handling selects. | 336 // Helper for handling selects. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 } | 410 } |
| 408 | 411 |
| 409 const Operator* Float64Op(Node* node) { | 412 const Operator* Float64Op(Node* node) { |
| 410 return changer_->Float64OperatorFor(node->opcode()); | 413 return changer_->Float64OperatorFor(node->opcode()); |
| 411 } | 414 } |
| 412 | 415 |
| 413 bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) { | 416 bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) { |
| 414 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); | 417 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); |
| 415 } | 418 } |
| 416 | 419 |
| 420 bool IsSafeBitOperand(Node* node) { |
| 421 Type* type = NodeProperties::GetBounds(node).upper; |
| 422 return type->Is(safe_bit_range_); |
| 423 } |
| 424 |
| 417 bool IsSafeIntAdditiveOperand(Node* node) { | 425 bool IsSafeIntAdditiveOperand(Node* node) { |
| 418 Type* type = NodeProperties::GetBounds(node).upper; | 426 Type* type = NodeProperties::GetBounds(node).upper; |
| 419 // TODO(jarin): Unfortunately, bitset types are not subtypes of larger | 427 // TODO(jarin): Unfortunately, bitset types are not subtypes of larger |
| 420 // range types, so we have to explicitly check for Integral32 here | 428 // range types, so we have to explicitly check for Integral32 here |
| 421 // (in addition to the safe integer range). Once we fix subtyping for | 429 // (in addition to the safe integer range). Once we fix subtyping for |
| 422 // ranges, we should simplify this. | 430 // ranges, we should simplify this. |
| 423 return type->Is(safe_int_additive_range_) || type->Is(Type::Integral32()); | 431 return type->Is(safe_int_additive_range_) || type->Is(Type::Integral32()); |
| 424 } | 432 } |
| 425 | 433 |
| 426 bool CanLowerToInt32AdditiveBinop(Node* node, MachineTypeUnion use) { | 434 bool CanLowerToInt32AdditiveBinop(Node* node, MachineTypeUnion use) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 // but that responsibility really lies in the typed lowering phase. | 522 // but that responsibility really lies in the typed lowering phase. |
| 515 #define DEFINE_JS_CASE(x) case IrOpcode::k##x: | 523 #define DEFINE_JS_CASE(x) case IrOpcode::k##x: |
| 516 JS_OP_LIST(DEFINE_JS_CASE) | 524 JS_OP_LIST(DEFINE_JS_CASE) |
| 517 #undef DEFINE_JS_CASE | 525 #undef DEFINE_JS_CASE |
| 518 VisitInputs(node); | 526 VisitInputs(node); |
| 519 return SetOutput(node, kRepTagged); | 527 return SetOutput(node, kRepTagged); |
| 520 | 528 |
| 521 //------------------------------------------------------------------ | 529 //------------------------------------------------------------------ |
| 522 // Simplified operators. | 530 // Simplified operators. |
| 523 //------------------------------------------------------------------ | 531 //------------------------------------------------------------------ |
| 532 case IrOpcode::kAnyToBoolean: { |
| 533 if (IsSafeBitOperand(node->InputAt(0))) { |
| 534 VisitUnop(node, kRepBit, kRepBit); |
| 535 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 536 } else { |
| 537 VisitUnop(node, kMachAnyTagged, kTypeBool | kRepTagged); |
| 538 if (lower()) { |
| 539 // AnyToBoolean(x) => Call(ToBooleanStub, x, no-context) |
| 540 Operator::Properties properties = node->op()->properties(); |
| 541 Callable callable = CodeFactory::ToBoolean( |
| 542 jsgraph_->isolate(), ToBooleanStub::RESULT_AS_ODDBALL); |
| 543 CallDescriptor::Flags flags = CallDescriptor::kPatchableCallSite; |
| 544 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 545 callable.descriptor(), 0, flags, properties, jsgraph_->zone()); |
| 546 node->set_op(jsgraph_->common()->Call(desc)); |
| 547 node->InsertInput(jsgraph_->zone(), 0, |
| 548 jsgraph_->HeapConstant(callable.code())); |
| 549 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
| 550 } |
| 551 } |
| 552 break; |
| 553 } |
| 524 case IrOpcode::kBooleanNot: { | 554 case IrOpcode::kBooleanNot: { |
| 525 if (lower()) { | 555 if (lower()) { |
| 526 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; | 556 MachineTypeUnion input = GetInfo(node->InputAt(0))->output; |
| 527 if (input & kRepBit) { | 557 if (input & kRepBit) { |
| 528 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) | 558 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) |
| 529 node->set_op(lowering->machine()->Word32Equal()); | 559 node->set_op(lowering->machine()->Word32Equal()); |
| 530 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); | 560 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); |
| 531 } else { | 561 } else { |
| 532 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) | 562 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) |
| 533 node->set_op(lowering->machine()->WordEqual()); | 563 node->set_op(lowering->machine()->WordEqual()); |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 | 1057 |
| 1028 private: | 1058 private: |
| 1029 JSGraph* jsgraph_; | 1059 JSGraph* jsgraph_; |
| 1030 int count_; // number of nodes in the graph | 1060 int count_; // number of nodes in the graph |
| 1031 NodeInfo* info_; // node id -> usage information | 1061 NodeInfo* info_; // node id -> usage information |
| 1032 NodeVector nodes_; // collected nodes | 1062 NodeVector nodes_; // collected nodes |
| 1033 NodeVector replacements_; // replacements to be done after lowering | 1063 NodeVector replacements_; // replacements to be done after lowering |
| 1034 Phase phase_; // current phase of algorithm | 1064 Phase phase_; // current phase of algorithm |
| 1035 RepresentationChanger* changer_; // for inserting representation changes | 1065 RepresentationChanger* changer_; // for inserting representation changes |
| 1036 ZoneQueue<Node*> queue_; // queue for traversing the graph | 1066 ZoneQueue<Node*> queue_; // queue for traversing the graph |
| 1067 Type* safe_bit_range_; |
| 1037 Type* safe_int_additive_range_; | 1068 Type* safe_int_additive_range_; |
| 1038 | 1069 |
| 1039 NodeInfo* GetInfo(Node* node) { | 1070 NodeInfo* GetInfo(Node* node) { |
| 1040 DCHECK(node->id() >= 0); | 1071 DCHECK(node->id() >= 0); |
| 1041 DCHECK(node->id() < count_); | 1072 DCHECK(node->id() < count_); |
| 1042 return &info_[node->id()]; | 1073 return &info_[node->id()]; |
| 1043 } | 1074 } |
| 1044 | 1075 |
| 1045 MachineTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; } | 1076 MachineTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; } |
| 1046 }; | 1077 }; |
| 1047 | 1078 |
| 1048 | 1079 |
| 1049 Node* SimplifiedLowering::IsTagged(Node* node) { | 1080 Node* SimplifiedLowering::IsTagged(Node* node) { |
| 1050 // TODO(titzer): factor this out to a TaggingScheme abstraction. | 1081 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 1051 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. | 1082 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. |
| 1052 return graph()->NewNode(machine()->WordAnd(), node, | 1083 return graph()->NewNode(machine()->WordAnd(), node, |
| 1053 jsgraph()->Int32Constant(kSmiTagMask)); | 1084 jsgraph()->Int32Constant(kSmiTagMask)); |
| 1054 } | 1085 } |
| 1055 | 1086 |
| 1056 | 1087 |
| 1057 void SimplifiedLowering::LowerAllNodes() { | 1088 void SimplifiedLowering::LowerAllNodes() { |
| 1058 SimplifiedOperatorBuilder simplified(graph()->zone()); | 1089 SimplifiedOperatorBuilder simplified(graph()->zone()); |
| 1059 RepresentationChanger changer(jsgraph(), &simplified, | 1090 RepresentationChanger changer(jsgraph(), &simplified, |
| 1060 graph()->zone()->isolate()); | 1091 graph()->zone()->isolate()); |
| 1061 RepresentationSelector selector(jsgraph(), zone(), &changer); | 1092 RepresentationSelector selector(jsgraph(), zone_, &changer); |
| 1062 selector.Run(this); | 1093 selector.Run(this); |
| 1063 } | 1094 } |
| 1064 | 1095 |
| 1065 | 1096 |
| 1066 Node* SimplifiedLowering::Untag(Node* node) { | 1097 Node* SimplifiedLowering::Untag(Node* node) { |
| 1067 // TODO(titzer): factor this out to a TaggingScheme abstraction. | 1098 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 1068 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); | 1099 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); |
| 1069 return graph()->NewNode(machine()->WordSar(), node, shift_amount); | 1100 return graph()->NewNode(machine()->WordSar(), node, shift_amount); |
| 1070 } | 1101 } |
| 1071 | 1102 |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1477 | 1508 |
| 1478 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1509 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
| 1479 node->set_op(machine()->IntLessThanOrEqual()); | 1510 node->set_op(machine()->IntLessThanOrEqual()); |
| 1480 node->ReplaceInput(0, StringComparison(node, true)); | 1511 node->ReplaceInput(0, StringComparison(node, true)); |
| 1481 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1512 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 1482 } | 1513 } |
| 1483 | 1514 |
| 1484 } // namespace compiler | 1515 } // namespace compiler |
| 1485 } // namespace internal | 1516 } // namespace internal |
| 1486 } // namespace v8 | 1517 } // namespace v8 |
| OLD | NEW |