Chromium Code Reviews| 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 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 } | 345 } |
| 345 | 346 |
| 346 const Operator* Uint32Op(Node* node) { | 347 const Operator* Uint32Op(Node* node) { |
| 347 return changer_->Uint32OperatorFor(node->opcode()); | 348 return changer_->Uint32OperatorFor(node->opcode()); |
| 348 } | 349 } |
| 349 | 350 |
| 350 const Operator* Float64Op(Node* node) { | 351 const Operator* Float64Op(Node* node) { |
| 351 return changer_->Float64OperatorFor(node->opcode()); | 352 return changer_->Float64OperatorFor(node->opcode()); |
| 352 } | 353 } |
| 353 | 354 |
| 355 bool CanBeInt32Binop(Node* node, MachineTypeUnion use) { | |
|
Michael Starzinger
2014/10/08 09:01:28
Please address my previous comment about the "CanB
titzer
2014/10/08 09:12:29
Done.
| |
| 356 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); | |
| 357 } | |
| 358 | |
| 359 bool CanBeUint32Binop(Node* node, MachineTypeUnion use) { | |
| 360 return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use); | |
| 361 } | |
| 362 | |
| 363 bool CanObserveNonInt32(MachineTypeUnion use) { | |
| 364 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; | |
| 365 } | |
| 366 | |
| 367 bool CanObserveMinusZero(MachineTypeUnion use) { | |
| 368 // TODO(turbofan): technically Uint32 cannot observe minus zero either. | |
| 369 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0; | |
| 370 } | |
| 371 | |
| 372 bool CanObserveNonUint32(MachineTypeUnion use) { | |
| 373 return (use & (kTypeInt32 | kTypeNumber | kTypeAny)) != 0; | |
| 374 } | |
| 375 | |
| 354 // Dispatching routine for visiting the node {node} with the usage {use}. | 376 // Dispatching routine for visiting the node {node} with the usage {use}. |
| 355 // Depending on the operator, propagate new usage info to the inputs. | 377 // Depending on the operator, propagate new usage info to the inputs. |
| 356 void VisitNode(Node* node, MachineTypeUnion use, | 378 void VisitNode(Node* node, MachineTypeUnion use, |
| 357 SimplifiedLowering* lowering) { | 379 SimplifiedLowering* lowering) { |
| 358 switch (node->opcode()) { | 380 switch (node->opcode()) { |
| 359 //------------------------------------------------------------------ | 381 //------------------------------------------------------------------ |
| 360 // Common operators. | 382 // Common operators. |
| 361 //------------------------------------------------------------------ | 383 //------------------------------------------------------------------ |
| 362 case IrOpcode::kStart: | 384 case IrOpcode::kStart: |
| 363 case IrOpcode::kDead: | 385 case IrOpcode::kDead: |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 // => Float64Cmp | 490 // => Float64Cmp |
| 469 VisitFloat64Cmp(node); | 491 VisitFloat64Cmp(node); |
| 470 if (lower()) node->set_op(Float64Op(node)); | 492 if (lower()) node->set_op(Float64Op(node)); |
| 471 } | 493 } |
| 472 break; | 494 break; |
| 473 } | 495 } |
| 474 case IrOpcode::kNumberAdd: | 496 case IrOpcode::kNumberAdd: |
| 475 case IrOpcode::kNumberSubtract: { | 497 case IrOpcode::kNumberSubtract: { |
| 476 // Add and subtract reduce to Int32Add/Sub if the inputs | 498 // Add and subtract reduce to Int32Add/Sub if the inputs |
| 477 // are already integers and all uses are truncating. | 499 // are already integers and all uses are truncating. |
| 478 if (BothInputsAre(node, Type::Signed32()) && | 500 if (CanBeInt32Binop(node, use)) { |
| 479 (use & (kTypeUint32 | kTypeNumber | kTypeAny)) == 0) { | |
| 480 // => signed Int32Add/Sub | 501 // => signed Int32Add/Sub |
| 481 VisitInt32Binop(node); | 502 VisitInt32Binop(node); |
| 482 if (lower()) node->set_op(Int32Op(node)); | 503 if (lower()) node->set_op(Int32Op(node)); |
| 483 } else if (BothInputsAre(node, Type::Unsigned32()) && | 504 } else if (CanBeUint32Binop(node, use)) { |
| 484 (use & (kTypeInt32 | kTypeNumber | kTypeAny)) == 0) { | |
| 485 // => unsigned Int32Add/Sub | 505 // => unsigned Int32Add/Sub |
| 486 VisitUint32Binop(node); | 506 VisitUint32Binop(node); |
| 487 if (lower()) node->set_op(Uint32Op(node)); | 507 if (lower()) node->set_op(Uint32Op(node)); |
| 488 } else { | 508 } else { |
| 489 // => Float64Add/Sub | 509 // => Float64Add/Sub |
| 490 VisitFloat64Binop(node); | 510 VisitFloat64Binop(node); |
| 491 if (lower()) node->set_op(Float64Op(node)); | 511 if (lower()) node->set_op(Float64Op(node)); |
| 492 } | 512 } |
| 493 break; | 513 break; |
| 494 } | 514 } |
| 495 case IrOpcode::kNumberMultiply: | 515 case IrOpcode::kNumberMultiply: { |
| 496 case IrOpcode::kNumberDivide: | 516 NumberMatcher right(node->InputAt(1)); |
| 497 case IrOpcode::kNumberModulus: { | 517 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa. |
| 498 // Float64Mul/Div/Mod | 518 if (CanBeInt32Binop(node, use)) { |
| 519 // => signed Int32Mul | |
| 520 VisitInt32Binop(node); | |
| 521 if (lower()) node->set_op(Int32Op(node)); | |
| 522 break; | |
| 523 } | |
| 524 } | |
| 525 // => Float64Mul | |
| 499 VisitFloat64Binop(node); | 526 VisitFloat64Binop(node); |
| 500 if (lower()) node->set_op(Float64Op(node)); | 527 if (lower()) node->set_op(Float64Op(node)); |
| 501 break; | 528 break; |
| 529 } | |
| 530 case IrOpcode::kNumberDivide: { | |
| 531 NumberMatcher right(node->InputAt(1)); | |
| 532 if (right.HasValue() && !right.Is(0) && !right.Is(-1)) { | |
| 533 if (CanBeInt32Binop(node, use)) { | |
| 534 // => signed Int32Div | |
| 535 VisitInt32Binop(node); | |
| 536 if (lower()) node->set_op(Int32Op(node)); | |
| 537 break; | |
| 538 } else if (CanBeUint32Binop(node, use)) { | |
| 539 // => unsigned Uint32Div | |
| 540 VisitUint32Binop(node); | |
| 541 if (lower()) node->set_op(Uint32Op(node)); | |
| 542 break; | |
| 543 } | |
| 544 } | |
| 545 // => Float64Div | |
| 546 VisitFloat64Binop(node); | |
| 547 if (lower()) node->set_op(Float64Op(node)); | |
| 548 break; | |
| 549 } | |
| 550 case IrOpcode::kNumberModulus: { | |
| 551 NumberMatcher right(node->InputAt(1)); | |
| 552 if (right.HasValue() && !right.Is(0) && !right.Is(-1)) { | |
| 553 if (BothInputsAre(node, Type::Signed32()) && | |
| 554 !CanObserveMinusZero(use)) { | |
| 555 // => signed Int32Mod | |
| 556 VisitInt32Binop(node); | |
| 557 if (lower()) node->set_op(Int32Op(node)); | |
| 558 break; | |
| 559 } else if (BothInputsAre(node, Type::Unsigned32())) { | |
| 560 // => unsigned Uint32Mod | |
| 561 VisitUint32Binop(node); | |
| 562 if (lower()) node->set_op(Uint32Op(node)); | |
| 563 break; | |
| 564 } | |
| 565 } | |
| 566 // => Float64Mod | |
| 567 VisitFloat64Binop(node); | |
| 568 if (lower()) node->set_op(Float64Op(node)); | |
| 569 break; | |
| 502 } | 570 } |
| 503 case IrOpcode::kNumberToInt32: { | 571 case IrOpcode::kNumberToInt32: { |
| 504 MachineTypeUnion use_rep = use & kRepMask; | 572 MachineTypeUnion use_rep = use & kRepMask; |
| 505 Node* input = node->InputAt(0); | 573 Node* input = node->InputAt(0); |
| 506 MachineTypeUnion in = GetInfo(input)->output; | 574 MachineTypeUnion in = GetInfo(input)->output; |
| 507 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32()) || | 575 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) { |
| 508 (in & kTypeMask) == kTypeInt32 || (in & kRepMask) == kRepWord32) { | 576 // If the input has type int32, pass through representation. |
| 509 // If the input has type int32, or is already a word32, just change | |
| 510 // representation if necessary. | |
| 511 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); | 577 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); |
| 512 if (lower()) DeferReplacement(node, node->InputAt(0)); | 578 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 579 } else if ((in & kTypeMask) == kTypeUint32 || | |
| 580 (in & kTypeMask) == kTypeInt32 || | |
| 581 (in & kRepMask) == kRepWord32) { | |
| 582 // Just change representation if necessary. | |
| 583 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); | |
| 584 if (lower()) DeferReplacement(node, node->InputAt(0)); | |
| 513 } else { | 585 } else { |
| 514 // Require the input in float64 format and perform truncation. | 586 // Require the input in float64 format and perform truncation. |
| 515 // TODO(turbofan): avoid a truncation with a smi check. | 587 // TODO(turbofan): avoid a truncation with a smi check. |
| 516 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); | 588 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); |
| 517 if (lower()) | 589 if (lower()) |
| 518 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); | 590 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); |
| 519 } | 591 } |
| 520 break; | 592 break; |
| 521 } | 593 } |
| 522 case IrOpcode::kNumberToUint32: { | 594 case IrOpcode::kNumberToUint32: { |
| 523 MachineTypeUnion use_rep = use & kRepMask; | 595 MachineTypeUnion use_rep = use & kRepMask; |
| 524 Node* input = node->InputAt(0); | 596 Node* input = node->InputAt(0); |
| 525 MachineTypeUnion in = GetInfo(input)->output; | 597 MachineTypeUnion in = GetInfo(input)->output; |
| 526 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32()) || | 598 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) { |
| 527 (in & kTypeMask) == kTypeUint32) { | 599 // If the input has type uint32, pass through representation. |
| 528 // If the input has type uint32, just change representation. | |
| 529 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); | 600 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); |
| 530 if (lower()) DeferReplacement(node, node->InputAt(0)); | 601 if (lower()) DeferReplacement(node, node->InputAt(0)); |
| 602 } else if ((in & kTypeMask) == kTypeUint32 || | |
| 603 (in & kTypeMask) == kTypeInt32 || | |
| 604 (in & kRepMask) == kRepWord32) { | |
| 605 // Just change representation if necessary. | |
| 606 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); | |
| 607 if (lower()) DeferReplacement(node, node->InputAt(0)); | |
| 531 } else { | 608 } else { |
| 532 // Require the input in float64 format and perform truncation. | 609 // Require the input in float64 format and perform truncation. |
| 533 // TODO(turbofan): avoid a truncation with a smi check. | 610 // TODO(turbofan): avoid a truncation with a smi check. |
| 534 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); | 611 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); |
| 535 if (lower()) | 612 if (lower()) |
| 536 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); | 613 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); |
| 537 } | 614 } |
| 538 break; | 615 break; |
| 539 } | 616 } |
| 540 case IrOpcode::kReferenceEqual: { | 617 case IrOpcode::kReferenceEqual: { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 return VisitFloat64Cmp(node); | 805 return VisitFloat64Cmp(node); |
| 729 case IrOpcode::kLoadStackPointer: | 806 case IrOpcode::kLoadStackPointer: |
| 730 return VisitLeaf(node, kMachPtr); | 807 return VisitLeaf(node, kMachPtr); |
| 731 default: | 808 default: |
| 732 VisitInputs(node); | 809 VisitInputs(node); |
| 733 break; | 810 break; |
| 734 } | 811 } |
| 735 } | 812 } |
| 736 | 813 |
| 737 void DeferReplacement(Node* node, Node* replacement) { | 814 void DeferReplacement(Node* node, Node* replacement) { |
| 815 if (FLAG_trace_representation) { | |
| 816 TRACE(("defer replacement #%d:%s with #%d:%s\n", node->id(), | |
| 817 node->op()->mnemonic(), replacement->id(), | |
| 818 replacement->op()->mnemonic())); | |
| 819 } | |
| 738 if (replacement->id() < count_) { | 820 if (replacement->id() < count_) { |
| 739 // Replace with a previously existing node eagerly. | 821 // Replace with a previously existing node eagerly. |
| 740 node->ReplaceUses(replacement); | 822 node->ReplaceUses(replacement); |
| 741 } else { | 823 } else { |
| 742 // Otherwise, we are replacing a node with a representation change. | 824 // Otherwise, we are replacing a node with a representation change. |
| 743 // Such a substitution must be done after all lowering is done, because | 825 // Such a substitution must be done after all lowering is done, because |
| 744 // new nodes do not have {NodeInfo} entries, and that would confuse | 826 // new nodes do not have {NodeInfo} entries, and that would confuse |
| 745 // the representation change insertion for uses of it. | 827 // the representation change insertion for uses of it. |
| 746 replacements_.push_back(node); | 828 replacements_.push_back(node); |
| 747 replacements_.push_back(replacement); | 829 replacements_.push_back(replacement); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 964 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { | 1046 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { |
| 965 node->set_op(machine()->IntLessThanOrEqual()); | 1047 node->set_op(machine()->IntLessThanOrEqual()); |
| 966 node->ReplaceInput(0, StringComparison(node, true)); | 1048 node->ReplaceInput(0, StringComparison(node, true)); |
| 967 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); | 1049 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); |
| 968 } | 1050 } |
| 969 | 1051 |
| 970 | 1052 |
| 971 } // namespace compiler | 1053 } // namespace compiler |
| 972 } // namespace internal | 1054 } // namespace internal |
| 973 } // namespace v8 | 1055 } // namespace v8 |
| OLD | NEW |