| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 158 |
| 159 | 159 |
| 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 161 const Register result = locs()->out(0).reg(); | 161 const Register result = locs()->out(0).reg(); |
| 162 | 162 |
| 163 Location left = locs()->in(0); | 163 Location left = locs()->in(0); |
| 164 Location right = locs()->in(1); | 164 Location right = locs()->in(1); |
| 165 ASSERT(!left.IsConstant() || !right.IsConstant()); | 165 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 166 | 166 |
| 167 // Emit comparison code. This must not overwrite the result register. | 167 // Emit comparison code. This must not overwrite the result register. |
| 168 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using |
| 169 // the labels or returning an invalid condition. |
| 168 BranchLabels labels = {NULL, NULL, NULL}; | 170 BranchLabels labels = {NULL, NULL, NULL}; |
| 169 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 171 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 172 ASSERT(true_condition != kInvalidCondition); |
| 170 | 173 |
| 171 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 174 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 172 | 175 |
| 173 intptr_t true_value = if_true_; | 176 intptr_t true_value = if_true_; |
| 174 intptr_t false_value = if_false_; | 177 intptr_t false_value = if_false_; |
| 175 | 178 |
| 176 if (is_power_of_two_kind) { | 179 if (is_power_of_two_kind) { |
| 177 if (true_value == 0) { | 180 if (true_value == 0) { |
| 178 // We need to have zero in result on true_condition. | 181 // We need to have zero in result on true_condition. |
| 179 true_condition = NegateCondition(true_condition); | 182 true_condition = NegateCondition(true_condition); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 return GE; | 536 return GE; |
| 534 default: | 537 default: |
| 535 UNREACHABLE(); | 538 UNREACHABLE(); |
| 536 return VS; | 539 return VS; |
| 537 } | 540 } |
| 538 } | 541 } |
| 539 | 542 |
| 540 | 543 |
| 541 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 544 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 542 LocationSummary* locs, | 545 LocationSummary* locs, |
| 546 BranchLabels labels, |
| 543 Token::Kind kind) { | 547 Token::Kind kind) { |
| 544 const VRegister left = locs->in(0).fpu_reg(); | 548 const VRegister left = locs->in(0).fpu_reg(); |
| 545 const VRegister right = locs->in(1).fpu_reg(); | 549 const VRegister right = locs->in(1).fpu_reg(); |
| 546 __ fcmpd(left, right); | 550 __ fcmpd(left, right); |
| 547 Condition true_condition = TokenKindToDoubleCondition(kind); | 551 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 552 if (true_condition != NE) { |
| 553 // Special case for NaN comparison. Result is always false unless |
| 554 // relational operator is !=. |
| 555 __ b(labels.false_label, VS); |
| 556 } |
| 548 return true_condition; | 557 return true_condition; |
| 549 } | 558 } |
| 550 | 559 |
| 551 | 560 |
| 552 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 561 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 553 BranchLabels labels) { | 562 BranchLabels labels) { |
| 554 if (operation_cid() == kSmiCid) { | 563 if (operation_cid() == kSmiCid) { |
| 555 return EmitSmiComparisonOp(compiler, locs(), kind()); | 564 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 556 } else { | 565 } else { |
| 557 ASSERT(operation_cid() == kDoubleCid); | 566 ASSERT(operation_cid() == kDoubleCid); |
| 558 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 567 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); |
| 559 } | 568 } |
| 560 } | 569 } |
| 561 | 570 |
| 562 | 571 |
| 563 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 564 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | |
| 565 Label is_true, is_false; | |
| 566 BranchLabels labels = {&is_true, &is_false, &is_false}; | |
| 567 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 568 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | |
| 569 // Special case for NaN comparison. Result is always false unless | |
| 570 // relational operator is !=. | |
| 571 __ b(&is_false, VS); | |
| 572 } | |
| 573 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 574 // TODO(zra): instead of branching, use the csel instruction to get | |
| 575 // True or False into result. | |
| 576 const Register result = locs()->out(0).reg(); | |
| 577 Label done; | |
| 578 __ Bind(&is_false); | |
| 579 __ LoadObject(result, Bool::False()); | |
| 580 __ b(&done); | |
| 581 __ Bind(&is_true); | |
| 582 __ LoadObject(result, Bool::True()); | |
| 583 __ Bind(&done); | |
| 584 } | |
| 585 | |
| 586 | |
| 587 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 588 BranchInstr* branch) { | |
| 589 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | |
| 590 | |
| 591 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 592 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 593 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | |
| 594 // Special case for NaN comparison. Result is always false unless | |
| 595 // relational operator is !=. | |
| 596 __ b(labels.false_label, VS); | |
| 597 } | |
| 598 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 599 } | |
| 600 | |
| 601 | |
| 602 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 572 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 603 const intptr_t kNumInputs = 2; | 573 const intptr_t kNumInputs = 2; |
| 604 const intptr_t kNumTemps = 0; | 574 const intptr_t kNumTemps = 0; |
| 605 LocationSummary* locs = new (zone) | 575 LocationSummary* locs = new (zone) |
| 606 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 576 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 607 locs->set_in(0, Location::RequiresRegister()); | 577 locs->set_in(0, Location::RequiresRegister()); |
| 608 // Only one input can be a constant operand. The case of two constant | 578 // Only one input can be a constant operand. The case of two constant |
| 609 // operands should be handled by constant propagation. | 579 // operands should be handled by constant propagation. |
| 610 locs->set_in(1, Location::RegisterOrConstant(right())); | 580 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 611 return locs; | 581 return locs; |
| 612 } | 582 } |
| 613 | 583 |
| 614 | 584 |
| 615 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 585 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 616 BranchLabels labels) { | 586 BranchLabels labels) { |
| 617 const Register left = locs()->in(0).reg(); | 587 const Register left = locs()->in(0).reg(); |
| 618 Location right = locs()->in(1); | 588 Location right = locs()->in(1); |
| 619 if (right.IsConstant()) { | 589 if (right.IsConstant()) { |
| 620 ASSERT(right.constant().IsSmi()); | 590 ASSERT(right.constant().IsSmi()); |
| 621 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); | 591 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
| 622 __ TestImmediate(left, imm); | 592 __ TestImmediate(left, imm); |
| 623 } else { | 593 } else { |
| 624 __ tst(left, Operand(right.reg())); | 594 __ tst(left, Operand(right.reg())); |
| 625 } | 595 } |
| 626 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 596 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 627 return true_condition; | 597 return true_condition; |
| 628 } | 598 } |
| 629 | 599 |
| 630 | 600 |
| 631 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 632 // Never emitted outside of the BranchInstr. | |
| 633 UNREACHABLE(); | |
| 634 } | |
| 635 | |
| 636 | |
| 637 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 638 BranchInstr* branch) { | |
| 639 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 640 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 641 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 642 } | |
| 643 | |
| 644 | |
| 645 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 601 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 646 bool opt) const { | 602 bool opt) const { |
| 647 const intptr_t kNumInputs = 1; | 603 const intptr_t kNumInputs = 1; |
| 648 const intptr_t kNumTemps = 1; | 604 const intptr_t kNumTemps = 1; |
| 649 LocationSummary* locs = new (zone) | 605 LocationSummary* locs = new (zone) |
| 650 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 606 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 651 locs->set_in(0, Location::RequiresRegister()); | 607 locs->set_in(0, Location::RequiresRegister()); |
| 652 locs->set_temp(0, Location::RequiresRegister()); | 608 locs->set_temp(0, Location::RequiresRegister()); |
| 653 locs->set_out(0, Location::RequiresRegister()); | 609 locs->set_out(0, Location::RequiresRegister()); |
| 654 return locs; | 610 return locs; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 // If the cid is not in the list, jump to the opposite label from the cids | 643 // If the cid is not in the list, jump to the opposite label from the cids |
| 688 // that are in the list. These must be all the same (see asserts in the | 644 // that are in the list. These must be all the same (see asserts in the |
| 689 // constructor). | 645 // constructor). |
| 690 Label* target = result ? labels.false_label : labels.true_label; | 646 Label* target = result ? labels.false_label : labels.true_label; |
| 691 if (target != labels.fall_through) { | 647 if (target != labels.fall_through) { |
| 692 __ b(target); | 648 __ b(target); |
| 693 } | 649 } |
| 694 } else { | 650 } else { |
| 695 __ b(deopt); | 651 __ b(deopt); |
| 696 } | 652 } |
| 697 // Dummy result as the last instruction is a jump, any conditional | 653 // Dummy result as this method already did the jump, there's no need |
| 698 // branch using the result will therefore be skipped. | 654 // for the caller to branch on a condition. |
| 699 return EQ; | 655 return kInvalidCondition; |
| 700 } | 656 } |
| 701 | 657 |
| 702 | 658 |
| 703 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 704 BranchInstr* branch) { | |
| 705 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 706 EmitComparisonCode(compiler, labels); | |
| 707 } | |
| 708 | |
| 709 | |
| 710 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 711 const Register result_reg = locs()->out(0).reg(); | |
| 712 Label is_true, is_false, done; | |
| 713 BranchLabels labels = {&is_true, &is_false, &is_false}; | |
| 714 EmitComparisonCode(compiler, labels); | |
| 715 // TODO(zra): instead of branching, use the csel instruction to get | |
| 716 // True or False into result. | |
| 717 __ Bind(&is_false); | |
| 718 __ LoadObject(result_reg, Bool::False()); | |
| 719 __ b(&done); | |
| 720 __ Bind(&is_true); | |
| 721 __ LoadObject(result_reg, Bool::True()); | |
| 722 __ Bind(&done); | |
| 723 } | |
| 724 | |
| 725 | |
| 726 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 659 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 727 bool opt) const { | 660 bool opt) const { |
| 728 const intptr_t kNumInputs = 2; | 661 const intptr_t kNumInputs = 2; |
| 729 const intptr_t kNumTemps = 0; | 662 const intptr_t kNumTemps = 0; |
| 730 if (operation_cid() == kDoubleCid) { | 663 if (operation_cid() == kDoubleCid) { |
| 731 LocationSummary* summary = new (zone) | 664 LocationSummary* summary = new (zone) |
| 732 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 665 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 733 summary->set_in(0, Location::RequiresFpuRegister()); | 666 summary->set_in(0, Location::RequiresFpuRegister()); |
| 734 summary->set_in(1, Location::RequiresFpuRegister()); | 667 summary->set_in(1, Location::RequiresFpuRegister()); |
| 735 summary->set_out(0, Location::RequiresRegister()); | 668 summary->set_out(0, Location::RequiresRegister()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 748 return summary; | 681 return summary; |
| 749 } | 682 } |
| 750 | 683 |
| 751 | 684 |
| 752 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 685 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 753 BranchLabels labels) { | 686 BranchLabels labels) { |
| 754 if (operation_cid() == kSmiCid) { | 687 if (operation_cid() == kSmiCid) { |
| 755 return EmitSmiComparisonOp(compiler, locs(), kind()); | 688 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 756 } else { | 689 } else { |
| 757 ASSERT(operation_cid() == kDoubleCid); | 690 ASSERT(operation_cid() == kDoubleCid); |
| 758 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 691 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); |
| 759 } | 692 } |
| 760 } | 693 } |
| 761 | 694 |
| 762 | 695 |
| 763 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 764 Label is_true, is_false; | |
| 765 BranchLabels labels = {&is_true, &is_false, &is_false}; | |
| 766 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 767 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | |
| 768 // Special case for NaN comparison. Result is always false unless | |
| 769 // relational operator is !=. | |
| 770 __ b(&is_false, VS); | |
| 771 } | |
| 772 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 773 // TODO(zra): instead of branching, use the csel instruction to get | |
| 774 // True or False into result. | |
| 775 const Register result = locs()->out(0).reg(); | |
| 776 Label done; | |
| 777 __ Bind(&is_false); | |
| 778 __ LoadObject(result, Bool::False()); | |
| 779 __ b(&done); | |
| 780 __ Bind(&is_true); | |
| 781 __ LoadObject(result, Bool::True()); | |
| 782 __ Bind(&done); | |
| 783 } | |
| 784 | |
| 785 | |
| 786 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 787 BranchInstr* branch) { | |
| 788 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 789 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 790 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | |
| 791 // Special case for NaN comparison. Result is always false unless | |
| 792 // relational operator is !=. | |
| 793 __ b(labels.false_label, VS); | |
| 794 } | |
| 795 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 796 } | |
| 797 | |
| 798 | |
| 799 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 696 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
| 800 bool opt) const { | 697 bool opt) const { |
| 801 return MakeCallSummary(zone); | 698 return MakeCallSummary(zone); |
| 802 } | 699 } |
| 803 | 700 |
| 804 | 701 |
| 805 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 702 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 806 SetupNative(); | 703 SetupNative(); |
| 807 const Register result = locs()->out(0).reg(); | 704 const Register result = locs()->out(0).reg(); |
| 808 | 705 |
| (...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3110 | 3007 |
| 3111 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3008 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3112 BranchInstr* branch) { | 3009 BranchInstr* branch) { |
| 3113 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3010 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3114 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3011 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3115 this, compiler->CurrentTryIndex(), labels, | 3012 this, compiler->CurrentTryIndex(), labels, |
| 3116 /* merged = */ true); | 3013 /* merged = */ true); |
| 3117 compiler->AddSlowPathCode(slow_path); | 3014 compiler->AddSlowPathCode(slow_path); |
| 3118 EMIT_SMI_CHECK; | 3015 EMIT_SMI_CHECK; |
| 3119 Condition true_condition = EmitComparisonCode(compiler, labels); | 3016 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3017 ASSERT(true_condition != kInvalidCondition); |
| 3120 EmitBranchOnCondition(compiler, true_condition, labels); | 3018 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3121 __ Bind(slow_path->exit_label()); | 3019 __ Bind(slow_path->exit_label()); |
| 3122 } | 3020 } |
| 3123 | 3021 |
| 3124 | 3022 |
| 3125 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3023 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3126 Label true_label, false_label, done; | 3024 Label true_label, false_label, done; |
| 3127 BranchLabels labels = {&true_label, &false_label, &false_label}; | 3025 BranchLabels labels = {&true_label, &false_label, &false_label}; |
| 3128 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3026 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3129 this, compiler->CurrentTryIndex(), labels, | 3027 this, compiler->CurrentTryIndex(), labels, |
| 3130 /* merged = */ false); | 3028 /* merged = */ false); |
| 3131 compiler->AddSlowPathCode(slow_path); | 3029 compiler->AddSlowPathCode(slow_path); |
| 3132 EMIT_SMI_CHECK; | 3030 EMIT_SMI_CHECK; |
| 3133 Condition true_condition = EmitComparisonCode(compiler, labels); | 3031 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3032 ASSERT(true_condition != kInvalidCondition); |
| 3134 EmitBranchOnCondition(compiler, true_condition, labels); | 3033 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3135 Register result = locs()->out(0).reg(); | 3034 Register result = locs()->out(0).reg(); |
| 3136 __ Bind(&false_label); | 3035 __ Bind(&false_label); |
| 3137 __ LoadObject(result, Bool::False()); | 3036 __ LoadObject(result, Bool::False()); |
| 3138 __ b(&done); | 3037 __ b(&done); |
| 3139 __ Bind(&true_label); | 3038 __ Bind(&true_label); |
| 3140 __ LoadObject(result, Bool::True()); | 3039 __ LoadObject(result, Bool::True()); |
| 3141 __ Bind(&done); | 3040 __ Bind(&done); |
| 3142 __ Bind(slow_path->exit_label()); | 3041 __ Bind(slow_path->exit_label()); |
| 3143 } | 3042 } |
| (...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3752 __ vmovrd(temp, value, 0); | 3651 __ vmovrd(temp, value, 0); |
| 3753 // Mask off the sign. | 3652 // Mask off the sign. |
| 3754 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); | 3653 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); |
| 3755 // Compare with +infinity. | 3654 // Compare with +infinity. |
| 3756 __ CompareImmediate(temp, 0x7FF0000000000000LL); | 3655 __ CompareImmediate(temp, 0x7FF0000000000000LL); |
| 3757 return is_negated ? NE : EQ; | 3656 return is_negated ? NE : EQ; |
| 3758 } | 3657 } |
| 3759 } | 3658 } |
| 3760 | 3659 |
| 3761 | 3660 |
| 3762 void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 3763 BranchInstr* branch) { | |
| 3764 ASSERT(compiler->is_optimizing()); | |
| 3765 BranchLabels labels = compiler->CreateBranchLabels(branch); | |
| 3766 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 3767 EmitBranchOnCondition(compiler, true_condition, labels); | |
| 3768 } | |
| 3769 | |
| 3770 | |
| 3771 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 3772 ASSERT(compiler->is_optimizing()); | |
| 3773 Label is_true, is_false; | |
| 3774 BranchLabels labels = {&is_true, &is_false, &is_false}; | |
| 3775 Condition true_condition = EmitComparisonCode(compiler, labels); | |
| 3776 const Register result = locs()->out(0).reg(); | |
| 3777 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | |
| 3778 __ LoadObject(result, Bool::False()); | |
| 3779 __ LoadObject(TMP, Bool::True()); | |
| 3780 __ csel(result, TMP, result, true_condition); | |
| 3781 } else { | |
| 3782 __ LoadObject(result, Bool::False()); | |
| 3783 __ LoadObject(TMP, Bool::True()); | |
| 3784 __ csel(result, TMP, result, true_condition); | |
| 3785 } | |
| 3786 } | |
| 3787 | |
| 3788 | |
| 3789 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3661 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 3790 bool opt) const { | 3662 bool opt) const { |
| 3791 const intptr_t kNumInputs = 2; | 3663 const intptr_t kNumInputs = 2; |
| 3792 const intptr_t kNumTemps = 0; | 3664 const intptr_t kNumTemps = 0; |
| 3793 LocationSummary* summary = new (zone) | 3665 LocationSummary* summary = new (zone) |
| 3794 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3795 summary->set_in(0, Location::RequiresFpuRegister()); | 3667 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3796 summary->set_in(1, Location::RequiresFpuRegister()); | 3668 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3797 summary->set_out(0, Location::RequiresFpuRegister()); | 3669 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3798 return summary; | 3670 return summary; |
| (...skipping 2183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5982 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 5854 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
| 5983 } | 5855 } |
| 5984 if (kind() != Token::kEQ_STRICT) { | 5856 if (kind() != Token::kEQ_STRICT) { |
| 5985 ASSERT(kind() == Token::kNE_STRICT); | 5857 ASSERT(kind() == Token::kNE_STRICT); |
| 5986 true_condition = NegateCondition(true_condition); | 5858 true_condition = NegateCondition(true_condition); |
| 5987 } | 5859 } |
| 5988 return true_condition; | 5860 return true_condition; |
| 5989 } | 5861 } |
| 5990 | 5862 |
| 5991 | 5863 |
| 5992 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5864 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5993 __ Comment("StrictCompareInstr"); | |
| 5994 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | |
| 5995 | |
| 5996 Label is_true, is_false; | 5865 Label is_true, is_false; |
| 5997 BranchLabels labels = {&is_true, &is_false, &is_false}; | 5866 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 5998 Condition true_condition = EmitComparisonCode(compiler, labels); | 5867 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5999 EmitBranchOnCondition(compiler, true_condition, labels); | 5868 const Register result = this->locs()->out(0).reg(); |
| 6000 | 5869 |
| 6001 const Register result = locs()->out(0).reg(); | 5870 // TODO(dartbug.com/29908): Use csel here for better branch prediction? |
| 5871 if (true_condition != kInvalidCondition) { |
| 5872 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5873 } |
| 6002 Label done; | 5874 Label done; |
| 6003 __ Bind(&is_false); | 5875 __ Bind(&is_false); |
| 6004 __ LoadObject(result, Bool::False()); | 5876 __ LoadObject(result, Bool::False()); |
| 6005 __ b(&done); | 5877 __ b(&done); |
| 6006 __ Bind(&is_true); | 5878 __ Bind(&is_true); |
| 6007 __ LoadObject(result, Bool::True()); | 5879 __ LoadObject(result, Bool::True()); |
| 6008 __ Bind(&done); | 5880 __ Bind(&done); |
| 6009 } | 5881 } |
| 6010 | 5882 |
| 6011 | 5883 |
| 6012 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 5884 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 6013 BranchInstr* branch) { | 5885 BranchInstr* branch) { |
| 6014 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | |
| 6015 | |
| 6016 BranchLabels labels = compiler->CreateBranchLabels(branch); | 5886 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 6017 Condition true_condition = EmitComparisonCode(compiler, labels); | 5887 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6018 EmitBranchOnCondition(compiler, true_condition, labels); | 5888 if (true_condition != kInvalidCondition) { |
| 5889 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5890 } |
| 6019 } | 5891 } |
| 6020 | 5892 |
| 6021 | 5893 |
| 6022 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 5894 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 6023 bool opt) const { | 5895 bool opt) const { |
| 6024 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 5896 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 6025 LocationSummary::kNoCall); | 5897 LocationSummary::kNoCall); |
| 6026 } | 5898 } |
| 6027 | 5899 |
| 6028 | 5900 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6082 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 5954 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
| 6083 kGrowRegExpStackRuntimeEntry, 1, locs()); | 5955 kGrowRegExpStackRuntimeEntry, 1, locs()); |
| 6084 __ Drop(1); | 5956 __ Drop(1); |
| 6085 __ Pop(result); | 5957 __ Pop(result); |
| 6086 } | 5958 } |
| 6087 | 5959 |
| 6088 | 5960 |
| 6089 } // namespace dart | 5961 } // namespace dart |
| 6090 | 5962 |
| 6091 #endif // defined TARGET_ARCH_ARM64 | 5963 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |