| 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 "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/compiler/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
| 10 #include "src/compiler/graph-inl.h" | 10 #include "src/compiler/graph-inl.h" |
| 11 #include "src/compiler/node-matchers.h" |
| 11 #include "src/compiler/node-properties-inl.h" | 12 #include "src/compiler/node-properties-inl.h" |
| 12 #include "src/compiler/representation-change.h" | 13 #include "src/compiler/representation-change.h" |
| 13 #include "src/compiler/simplified-lowering.h" | 14 #include "src/compiler/simplified-lowering.h" |
| 14 #include "src/compiler/simplified-operator.h" | 15 #include "src/compiler/simplified-operator.h" |
| 15 #include "src/objects.h" | 16 #include "src/objects.h" |
| 16 | 17 |
| 17 namespace v8 { | 18 namespace v8 { |
| 18 namespace internal { | 19 namespace internal { |
| 19 namespace compiler { | 20 namespace compiler { |
| 20 | 21 |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 } | 348 } |
| 348 | 349 |
| 349 const Operator* Uint32Op(Node* node) { | 350 const Operator* Uint32Op(Node* node) { |
| 350 return changer_->Uint32OperatorFor(node->opcode()); | 351 return changer_->Uint32OperatorFor(node->opcode()); |
| 351 } | 352 } |
| 352 | 353 |
| 353 const Operator* Float64Op(Node* node) { | 354 const Operator* Float64Op(Node* node) { |
| 354 return changer_->Float64OperatorFor(node->opcode()); | 355 return changer_->Float64OperatorFor(node->opcode()); |
| 355 } | 356 } |
| 356 | 357 |
| 358 bool CanLowerToInt32Binop(Node* node, MachineTypeUnion use) { |
| 359 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); |
| 360 } |
| 361 |
| 362 bool CanLowerToUint32Binop(Node* node, MachineTypeUnion use) { |
| 363 return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use); |
| 364 } |
| 365 |
| 366 bool CanObserveNonInt32(MachineTypeUnion use) { |
| 367 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; |
| 368 } |
| 369 |
| 370 bool CanObserveMinusZero(MachineTypeUnion use) { |
| 371 // TODO(turbofan): technically Uint32 cannot observe minus zero either. |
| 372 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; |
| 373 } |
| 374 |
| 375 bool CanObserveNonUint32(MachineTypeUnion use) { |
| 376 return (use & (kTypeInt32 | kTypeNumber | kTypeAny)) != 0; |
| 377 } |
| 378 |
| 357 // Dispatching routine for visiting the node {node} with the usage {use}. | 379 // Dispatching routine for visiting the node {node} with the usage {use}. |
| 358 // Depending on the operator, propagate new usage info to the inputs. | 380 // Depending on the operator, propagate new usage info to the inputs. |
| 359 void VisitNode(Node* node, MachineTypeUnion use, | 381 void VisitNode(Node* node, MachineTypeUnion use, |
| 360 SimplifiedLowering* lowering) { | 382 SimplifiedLowering* lowering) { |
| 361 switch (node->opcode()) { | 383 switch (node->opcode()) { |
| 362 //------------------------------------------------------------------ | 384 //------------------------------------------------------------------ |
| 363 // Common operators. | 385 // Common operators. |
| 364 //------------------------------------------------------------------ | 386 //------------------------------------------------------------------ |
| 365 case IrOpcode::kStart: | 387 case IrOpcode::kStart: |
| 366 case IrOpcode::kDead: | 388 case IrOpcode::kDead: |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 // => Float64Cmp | 493 // => Float64Cmp |
| 472 VisitFloat64Cmp(node); | 494 VisitFloat64Cmp(node); |
| 473 if (lower()) node->set_op(Float64Op(node)); | 495 if (lower()) node->set_op(Float64Op(node)); |
| 474 } | 496 } |
| 475 break; | 497 break; |
| 476 } | 498 } |
| 477 case IrOpcode::kNumberAdd: | 499 case IrOpcode::kNumberAdd: |
| 478 case IrOpcode::kNumberSubtract: { | 500 case IrOpcode::kNumberSubtract: { |
| 479 // Add and subtract reduce to Int32Add/Sub if the inputs | 501 // Add and subtract reduce to Int32Add/Sub if the inputs |
| 480 // are already integers and all uses are truncating. | 502 // are already integers and all uses are truncating. |
| 481 if (BothInputsAre(node, Type::Signed32()) && | 503 if (CanLowerToInt32Binop(node, use)) { |
| 482 (use & (kTypeUint32 | kTypeNumber | kTypeAny)) == 0) { | |
| 483 // => signed Int32Add/Sub | 504 // => signed Int32Add/Sub |
| 484 VisitInt32Binop(node); | 505 VisitInt32Binop(node); |
| 485 if (lower()) node->set_op(Int32Op(node)); | 506 if (lower()) node->set_op(Int32Op(node)); |
| 486 } else if (BothInputsAre(node, Type::Unsigned32()) && | 507 } else if (CanLowerToUint32Binop(node, use)) { |
| 487 (use & (kTypeInt32 | kTypeNumber | kTypeAny)) == 0) { | |
| 488 // => unsigned Int32Add/Sub | 508 // => unsigned Int32Add/Sub |
| 489 VisitUint32Binop(node); | 509 VisitUint32Binop(node); |
| 490 if (lower()) node->set_op(Uint32Op(node)); | 510 if (lower()) node->set_op(Uint32Op(node)); |
| 491 } else { | 511 } else { |
| 492 // => Float64Add/Sub | 512 // => Float64Add/Sub |
| 493 VisitFloat64Binop(node); | 513 VisitFloat64Binop(node); |
| 494 if (lower()) node->set_op(Float64Op(node)); | 514 if (lower()) node->set_op(Float64Op(node)); |
| 495 } | 515 } |
| 496 break; | 516 break; |
| 497 } | 517 } |
| 498 case IrOpcode::kNumberMultiply: | 518 case IrOpcode::kNumberMultiply: { |
| 499 case IrOpcode::kNumberDivide: | 519 NumberMatcher right(node->InputAt(1)); |
| 500 case IrOpcode::kNumberModulus: { | 520 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. |
| 501 // Float64Mul/Div/Mod | 521 if (CanLowerToInt32Binop(node, use)) { |
| 522 // => signed Int32Mul |
| 523 VisitInt32Binop(node); |
| 524 if (lower()) node->set_op(Int32Op(node)); |
| 525 break; |
| 526 } |
| 527 } |
| 528 // => Float64Mul |
| 502 VisitFloat64Binop(node); | 529 VisitFloat64Binop(node); |
| 503 if (lower()) node->set_op(Float64Op(node)); | 530 if (lower()) node->set_op(Float64Op(node)); |
| 504 break; | 531 break; |
| 532 } |
| 533 case IrOpcode::kNumberDivide: { |
| 534 NumberMatcher right(node->InputAt(1)); |
| 535 if (right.HasValue() && !right.Is(0) && !right.Is(-1)) { |
| 536 if (CanLowerToInt32Binop(node, use)) { |
| 537 // => signed Int32Div |
| 538 VisitInt32Binop(node); |
| 539 if (lower()) node->set_op(Int32Op(node)); |
| 540 break; |
| 541 } else if (CanLowerToUint32Binop(node, use)) { |
| 542 // => unsigned Uint32Div |
| 543 VisitUint32Binop(node); |
| 544 if (lower()) node->set_op(Uint32Op(node)); |
| 545 break; |
| 546 } |
| 547 } |
| 548 // => Float64Div |
| 549 VisitFloat64Binop(node); |
| 550 if (lower()) node->set_op(Float64Op(node)); |
| 551 break; |
| 552 } |
| 553 case IrOpcode::kNumberModulus: { |
| 554 NumberMatcher right(node->InputAt(1)); |
| 555 if (right.HasValue() && !right.Is(0) && !right.Is(-1)) { |
| 556 if (BothInputsAre(node, Type::Signed32()) && |
| 557 !CanObserveMinusZero(use)) { |
| 558 // => signed Int32Mod |
| 559 VisitInt32Binop(node); |
| 560 if (lower()) node->set_op(Int32Op(node)); |
| 561 break; |
| 562 } else if (BothInputsAre(node, Type::Unsigned32())) { |
| 563 // => unsigned Uint32Mod |
| 564 VisitUint32Binop(node); |
| 565 if (lower()) node->set_op(Uint32Op(node)); |
| 566 break; |
| 567 } |
| 568 } |
| 569 // => Float64Mod |
| 570 VisitFloat64Binop(node); |
| 571 if (lower()) node->set_op(Float64Op(node)); |
| 572 break; |
| 505 } | 573 } |
| 506 case IrOpcode::kNumberToInt32: { | 574 case IrOpcode::kNumberToInt32: { |
| 507 MachineTypeUnion use_rep = use & kRepMask; | 575 MachineTypeUnion use_rep = use & kRepMask; |
| 508 Node* input = node->InputAt(0); | 576 Node* input = node->InputAt(0); |
| 509 MachineTypeUnion in = GetInfo(input)->output; | 577 MachineTypeUnion in = GetInfo(input)->output; |
| 510 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32()) || | 578 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) { |
| 511 (in & kTypeMask) == kTypeInt32 || (in & kRepMask) == kRepWord32) { | 579 // If the input has type int32, pass through representation. |
| 512 // If the input has type int32, or is already a word32, just change | |
| 513 // representation if necessary. | |
| 514 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); | 580 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); |
| 515 if (lower()) DeferReplacement(node, node->InputAt(0)); | 581 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 582 } else if ((in & kTypeMask) == kTypeUint32 || |
| 583 (in & kTypeMask) == kTypeInt32 || |
| 584 (in & kRepMask) == kRepWord32) { |
| 585 // Just change representation if necessary. |
| 586 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); |
| 587 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 516 } else { | 588 } else { |
| 517 // Require the input in float64 format and perform truncation. | 589 // Require the input in float64 format and perform truncation. |
| 518 // TODO(turbofan): avoid a truncation with a smi check. | 590 // TODO(turbofan): avoid a truncation with a smi check. |
| 519 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); | 591 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); |
| 520 if (lower()) | 592 if (lower()) |
| 521 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); | 593 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); |
| 522 } | 594 } |
| 523 break; | 595 break; |
| 524 } | 596 } |
| 525 case IrOpcode::kNumberToUint32: { | 597 case IrOpcode::kNumberToUint32: { |
| 526 MachineTypeUnion use_rep = use & kRepMask; | 598 MachineTypeUnion use_rep = use & kRepMask; |
| 527 Node* input = node->InputAt(0); | 599 Node* input = node->InputAt(0); |
| 528 MachineTypeUnion in = GetInfo(input)->output; | 600 MachineTypeUnion in = GetInfo(input)->output; |
| 529 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32()) || | 601 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) { |
| 530 (in & kTypeMask) == kTypeUint32) { | 602 // If the input has type uint32, pass through representation. |
| 531 // If the input has type uint32, just change representation. | |
| 532 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); | 603 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); |
| 533 if (lower()) DeferReplacement(node, node->InputAt(0)); | 604 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 605 } else if ((in & kTypeMask) == kTypeUint32 || |
| 606 (in & kTypeMask) == kTypeInt32 || |
| 607 (in & kRepMask) == kRepWord32) { |
| 608 // Just change representation if necessary. |
| 609 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); |
| 610 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 534 } else { | 611 } else { |
| 535 // Require the input in float64 format and perform truncation. | 612 // Require the input in float64 format and perform truncation. |
| 536 // TODO(turbofan): avoid a truncation with a smi check. | 613 // TODO(turbofan): avoid a truncation with a smi check. |
| 537 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); | 614 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); |
| 538 if (lower()) | 615 if (lower()) |
| 539 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); | 616 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); |
| 540 } | 617 } |
| 541 break; | 618 break; |
| 542 } | 619 } |
| 543 case IrOpcode::kReferenceEqual: { | 620 case IrOpcode::kReferenceEqual: { |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 } | 814 } |
| 738 SetOutput(node, kMachAnyTagged); | 815 SetOutput(node, kMachAnyTagged); |
| 739 break; | 816 break; |
| 740 default: | 817 default: |
| 741 VisitInputs(node); | 818 VisitInputs(node); |
| 742 break; | 819 break; |
| 743 } | 820 } |
| 744 } | 821 } |
| 745 | 822 |
| 746 void DeferReplacement(Node* node, Node* replacement) { | 823 void DeferReplacement(Node* node, Node* replacement) { |
| 824 if (FLAG_trace_representation) { |
| 825 TRACE(("defer replacement #%d:%s with #%d:%s\n", node->id(), |
| 826 node->op()->mnemonic(), replacement->id(), |
| 827 replacement->op()->mnemonic())); |
| 828 } |
| 747 if (replacement->id() < count_) { | 829 if (replacement->id() < count_) { |
| 748 // Replace with a previously existing node eagerly. | 830 // Replace with a previously existing node eagerly. |
| 749 node->ReplaceUses(replacement); | 831 node->ReplaceUses(replacement); |
| 750 } else { | 832 } else { |
| 751 // Otherwise, we are replacing a node with a representation change. | 833 // Otherwise, we are replacing a node with a representation change. |
| 752 // Such a substitution must be done after all lowering is done, because | 834 // Such a substitution must be done after all lowering is done, because |
| 753 // new nodes do not have {NodeInfo} entries, and that would confuse | 835 // new nodes do not have {NodeInfo} entries, and that would confuse |
| 754 // the representation change insertion for uses of it. | 836 // the representation change insertion for uses of it. |
| 755 replacements_.push_back(node); | 837 replacements_.push_back(node); |
| 756 replacements_.push_back(replacement); | 838 replacements_.push_back(replacement); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1055 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
| 974 node->set_op(machine()->IntLessThanOrEqual()); | 1056 node->set_op(machine()->IntLessThanOrEqual()); |
| 975 node->ReplaceInput(0, StringComparison(node, true)); | 1057 node->ReplaceInput(0, StringComparison(node, true)); |
| 976 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1058 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 977 } | 1059 } |
| 978 | 1060 |
| 979 | 1061 |
| 980 } // namespace compiler | 1062 } // namespace compiler |
| 981 } // namespace internal | 1063 } // namespace internal |
| 982 } // namespace v8 | 1064 } // namespace v8 |
| OLD | NEW |