| 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/address-map.h" | 9 #include "src/address-map.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 }; | 176 }; |
| 177 | 177 |
| 178 #endif // DEBUG | 178 #endif // DEBUG |
| 179 | 179 |
| 180 } // namespace | 180 } // namespace |
| 181 | 181 |
| 182 | 182 |
| 183 class RepresentationSelector { | 183 class RepresentationSelector { |
| 184 public: | 184 public: |
| 185 // Information for each node tracked during the fixpoint. | 185 // Information for each node tracked during the fixpoint. |
| 186 class NodeInfo { | 186 class NodeInfo final { |
| 187 public: | 187 public: |
| 188 // Adds new use to the node. Returns true if something has changed | 188 // Adds new use to the node. Returns true if something has changed |
| 189 // and the node has to be requeued. | 189 // and the node has to be requeued. |
| 190 bool AddUse(UseInfo info) { | 190 bool AddUse(UseInfo info) { |
| 191 Truncation old_truncation = truncation_; | 191 Truncation old_truncation = truncation_; |
| 192 truncation_ = Truncation::Generalize(truncation_, info.truncation()); | 192 truncation_ = Truncation::Generalize(truncation_, info.truncation()); |
| 193 return truncation_ != old_truncation; | 193 return truncation_ != old_truncation; |
| 194 } | 194 } |
| 195 | 195 |
| 196 void set_queued() { state_ = kQueued; } | 196 void set_queued() { state_ = kQueued; } |
| 197 void set_visited() { state_ = kVisited; } | 197 void set_visited() { state_ = kVisited; } |
| 198 void set_pushed() { state_ = kPushed; } | 198 void set_pushed() { state_ = kPushed; } |
| 199 void reset_state() { state_ = kUnvisited; } | 199 void reset_state() { state_ = kUnvisited; } |
| 200 bool visited() const { return state_ == kVisited; } | 200 bool visited() const { return state_ == kVisited; } |
| 201 bool queued() const { return state_ == kQueued; } | 201 bool queued() const { return state_ == kQueued; } |
| 202 bool unvisited() const { return state_ == kUnvisited; } | 202 bool unvisited() const { return state_ == kUnvisited; } |
| 203 Truncation truncation() const { return truncation_; } | 203 Truncation truncation() const { return truncation_; } |
| 204 void set_output(MachineRepresentation output) { representation_ = output; } | 204 void set_output(MachineRepresentation output) { representation_ = output; } |
| 205 | 205 |
| 206 MachineRepresentation representation() const { return representation_; } | 206 MachineRepresentation representation() const { return representation_; } |
| 207 | 207 |
| 208 // Helpers for feedback typing. | 208 // Helpers for feedback typing. |
| 209 void set_feedback_type(Type* type) { feedback_type_ = type; } | 209 void set_feedback_type(Type* type) { feedback_type_ = type; } |
| 210 Type* feedback_type() { return feedback_type_; } | 210 Type* feedback_type() const { return feedback_type_; } |
| 211 void set_weakened() { weakened_ = true; } | 211 void set_weakened() { weakened_ = true; } |
| 212 bool weakened() { return weakened_; } | 212 bool weakened() const { return weakened_; } |
| 213 TypeCheckKind type_check() { return type_check_; } | 213 void set_restriction_type(Type* type) { restriction_type_ = type; } |
| 214 void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; } | 214 Type* restriction_type() const { return restriction_type_; } |
| 215 | 215 |
| 216 private: | 216 private: |
| 217 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; | 217 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; |
| 218 State state_ = kUnvisited; | 218 State state_ = kUnvisited; |
| 219 MachineRepresentation representation_ = | 219 MachineRepresentation representation_ = |
| 220 MachineRepresentation::kNone; // Output representation. | 220 MachineRepresentation::kNone; // Output representation. |
| 221 Truncation truncation_ = Truncation::None(); // Information about uses. | 221 Truncation truncation_ = Truncation::None(); // Information about uses. |
| 222 TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind. | |
| 223 | 222 |
| 223 Type* restriction_type_ = Type::Any(); |
| 224 Type* feedback_type_ = nullptr; | 224 Type* feedback_type_ = nullptr; |
| 225 bool weakened_ = false; | 225 bool weakened_ = false; |
| 226 }; | 226 }; |
| 227 | 227 |
| 228 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 228 RepresentationSelector(JSGraph* jsgraph, Zone* zone, |
| 229 RepresentationChanger* changer, | 229 RepresentationChanger* changer, |
| 230 SourcePositionTable* source_positions) | 230 SourcePositionTable* source_positions) |
| 231 : jsgraph_(jsgraph), | 231 : jsgraph_(jsgraph), |
| 232 zone_(zone), | 232 zone_(zone), |
| 233 count_(jsgraph->graph()->NodeCount()), | 233 count_(jsgraph->graph()->NodeCount()), |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); | 336 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); |
| 337 } | 337 } |
| 338 return type; | 338 return type; |
| 339 } | 339 } |
| 340 | 340 |
| 341 Type* TypeSelect(Node* node) { | 341 Type* TypeSelect(Node* node) { |
| 342 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), | 342 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), |
| 343 FeedbackTypeOf(node->InputAt(2))); | 343 FeedbackTypeOf(node->InputAt(2))); |
| 344 } | 344 } |
| 345 | 345 |
| 346 static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) { | |
| 347 switch (type_check) { | |
| 348 case TypeCheckKind::kNone: | |
| 349 return Type::Any(); | |
| 350 case TypeCheckKind::kSigned32: | |
| 351 return Type::Signed32(); | |
| 352 case TypeCheckKind::kNumber: | |
| 353 return Type::Number(); | |
| 354 // Unexpected cases. | |
| 355 case TypeCheckKind::kNumberOrUndefined: | |
| 356 FATAL("Unexpected checked type."); | |
| 357 break; | |
| 358 } | |
| 359 UNREACHABLE(); | |
| 360 return nullptr; | |
| 361 } | |
| 362 | |
| 363 bool UpdateFeedbackType(Node* node) { | 346 bool UpdateFeedbackType(Node* node) { |
| 364 if (node->op()->ValueOutputCount() == 0) return false; | 347 if (node->op()->ValueOutputCount() == 0) return false; |
| 365 | 348 |
| 366 NodeInfo* info = GetInfo(node); | 349 NodeInfo* info = GetInfo(node); |
| 367 Type* type = info->feedback_type(); | 350 Type* type = info->feedback_type(); |
| 368 Type* new_type = type; | 351 Type* new_type = type; |
| 369 | 352 |
| 370 // For any non-phi node just wait until we get all inputs typed. We only | 353 // For any non-phi node just wait until we get all inputs typed. We only |
| 371 // allow untyped inputs for phi nodes because phis are the only places | 354 // allow untyped inputs for phi nodes because phis are the only places |
| 372 // where cycles need to be broken. | 355 // where cycles need to be broken. |
| 373 if (node->opcode() != IrOpcode::kPhi) { | 356 if (node->opcode() != IrOpcode::kPhi) { |
| 374 for (int i = 0; i < node->op()->ValueInputCount(); i++) { | 357 for (int i = 0; i < node->op()->ValueInputCount(); i++) { |
| 375 if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) { | 358 if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) { |
| 376 return false; | 359 return false; |
| 377 } | 360 } |
| 378 } | 361 } |
| 379 } | 362 } |
| 380 | 363 |
| 381 switch (node->opcode()) { | 364 switch (node->opcode()) { |
| 365 case IrOpcode::kNumberAdd: |
| 382 case IrOpcode::kSpeculativeNumberAdd: { | 366 case IrOpcode::kSpeculativeNumberAdd: { |
| 383 // TODO(jarin) The ToNumber conversion is too conservative here, | 367 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 384 // e.g. it will treat true as 1 even though the number check will | 368 // e.g. it will treat true as 1 even though the number check will |
| 385 // fail on a boolean. OperationTyper should have a function that | 369 // fail on a boolean. OperationTyper should have a function that |
| 386 // computes a more precise type. | 370 // computes a more precise type. |
| 387 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 371 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 388 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 372 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 389 Type* static_type = op_typer_.NumberAdd(lhs, rhs); | 373 Type* computed_type = op_typer_.NumberAdd(lhs, rhs); |
| 390 if (info->type_check() == TypeCheckKind::kNone) { | 374 new_type = Type::Intersect(computed_type, info->restriction_type(), |
| 391 new_type = static_type; | 375 graph_zone()); |
| 392 } else { | |
| 393 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 394 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 395 } | |
| 396 break; | 376 break; |
| 397 } | 377 } |
| 398 | 378 |
| 379 case IrOpcode::kNumberSubtract: |
| 399 case IrOpcode::kSpeculativeNumberSubtract: { | 380 case IrOpcode::kSpeculativeNumberSubtract: { |
| 400 // TODO(jarin) The ToNumber conversion is too conservative here, | 381 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 401 // e.g. it will treat true as 1 even though the number check will | 382 // e.g. it will treat true as 1 even though the number check will |
| 402 // fail on a boolean. OperationTyper should have a function that | 383 // fail on a boolean. OperationTyper should have a function that |
| 403 // computes a more precise type. | 384 // computes a more precise type. |
| 404 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 385 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 405 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 386 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 406 Type* static_type = op_typer_.NumberSubtract(lhs, rhs); | 387 Type* computed_type = op_typer_.NumberSubtract(lhs, rhs); |
| 407 if (info->type_check() == TypeCheckKind::kNone) { | 388 new_type = Type::Intersect(computed_type, info->restriction_type(), |
| 408 new_type = static_type; | 389 graph_zone()); |
| 409 } else { | |
| 410 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 411 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 412 } | |
| 413 break; | 390 break; |
| 414 } | 391 } |
| 415 | 392 |
| 393 case IrOpcode::kNumberMultiply: |
| 416 case IrOpcode::kSpeculativeNumberMultiply: { | 394 case IrOpcode::kSpeculativeNumberMultiply: { |
| 417 // TODO(jarin) The ToNumber conversion is too conservative here, | 395 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 418 // e.g. it will treat true as 1 even though the number check will | 396 // e.g. it will treat true as 1 even though the number check will |
| 419 // fail on a boolean. OperationTyper should have a function that | 397 // fail on a boolean. OperationTyper should have a function that |
| 420 // computes a more precise type. | 398 // computes a more precise type. |
| 421 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 399 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 422 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 400 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 423 Type* static_type = op_typer_.NumberMultiply(lhs, rhs); | 401 Type* computed_type = op_typer_.NumberMultiply(lhs, rhs); |
| 424 if (info->type_check() == TypeCheckKind::kNone) { | 402 new_type = Type::Intersect(computed_type, info->restriction_type(), |
| 425 new_type = static_type; | 403 graph_zone()); |
| 426 } else { | |
| 427 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 428 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 429 } | |
| 430 break; | 404 break; |
| 431 } | 405 } |
| 432 | 406 |
| 407 case IrOpcode::kNumberDivide: |
| 433 case IrOpcode::kSpeculativeNumberDivide: { | 408 case IrOpcode::kSpeculativeNumberDivide: { |
| 434 // TODO(jarin) The ToNumber conversion is too conservative here, | 409 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 435 // e.g. it will treat true as 1 even though the number check will | 410 // e.g. it will treat true as 1 even though the number check will |
| 436 // fail on a boolean. OperationTyper should have a function that | 411 // fail on a boolean. OperationTyper should have a function that |
| 437 // computes a more precise type. | 412 // computes a more precise type. |
| 438 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 413 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 439 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 414 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 440 Type* static_type = op_typer_.NumberDivide(lhs, rhs); | 415 Type* computed_type = op_typer_.NumberDivide(lhs, rhs); |
| 441 if (info->type_check() == TypeCheckKind::kNone) { | 416 new_type = Type::Intersect(computed_type, info->restriction_type(), |
| 442 new_type = static_type; | 417 graph_zone()); |
| 443 } else { | |
| 444 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 445 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 446 } | |
| 447 break; | 418 break; |
| 448 } | 419 } |
| 449 | 420 |
| 421 case IrOpcode::kNumberModulus: |
| 450 case IrOpcode::kSpeculativeNumberModulus: { | 422 case IrOpcode::kSpeculativeNumberModulus: { |
| 451 // TODO(jarin) The ToNumber conversion is too conservative here, | 423 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 452 // e.g. it will treat true as 1 even though the number check will | 424 // e.g. it will treat true as 1 even though the number check will |
| 453 // fail on a boolean. OperationTyper should have a function that | 425 // fail on a boolean. OperationTyper should have a function that |
| 454 // computes a more precise type. | 426 // computes a more precise type. |
| 455 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 427 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
| 456 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 428 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
| 457 Type* static_type = op_typer_.NumberModulus(lhs, rhs); | 429 Type* computed_type = op_typer_.NumberModulus(lhs, rhs); |
| 458 if (info->type_check() == TypeCheckKind::kNone) { | 430 new_type = Type::Intersect(computed_type, info->restriction_type(), |
| 459 new_type = static_type; | 431 graph_zone()); |
| 460 } else { | |
| 461 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | |
| 462 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | |
| 463 } | |
| 464 break; | 432 break; |
| 465 } | 433 } |
| 466 | 434 |
| 467 case IrOpcode::kNumberAbs: { | 435 case IrOpcode::kNumberAbs: { |
| 468 new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0))); | 436 new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0))); |
| 469 break; | 437 break; |
| 470 } | 438 } |
| 471 | 439 |
| 472 case IrOpcode::kPhi: { | 440 case IrOpcode::kPhi: { |
| 473 new_type = TypePhi(node); | 441 new_type = TypePhi(node); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 } | 618 } |
| 651 PrintTruncation(info->truncation()); | 619 PrintTruncation(info->truncation()); |
| 652 } | 620 } |
| 653 } | 621 } |
| 654 | 622 |
| 655 bool lower() const { return phase_ == LOWER; } | 623 bool lower() const { return phase_ == LOWER; } |
| 656 bool retype() const { return phase_ == RETYPE; } | 624 bool retype() const { return phase_ == RETYPE; } |
| 657 bool propagate() const { return phase_ == PROPAGATE; } | 625 bool propagate() const { return phase_ == PROPAGATE; } |
| 658 | 626 |
| 659 void SetOutput(Node* node, MachineRepresentation representation, | 627 void SetOutput(Node* node, MachineRepresentation representation, |
| 660 TypeCheckKind type_check = TypeCheckKind::kNone) { | 628 Type* restriction_type = Type::Any()) { |
| 661 NodeInfo* const info = GetInfo(node); | 629 NodeInfo* const info = GetInfo(node); |
| 662 switch (phase_) { | 630 switch (phase_) { |
| 663 case PROPAGATE: | 631 case PROPAGATE: |
| 664 info->set_type_check(type_check); | 632 info->set_restriction_type(restriction_type); |
| 665 break; | 633 break; |
| 666 case RETYPE: | 634 case RETYPE: |
| 667 DCHECK_EQ(info->type_check(), type_check); | 635 DCHECK(info->restriction_type()->Is(restriction_type)); |
| 636 DCHECK(restriction_type->Is(info->restriction_type())); |
| 668 info->set_output(representation); | 637 info->set_output(representation); |
| 669 break; | 638 break; |
| 670 case LOWER: | 639 case LOWER: |
| 671 DCHECK_EQ(info->type_check(), type_check); | |
| 672 DCHECK_EQ(info->representation(), representation); | 640 DCHECK_EQ(info->representation(), representation); |
| 641 DCHECK(info->restriction_type()->Is(restriction_type)); |
| 642 DCHECK(restriction_type->Is(info->restriction_type())); |
| 673 break; | 643 break; |
| 674 } | 644 } |
| 675 } | 645 } |
| 676 | 646 |
| 677 void ResetOutput(Node* node, MachineRepresentation representation, | |
| 678 TypeCheckKind type_check = TypeCheckKind::kNone) { | |
| 679 NodeInfo* info = GetInfo(node); | |
| 680 info->set_output(representation); | |
| 681 info->set_type_check(type_check); | |
| 682 } | |
| 683 | |
| 684 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } | 647 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } |
| 685 | 648 |
| 686 bool InputCannotBe(Node* node, Type* type) { | 649 bool InputCannotBe(Node* node, Type* type) { |
| 687 DCHECK_EQ(1, node->op()->ValueInputCount()); | 650 DCHECK_EQ(1, node->op()->ValueInputCount()); |
| 688 return !GetUpperBound(node->InputAt(0))->Maybe(type); | 651 return !GetUpperBound(node->InputAt(0))->Maybe(type); |
| 689 } | 652 } |
| 690 | 653 |
| 691 bool InputIs(Node* node, Type* type) { | 654 bool InputIs(Node* node, Type* type) { |
| 692 DCHECK_EQ(1, node->op()->ValueInputCount()); | 655 DCHECK_EQ(1, node->op()->ValueInputCount()); |
| 693 return GetUpperBound(node->InputAt(0))->Is(type); | 656 return GetUpperBound(node->InputAt(0))->Is(type); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 } | 733 } |
| 771 // Only enqueue other inputs (framestates, effects, control). | 734 // Only enqueue other inputs (framestates, effects, control). |
| 772 for (int i = tagged_count; i < node->InputCount(); i++) { | 735 for (int i = tagged_count; i < node->InputCount(); i++) { |
| 773 EnqueueInput(node, i); | 736 EnqueueInput(node, i); |
| 774 } | 737 } |
| 775 } | 738 } |
| 776 | 739 |
| 777 // Helper for binops of the R x L -> O variety. | 740 // Helper for binops of the R x L -> O variety. |
| 778 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, | 741 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, |
| 779 MachineRepresentation output, | 742 MachineRepresentation output, |
| 780 TypeCheckKind type_check = TypeCheckKind::kNone) { | 743 Type* restriction_type = Type::Any()) { |
| 781 DCHECK_EQ(2, node->op()->ValueInputCount()); | 744 DCHECK_EQ(2, node->op()->ValueInputCount()); |
| 782 ProcessInput(node, 0, left_use); | 745 ProcessInput(node, 0, left_use); |
| 783 ProcessInput(node, 1, right_use); | 746 ProcessInput(node, 1, right_use); |
| 784 for (int i = 2; i < node->InputCount(); i++) { | 747 for (int i = 2; i < node->InputCount(); i++) { |
| 785 EnqueueInput(node, i); | 748 EnqueueInput(node, i); |
| 786 } | 749 } |
| 787 SetOutput(node, output, type_check); | 750 SetOutput(node, output, restriction_type); |
| 788 } | 751 } |
| 789 | 752 |
| 790 // Helper for binops of the I x I -> O variety. | 753 // Helper for binops of the I x I -> O variety. |
| 791 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, | 754 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, |
| 792 TypeCheckKind type_check = TypeCheckKind::kNone) { | 755 Type* restriction_type = Type::Any()) { |
| 793 VisitBinop(node, input_use, input_use, output, type_check); | 756 VisitBinop(node, input_use, input_use, output, restriction_type); |
| 794 } | 757 } |
| 795 | 758 |
| 796 // Helper for unops of the I -> O variety. | 759 // Helper for unops of the I -> O variety. |
| 797 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { | 760 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { |
| 798 DCHECK_EQ(1, node->op()->ValueInputCount()); | 761 DCHECK_EQ(1, node->op()->ValueInputCount()); |
| 799 ProcessInput(node, 0, input_use); | 762 ProcessInput(node, 0, input_use); |
| 800 ProcessRemainingInputs(node, 1); | 763 ProcessRemainingInputs(node, 1); |
| 801 SetOutput(node, output); | 764 SetOutput(node, output); |
| 802 } | 765 } |
| 803 | 766 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 } | 962 } |
| 1000 | 963 |
| 1001 const Operator* Int32OverflowOp(Node* node) { | 964 const Operator* Int32OverflowOp(Node* node) { |
| 1002 return changer_->Int32OverflowOperatorFor(node->opcode()); | 965 return changer_->Int32OverflowOperatorFor(node->opcode()); |
| 1003 } | 966 } |
| 1004 | 967 |
| 1005 const Operator* Uint32Op(Node* node) { | 968 const Operator* Uint32Op(Node* node) { |
| 1006 return changer_->Uint32OperatorFor(node->opcode()); | 969 return changer_->Uint32OperatorFor(node->opcode()); |
| 1007 } | 970 } |
| 1008 | 971 |
| 972 const Operator* Uint32OverflowOp(Node* node) { |
| 973 return changer_->Uint32OverflowOperatorFor(node->opcode()); |
| 974 } |
| 975 |
| 1009 const Operator* Float64Op(Node* node) { | 976 const Operator* Float64Op(Node* node) { |
| 1010 return changer_->Float64OperatorFor(node->opcode()); | 977 return changer_->Float64OperatorFor(node->opcode()); |
| 1011 } | 978 } |
| 1012 | 979 |
| 1013 WriteBarrierKind WriteBarrierKindFor( | 980 WriteBarrierKind WriteBarrierKindFor( |
| 1014 BaseTaggedness base_taggedness, | 981 BaseTaggedness base_taggedness, |
| 1015 MachineRepresentation field_representation, Type* field_type, | 982 MachineRepresentation field_representation, Type* field_type, |
| 1016 Node* value) { | 983 Node* value) { |
| 1017 if (base_taggedness == kTaggedBase && | 984 if (base_taggedness == kTaggedBase && |
| 1018 field_representation == MachineRepresentation::kTagged) { | 985 field_representation == MachineRepresentation::kTagged) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1101 Node* effect = NodeProperties::GetEffectInput(node); | 1068 Node* effect = NodeProperties::GetEffectInput(node); |
| 1102 ReplaceEffectControlUses(node, effect, control); | 1069 ReplaceEffectControlUses(node, effect, control); |
| 1103 node->TrimInputCount(new_op->ValueInputCount()); | 1070 node->TrimInputCount(new_op->ValueInputCount()); |
| 1104 } else { | 1071 } else { |
| 1105 DCHECK_EQ(0, node->op()->ControlInputCount()); | 1072 DCHECK_EQ(0, node->op()->ControlInputCount()); |
| 1106 } | 1073 } |
| 1107 | 1074 |
| 1108 NodeProperties::ChangeOp(node, new_op); | 1075 NodeProperties::ChangeOp(node, new_op); |
| 1109 } | 1076 } |
| 1110 | 1077 |
| 1111 void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) { | 1078 void ChangeToInt32OverflowOp(Node* node) { |
| 1112 NodeProperties::ChangeOp(node, new_op); | 1079 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); |
| 1080 } |
| 1081 |
| 1082 void ChangeToUint32OverflowOp(Node* node) { |
| 1083 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); |
| 1113 } | 1084 } |
| 1114 | 1085 |
| 1115 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 1086 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
| 1116 SimplifiedLowering* lowering) { | 1087 SimplifiedLowering* lowering) { |
| 1117 if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 1088 if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && |
| 1118 NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1089 NodeProperties::GetType(node)->Is(Type::Signed32())) { |
| 1119 // int32 + int32 = int32 ==> signed Int32Add/Sub | 1090 // int32 + int32 = int32 ==> signed Int32Add/Sub |
| 1120 VisitInt32Binop(node); | 1091 VisitInt32Binop(node); |
| 1121 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1092 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1122 return; | 1093 return; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1137 | 1108 |
| 1138 // Handle the case when no int32 checks on inputs are necessary | 1109 // Handle the case when no int32 checks on inputs are necessary |
| 1139 // (but an overflow check is needed on the output). | 1110 // (but an overflow check is needed on the output). |
| 1140 if (BothInputsAre(node, Type::Signed32()) || | 1111 if (BothInputsAre(node, Type::Signed32()) || |
| 1141 (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && | 1112 (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) && |
| 1142 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | 1113 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { |
| 1143 // If both the inputs the feedback are int32, use the overflow op. | 1114 // If both the inputs the feedback are int32, use the overflow op. |
| 1144 if (hint == BinaryOperationHints::kSignedSmall || | 1115 if (hint == BinaryOperationHints::kSignedSmall || |
| 1145 hint == BinaryOperationHints::kSigned32) { | 1116 hint == BinaryOperationHints::kSigned32) { |
| 1146 VisitBinop(node, UseInfo::TruncatingWord32(), | 1117 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1147 MachineRepresentation::kWord32, TypeCheckKind::kSigned32); | 1118 MachineRepresentation::kWord32, Type::Signed32()); |
| 1148 if (lower()) { | 1119 if (lower()) ChangeToInt32OverflowOp(node); |
| 1149 ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1150 } | |
| 1151 return; | 1120 return; |
| 1152 } | 1121 } |
| 1153 } | 1122 } |
| 1154 | 1123 |
| 1155 if (hint == BinaryOperationHints::kSignedSmall || | 1124 if (hint == BinaryOperationHints::kSignedSmall || |
| 1156 hint == BinaryOperationHints::kSigned32) { | 1125 hint == BinaryOperationHints::kSigned32) { |
| 1157 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1126 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| 1158 MachineRepresentation::kWord32, TypeCheckKind::kSigned32); | 1127 MachineRepresentation::kWord32, Type::Signed32()); |
| 1159 if (lower()) { | 1128 if (lower()) ChangeToInt32OverflowOp(node); |
| 1160 ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1161 } | |
| 1162 return; | 1129 return; |
| 1163 } | 1130 } |
| 1164 | 1131 |
| 1165 // default case => Float64Add/Sub | 1132 // default case => Float64Add/Sub |
| 1166 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1133 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1167 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1134 MachineRepresentation::kFloat64, Type::Number()); |
| 1168 if (lower()) { | 1135 if (lower()) { |
| 1169 ChangeToPureOp(node, Float64Op(node)); | 1136 ChangeToPureOp(node, Float64Op(node)); |
| 1170 } | 1137 } |
| 1171 return; | 1138 return; |
| 1172 } | 1139 } |
| 1173 | 1140 |
| 1174 // Dispatching routine for visiting the node {node} with the usage {use}. | 1141 // Dispatching routine for visiting the node {node} with the usage {use}. |
| 1175 // Depending on the operator, propagate new usage info to the inputs. | 1142 // Depending on the operator, propagate new usage info to the inputs. |
| 1176 void VisitNode(Node* node, Truncation truncation, | 1143 void VisitNode(Node* node, Truncation truncation, |
| 1177 SimplifiedLowering* lowering) { | 1144 SimplifiedLowering* lowering) { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1308 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
| 1342 } else { | 1309 } else { |
| 1343 // => Float64Add/Sub | 1310 // => Float64Add/Sub |
| 1344 VisitFloat64Binop(node); | 1311 VisitFloat64Binop(node); |
| 1345 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1312 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
| 1346 } | 1313 } |
| 1347 return; | 1314 return; |
| 1348 } | 1315 } |
| 1349 case IrOpcode::kSpeculativeNumberMultiply: | 1316 case IrOpcode::kSpeculativeNumberMultiply: |
| 1350 case IrOpcode::kNumberMultiply: { | 1317 case IrOpcode::kNumberMultiply: { |
| 1351 if (BothInputsAreSigned32(node)) { | 1318 if (BothInputsAre(node, Type::Integral32()) && |
| 1352 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1319 (NodeProperties::GetType(node)->Is(Type::Signed32()) || |
| 1353 // Multiply reduces to Int32Mul if the inputs and the output | 1320 NodeProperties::GetType(node)->Is(Type::Unsigned32()) || |
| 1354 // are integers. | 1321 (truncation.TruncatesToWord32() && |
| 1355 VisitInt32Binop(node); | |
| 1356 if (lower()) ChangeToPureOp(node, Int32Op(node)); | |
| 1357 return; | |
| 1358 } | |
| 1359 if (truncation.TruncatesToWord32() && | |
| 1360 NodeProperties::GetType(node)->Is( | 1322 NodeProperties::GetType(node)->Is( |
| 1361 type_cache_.kSafeIntegerOrMinusZero)) { | 1323 type_cache_.kSafeIntegerOrMinusZero)))) { |
| 1362 // Multiply reduces to Int32Mul if the inputs are integers, | 1324 // Multiply reduces to Int32Mul if the inputs are integers, and |
| 1363 // the uses are truncating and the result is in the safe | 1325 // (a) the output is either known to be Signed32, or |
| 1364 // integer range. | 1326 // (b) the output is known to be Unsigned32, or |
| 1365 VisitWord32TruncatingBinop(node); | 1327 // (c) the uses are truncating and the result is in the safe |
| 1366 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1328 // integer range. |
| 1367 return; | 1329 VisitWord32TruncatingBinop(node); |
| 1368 } | 1330 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1331 return; |
| 1369 } | 1332 } |
| 1370 // Number x Number => Float64Mul | 1333 // Number x Number => Float64Mul |
| 1371 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 1334 if (BothInputsAre(node, Type::NumberOrUndefined())) { |
| 1372 VisitFloat64Binop(node); | 1335 VisitFloat64Binop(node); |
| 1373 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1336 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1374 return; | 1337 return; |
| 1375 } | 1338 } |
| 1376 // Checked float64 x float64 => float64 | 1339 // Checked float64 x float64 => float64 |
| 1377 DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); | 1340 DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); |
| 1378 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1341 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1379 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1342 MachineRepresentation::kFloat64, Type::Number()); |
| 1380 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1343 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1381 return; | 1344 return; |
| 1382 } | 1345 } |
| 1383 case IrOpcode::kSpeculativeNumberDivide: { | 1346 case IrOpcode::kSpeculativeNumberDivide: { |
| 1384 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1347 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
| 1385 // => unsigned Uint32Div | 1348 // => unsigned Uint32Div |
| 1386 VisitWord32TruncatingBinop(node); | 1349 VisitWord32TruncatingBinop(node); |
| 1387 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 1350 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); |
| 1388 return; | 1351 return; |
| 1389 } | 1352 } |
| 1390 if (BothInputsAreSigned32(node)) { | 1353 if (BothInputsAreSigned32(node)) { |
| 1391 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1354 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
| 1392 // => signed Int32Div | 1355 // => signed Int32Div |
| 1393 VisitInt32Binop(node); | 1356 VisitInt32Binop(node); |
| 1394 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1357 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
| 1395 return; | 1358 return; |
| 1396 } | 1359 } |
| 1397 if (truncation.TruncatesToWord32()) { | 1360 if (truncation.TruncatesToWord32()) { |
| 1398 // => signed Int32Div | 1361 // => signed Int32Div |
| 1399 VisitWord32TruncatingBinop(node); | 1362 VisitWord32TruncatingBinop(node); |
| 1400 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1363 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
| 1401 return; | 1364 return; |
| 1402 } | 1365 } |
| 1403 } | 1366 } |
| 1404 | 1367 |
| 1405 // Try to use type feedback. | 1368 // Try to use type feedback. |
| 1406 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 1369 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
| 1407 | 1370 |
| 1371 // Handle the case when no uint32 checks on inputs are necessary |
| 1372 // (but an overflow check is needed on the output). |
| 1373 if (BothInputsAreUnsigned32(node)) { |
| 1374 if (hint == BinaryOperationHints::kSignedSmall || |
| 1375 hint == BinaryOperationHints::kSigned32) { |
| 1376 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1377 MachineRepresentation::kWord32, Type::Unsigned32()); |
| 1378 if (lower()) ChangeToUint32OverflowOp(node); |
| 1379 return; |
| 1380 } |
| 1381 } |
| 1382 |
| 1408 // Handle the case when no int32 checks on inputs are necessary | 1383 // Handle the case when no int32 checks on inputs are necessary |
| 1409 // (but an overflow check is needed on the output). | 1384 // (but an overflow check is needed on the output). |
| 1410 if (BothInputsAre(node, Type::Signed32())) { | 1385 if (BothInputsAreSigned32(node)) { |
| 1411 // If both the inputs the feedback are int32, use the overflow op. | 1386 // If both the inputs the feedback are int32, use the overflow op. |
| 1412 if (hint == BinaryOperationHints::kSignedSmall || | 1387 if (hint == BinaryOperationHints::kSignedSmall || |
| 1413 hint == BinaryOperationHints::kSigned32) { | 1388 hint == BinaryOperationHints::kSigned32) { |
| 1414 VisitBinop(node, UseInfo::TruncatingWord32(), | 1389 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1415 MachineRepresentation::kWord32, | 1390 MachineRepresentation::kWord32, Type::Signed32()); |
| 1416 TypeCheckKind::kSigned32); | 1391 if (lower()) ChangeToInt32OverflowOp(node); |
| 1417 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1418 return; | 1392 return; |
| 1419 } | 1393 } |
| 1420 } | 1394 } |
| 1421 | 1395 |
| 1422 if (hint == BinaryOperationHints::kSignedSmall || | 1396 if (hint == BinaryOperationHints::kSignedSmall || |
| 1423 hint == BinaryOperationHints::kSigned32) { | 1397 hint == BinaryOperationHints::kSigned32) { |
| 1424 // If the result is truncated, we only need to check the inputs. | 1398 // If the result is truncated, we only need to check the inputs. |
| 1425 if (truncation.TruncatesToWord32()) { | 1399 if (truncation.TruncatesToWord32()) { |
| 1426 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1400 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| 1427 MachineRepresentation::kWord32); | 1401 MachineRepresentation::kWord32); |
| 1428 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1402 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
| 1429 } else { | 1403 } else { |
| 1430 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1404 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| 1431 MachineRepresentation::kWord32, | 1405 MachineRepresentation::kWord32, Type::Signed32()); |
| 1432 TypeCheckKind::kSigned32); | 1406 if (lower()) ChangeToInt32OverflowOp(node); |
| 1433 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1434 } | 1407 } |
| 1435 return; | 1408 return; |
| 1436 } | 1409 } |
| 1437 | 1410 |
| 1438 // default case => Float64Div | 1411 // default case => Float64Div |
| 1439 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1412 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1440 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1413 MachineRepresentation::kFloat64, Type::Number()); |
| 1441 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1414 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1442 return; | 1415 return; |
| 1443 } | 1416 } |
| 1444 case IrOpcode::kNumberDivide: { | 1417 case IrOpcode::kNumberDivide: { |
| 1445 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1418 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
| 1446 // => unsigned Uint32Div | 1419 // => unsigned Uint32Div |
| 1447 VisitWord32TruncatingBinop(node); | 1420 VisitWord32TruncatingBinop(node); |
| 1448 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 1421 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); |
| 1449 return; | 1422 return; |
| 1450 } | 1423 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1464 } | 1437 } |
| 1465 // Number x Number => Float64Div | 1438 // Number x Number => Float64Div |
| 1466 if (BothInputsAre(node, Type::NumberOrUndefined())) { | 1439 if (BothInputsAre(node, Type::NumberOrUndefined())) { |
| 1467 VisitFloat64Binop(node); | 1440 VisitFloat64Binop(node); |
| 1468 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1441 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1469 return; | 1442 return; |
| 1470 } | 1443 } |
| 1471 // Checked float64 x float64 => float64 | 1444 // Checked float64 x float64 => float64 |
| 1472 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); | 1445 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); |
| 1473 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1446 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1474 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1447 MachineRepresentation::kFloat64, Type::Number()); |
| 1475 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1448 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1476 return; | 1449 return; |
| 1477 } | 1450 } |
| 1478 case IrOpcode::kSpeculativeNumberModulus: { | 1451 case IrOpcode::kSpeculativeNumberModulus: { |
| 1479 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1452 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
| 1480 // => unsigned Uint32Mod | 1453 // => unsigned Uint32Mod |
| 1481 VisitWord32TruncatingBinop(node); | 1454 VisitWord32TruncatingBinop(node); |
| 1482 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1455 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1483 return; | 1456 return; |
| 1484 } | 1457 } |
| 1485 if (BothInputsAreSigned32(node)) { | 1458 if (BothInputsAreSigned32(node)) { |
| 1486 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1459 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
| 1487 // => signed Int32Mod | 1460 // => signed Int32Mod |
| 1488 VisitInt32Binop(node); | 1461 VisitInt32Binop(node); |
| 1489 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1462 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1490 return; | 1463 return; |
| 1491 } | 1464 } |
| 1492 if (truncation.TruncatesToWord32()) { | 1465 if (truncation.TruncatesToWord32()) { |
| 1493 // => signed Int32Mod | 1466 // => signed Int32Mod |
| 1494 VisitWord32TruncatingBinop(node); | 1467 VisitWord32TruncatingBinop(node); |
| 1495 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1468 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1496 return; | 1469 return; |
| 1497 } | 1470 } |
| 1498 } | 1471 } |
| 1499 | 1472 |
| 1500 // Try to use type feedback. | 1473 // Try to use type feedback. |
| 1501 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); | 1474 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
| 1502 | 1475 |
| 1476 // Handle the case when no uint32 checks on inputs are necessary |
| 1477 // (but an overflow check is needed on the output). |
| 1478 if (BothInputsAreUnsigned32(node)) { |
| 1479 if (hint == BinaryOperationHints::kSignedSmall || |
| 1480 hint == BinaryOperationHints::kSigned32) { |
| 1481 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1482 MachineRepresentation::kWord32, Type::Unsigned32()); |
| 1483 if (lower()) ChangeToUint32OverflowOp(node); |
| 1484 return; |
| 1485 } |
| 1486 } |
| 1487 |
| 1503 // Handle the case when no int32 checks on inputs are necessary | 1488 // Handle the case when no int32 checks on inputs are necessary |
| 1504 // (but an overflow check is needed on the output). | 1489 // (but an overflow check is needed on the output). |
| 1505 if (BothInputsAre(node, Type::Signed32())) { | 1490 if (BothInputsAre(node, Type::Signed32())) { |
| 1506 // If both the inputs the feedback are int32, use the overflow op. | 1491 // If both the inputs the feedback are int32, use the overflow op. |
| 1507 if (hint == BinaryOperationHints::kSignedSmall || | 1492 if (hint == BinaryOperationHints::kSignedSmall || |
| 1508 hint == BinaryOperationHints::kSigned32) { | 1493 hint == BinaryOperationHints::kSigned32) { |
| 1509 VisitBinop(node, UseInfo::TruncatingWord32(), | 1494 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1510 MachineRepresentation::kWord32, | 1495 MachineRepresentation::kWord32, Type::Signed32()); |
| 1511 TypeCheckKind::kSigned32); | 1496 if (lower()) ChangeToInt32OverflowOp(node); |
| 1512 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1513 return; | 1497 return; |
| 1514 } | 1498 } |
| 1515 } | 1499 } |
| 1516 | 1500 |
| 1517 if (hint == BinaryOperationHints::kSignedSmall || | 1501 if (hint == BinaryOperationHints::kSignedSmall || |
| 1518 hint == BinaryOperationHints::kSigned32) { | 1502 hint == BinaryOperationHints::kSigned32) { |
| 1519 // If the result is truncated, we only need to check the inputs. | 1503 // If the result is truncated, we only need to check the inputs. |
| 1520 if (truncation.TruncatesToWord32()) { | 1504 if (truncation.TruncatesToWord32()) { |
| 1521 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1505 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| 1522 MachineRepresentation::kWord32); | 1506 MachineRepresentation::kWord32); |
| 1523 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1507 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
| 1524 } else { | 1508 } else { |
| 1525 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 1509 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| 1526 MachineRepresentation::kWord32, | 1510 MachineRepresentation::kWord32, Type::Signed32()); |
| 1527 TypeCheckKind::kSigned32); | 1511 if (lower()) ChangeToInt32OverflowOp(node); |
| 1528 if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); | |
| 1529 } | 1512 } |
| 1530 return; | 1513 return; |
| 1531 } | 1514 } |
| 1532 | 1515 |
| 1533 // default case => Float64Mod | 1516 // default case => Float64Mod |
| 1534 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), | 1517 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1535 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); | 1518 MachineRepresentation::kFloat64, Type::Number()); |
| 1536 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1519 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1537 return; | 1520 return; |
| 1538 } | 1521 } |
| 1539 case IrOpcode::kNumberModulus: { | 1522 case IrOpcode::kNumberModulus: { |
| 1540 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1523 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
| 1541 // => unsigned Uint32Mod | 1524 // => unsigned Uint32Mod |
| 1542 VisitWord32TruncatingBinop(node); | 1525 VisitWord32TruncatingBinop(node); |
| 1543 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1526 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
| 1544 return; | 1527 return; |
| 1545 } | 1528 } |
| (...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3288 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3271 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3289 Operator::kNoProperties); | 3272 Operator::kNoProperties); |
| 3290 to_number_operator_.set(common()->Call(desc)); | 3273 to_number_operator_.set(common()->Call(desc)); |
| 3291 } | 3274 } |
| 3292 return to_number_operator_.get(); | 3275 return to_number_operator_.get(); |
| 3293 } | 3276 } |
| 3294 | 3277 |
| 3295 } // namespace compiler | 3278 } // namespace compiler |
| 3296 } // namespace internal | 3279 } // namespace internal |
| 3297 } // namespace v8 | 3280 } // namespace v8 |
| OLD | NEW |