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. | |
170 BranchLabels labels = {NULL, NULL, NULL}; | 168 BranchLabels labels = {NULL, NULL, NULL}; |
171 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 169 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
172 ASSERT(true_condition != kInvalidCondition); | |
173 | 170 |
174 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 171 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
175 | 172 |
176 intptr_t true_value = if_true_; | 173 intptr_t true_value = if_true_; |
177 intptr_t false_value = if_false_; | 174 intptr_t false_value = if_false_; |
178 | 175 |
179 if (is_power_of_two_kind) { | 176 if (is_power_of_two_kind) { |
180 if (true_value == 0) { | 177 if (true_value == 0) { |
181 // We need to have zero in result on true_condition. | 178 // We need to have zero in result on true_condition. |
182 true_condition = NegateCondition(true_condition); | 179 true_condition = NegateCondition(true_condition); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 return GE; | 533 return GE; |
537 default: | 534 default: |
538 UNREACHABLE(); | 535 UNREACHABLE(); |
539 return VS; | 536 return VS; |
540 } | 537 } |
541 } | 538 } |
542 | 539 |
543 | 540 |
544 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 541 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
545 LocationSummary* locs, | 542 LocationSummary* locs, |
546 BranchLabels labels, | |
547 Token::Kind kind) { | 543 Token::Kind kind) { |
548 const VRegister left = locs->in(0).fpu_reg(); | 544 const VRegister left = locs->in(0).fpu_reg(); |
549 const VRegister right = locs->in(1).fpu_reg(); | 545 const VRegister right = locs->in(1).fpu_reg(); |
550 __ fcmpd(left, right); | 546 __ fcmpd(left, right); |
551 Condition true_condition = TokenKindToDoubleCondition(kind); | 547 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 } | |
557 return true_condition; | 548 return true_condition; |
558 } | 549 } |
559 | 550 |
560 | 551 |
561 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 552 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
562 BranchLabels labels) { | 553 BranchLabels labels) { |
563 if (operation_cid() == kSmiCid) { | 554 if (operation_cid() == kSmiCid) { |
564 return EmitSmiComparisonOp(compiler, locs(), kind()); | 555 return EmitSmiComparisonOp(compiler, locs(), kind()); |
565 } else { | 556 } else { |
566 ASSERT(operation_cid() == kDoubleCid); | 557 ASSERT(operation_cid() == kDoubleCid); |
567 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); | 558 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
568 } | 559 } |
569 } | 560 } |
570 | 561 |
571 | 562 |
| 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 |
572 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 602 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
573 const intptr_t kNumInputs = 2; | 603 const intptr_t kNumInputs = 2; |
574 const intptr_t kNumTemps = 0; | 604 const intptr_t kNumTemps = 0; |
575 LocationSummary* locs = new (zone) | 605 LocationSummary* locs = new (zone) |
576 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 606 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
577 locs->set_in(0, Location::RequiresRegister()); | 607 locs->set_in(0, Location::RequiresRegister()); |
578 // Only one input can be a constant operand. The case of two constant | 608 // Only one input can be a constant operand. The case of two constant |
579 // operands should be handled by constant propagation. | 609 // operands should be handled by constant propagation. |
580 locs->set_in(1, Location::RegisterOrConstant(right())); | 610 locs->set_in(1, Location::RegisterOrConstant(right())); |
581 return locs; | 611 return locs; |
582 } | 612 } |
583 | 613 |
584 | 614 |
585 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 615 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
586 BranchLabels labels) { | 616 BranchLabels labels) { |
587 const Register left = locs()->in(0).reg(); | 617 const Register left = locs()->in(0).reg(); |
588 Location right = locs()->in(1); | 618 Location right = locs()->in(1); |
589 if (right.IsConstant()) { | 619 if (right.IsConstant()) { |
590 ASSERT(right.constant().IsSmi()); | 620 ASSERT(right.constant().IsSmi()); |
591 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); | 621 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
592 __ TestImmediate(left, imm); | 622 __ TestImmediate(left, imm); |
593 } else { | 623 } else { |
594 __ tst(left, Operand(right.reg())); | 624 __ tst(left, Operand(right.reg())); |
595 } | 625 } |
596 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 626 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
597 return true_condition; | 627 return true_condition; |
598 } | 628 } |
599 | 629 |
600 | 630 |
| 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 |
601 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 645 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
602 bool opt) const { | 646 bool opt) const { |
603 const intptr_t kNumInputs = 1; | 647 const intptr_t kNumInputs = 1; |
604 const intptr_t kNumTemps = 1; | 648 const intptr_t kNumTemps = 1; |
605 LocationSummary* locs = new (zone) | 649 LocationSummary* locs = new (zone) |
606 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 650 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
607 locs->set_in(0, Location::RequiresRegister()); | 651 locs->set_in(0, Location::RequiresRegister()); |
608 locs->set_temp(0, Location::RequiresRegister()); | 652 locs->set_temp(0, Location::RequiresRegister()); |
609 locs->set_out(0, Location::RequiresRegister()); | 653 locs->set_out(0, Location::RequiresRegister()); |
610 return locs; | 654 return locs; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 // If the cid is not in the list, jump to the opposite label from the cids | 687 // If the cid is not in the list, jump to the opposite label from the cids |
644 // that are in the list. These must be all the same (see asserts in the | 688 // that are in the list. These must be all the same (see asserts in the |
645 // constructor). | 689 // constructor). |
646 Label* target = result ? labels.false_label : labels.true_label; | 690 Label* target = result ? labels.false_label : labels.true_label; |
647 if (target != labels.fall_through) { | 691 if (target != labels.fall_through) { |
648 __ b(target); | 692 __ b(target); |
649 } | 693 } |
650 } else { | 694 } else { |
651 __ b(deopt); | 695 __ b(deopt); |
652 } | 696 } |
653 // Dummy result as this method already did the jump, there's no need | 697 // Dummy result as the last instruction is a jump, any conditional |
654 // for the caller to branch on a condition. | 698 // branch using the result will therefore be skipped. |
655 return kInvalidCondition; | 699 return EQ; |
656 } | 700 } |
657 | 701 |
658 | 702 |
| 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 |
659 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 726 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
660 bool opt) const { | 727 bool opt) const { |
661 const intptr_t kNumInputs = 2; | 728 const intptr_t kNumInputs = 2; |
662 const intptr_t kNumTemps = 0; | 729 const intptr_t kNumTemps = 0; |
663 if (operation_cid() == kDoubleCid) { | 730 if (operation_cid() == kDoubleCid) { |
664 LocationSummary* summary = new (zone) | 731 LocationSummary* summary = new (zone) |
665 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 732 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
666 summary->set_in(0, Location::RequiresFpuRegister()); | 733 summary->set_in(0, Location::RequiresFpuRegister()); |
667 summary->set_in(1, Location::RequiresFpuRegister()); | 734 summary->set_in(1, Location::RequiresFpuRegister()); |
668 summary->set_out(0, Location::RequiresRegister()); | 735 summary->set_out(0, Location::RequiresRegister()); |
(...skipping 12 matching lines...) Expand all Loading... |
681 return summary; | 748 return summary; |
682 } | 749 } |
683 | 750 |
684 | 751 |
685 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 752 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
686 BranchLabels labels) { | 753 BranchLabels labels) { |
687 if (operation_cid() == kSmiCid) { | 754 if (operation_cid() == kSmiCid) { |
688 return EmitSmiComparisonOp(compiler, locs(), kind()); | 755 return EmitSmiComparisonOp(compiler, locs(), kind()); |
689 } else { | 756 } else { |
690 ASSERT(operation_cid() == kDoubleCid); | 757 ASSERT(operation_cid() == kDoubleCid); |
691 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); | 758 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
692 } | 759 } |
693 } | 760 } |
694 | 761 |
695 | 762 |
| 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 |
696 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 799 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
697 bool opt) const { | 800 bool opt) const { |
698 return MakeCallSummary(zone); | 801 return MakeCallSummary(zone); |
699 } | 802 } |
700 | 803 |
701 | 804 |
702 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 805 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
703 SetupNative(); | 806 SetupNative(); |
704 const Register result = locs()->out(0).reg(); | 807 const Register result = locs()->out(0).reg(); |
705 | 808 |
(...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3007 | 3110 |
3008 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3111 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
3009 BranchInstr* branch) { | 3112 BranchInstr* branch) { |
3010 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3113 BranchLabels labels = compiler->CreateBranchLabels(branch); |
3011 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3114 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3012 this, compiler->CurrentTryIndex(), labels, | 3115 this, compiler->CurrentTryIndex(), labels, |
3013 /* merged = */ true); | 3116 /* merged = */ true); |
3014 compiler->AddSlowPathCode(slow_path); | 3117 compiler->AddSlowPathCode(slow_path); |
3015 EMIT_SMI_CHECK; | 3118 EMIT_SMI_CHECK; |
3016 Condition true_condition = EmitComparisonCode(compiler, labels); | 3119 Condition true_condition = EmitComparisonCode(compiler, labels); |
3017 ASSERT(true_condition != kInvalidCondition); | |
3018 EmitBranchOnCondition(compiler, true_condition, labels); | 3120 EmitBranchOnCondition(compiler, true_condition, labels); |
3019 __ Bind(slow_path->exit_label()); | 3121 __ Bind(slow_path->exit_label()); |
3020 } | 3122 } |
3021 | 3123 |
3022 | 3124 |
3023 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3125 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3024 Label true_label, false_label, done; | 3126 Label true_label, false_label, done; |
3025 BranchLabels labels = {&true_label, &false_label, &false_label}; | 3127 BranchLabels labels = {&true_label, &false_label, &false_label}; |
3026 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 3128 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
3027 this, compiler->CurrentTryIndex(), labels, | 3129 this, compiler->CurrentTryIndex(), labels, |
3028 /* merged = */ false); | 3130 /* merged = */ false); |
3029 compiler->AddSlowPathCode(slow_path); | 3131 compiler->AddSlowPathCode(slow_path); |
3030 EMIT_SMI_CHECK; | 3132 EMIT_SMI_CHECK; |
3031 Condition true_condition = EmitComparisonCode(compiler, labels); | 3133 Condition true_condition = EmitComparisonCode(compiler, labels); |
3032 ASSERT(true_condition != kInvalidCondition); | |
3033 EmitBranchOnCondition(compiler, true_condition, labels); | 3134 EmitBranchOnCondition(compiler, true_condition, labels); |
3034 Register result = locs()->out(0).reg(); | 3135 Register result = locs()->out(0).reg(); |
3035 __ Bind(&false_label); | 3136 __ Bind(&false_label); |
3036 __ LoadObject(result, Bool::False()); | 3137 __ LoadObject(result, Bool::False()); |
3037 __ b(&done); | 3138 __ b(&done); |
3038 __ Bind(&true_label); | 3139 __ Bind(&true_label); |
3039 __ LoadObject(result, Bool::True()); | 3140 __ LoadObject(result, Bool::True()); |
3040 __ Bind(&done); | 3141 __ Bind(&done); |
3041 __ Bind(slow_path->exit_label()); | 3142 __ Bind(slow_path->exit_label()); |
3042 } | 3143 } |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3651 __ vmovrd(temp, value, 0); | 3752 __ vmovrd(temp, value, 0); |
3652 // Mask off the sign. | 3753 // Mask off the sign. |
3653 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); | 3754 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); |
3654 // Compare with +infinity. | 3755 // Compare with +infinity. |
3655 __ CompareImmediate(temp, 0x7FF0000000000000LL); | 3756 __ CompareImmediate(temp, 0x7FF0000000000000LL); |
3656 return is_negated ? NE : EQ; | 3757 return is_negated ? NE : EQ; |
3657 } | 3758 } |
3658 } | 3759 } |
3659 | 3760 |
3660 | 3761 |
| 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 |
3661 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3789 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
3662 bool opt) const { | 3790 bool opt) const { |
3663 const intptr_t kNumInputs = 2; | 3791 const intptr_t kNumInputs = 2; |
3664 const intptr_t kNumTemps = 0; | 3792 const intptr_t kNumTemps = 0; |
3665 LocationSummary* summary = new (zone) | 3793 LocationSummary* summary = new (zone) |
3666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3794 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3667 summary->set_in(0, Location::RequiresFpuRegister()); | 3795 summary->set_in(0, Location::RequiresFpuRegister()); |
3668 summary->set_in(1, Location::RequiresFpuRegister()); | 3796 summary->set_in(1, Location::RequiresFpuRegister()); |
3669 summary->set_out(0, Location::RequiresFpuRegister()); | 3797 summary->set_out(0, Location::RequiresFpuRegister()); |
3670 return summary; | 3798 return summary; |
(...skipping 2183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5854 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 5982 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
5855 } | 5983 } |
5856 if (kind() != Token::kEQ_STRICT) { | 5984 if (kind() != Token::kEQ_STRICT) { |
5857 ASSERT(kind() == Token::kNE_STRICT); | 5985 ASSERT(kind() == Token::kNE_STRICT); |
5858 true_condition = NegateCondition(true_condition); | 5986 true_condition = NegateCondition(true_condition); |
5859 } | 5987 } |
5860 return true_condition; | 5988 return true_condition; |
5861 } | 5989 } |
5862 | 5990 |
5863 | 5991 |
5864 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5992 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5993 __ Comment("StrictCompareInstr"); |
| 5994 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 5995 |
5865 Label is_true, is_false; | 5996 Label is_true, is_false; |
5866 BranchLabels labels = {&is_true, &is_false, &is_false}; | 5997 BranchLabels labels = {&is_true, &is_false, &is_false}; |
5867 Condition true_condition = EmitComparisonCode(compiler, labels); | 5998 Condition true_condition = EmitComparisonCode(compiler, labels); |
5868 const Register result = this->locs()->out(0).reg(); | 5999 EmitBranchOnCondition(compiler, true_condition, labels); |
5869 | 6000 |
5870 // TODO(dartbug.com/29908): Use csel here for better branch prediction? | 6001 const Register result = locs()->out(0).reg(); |
5871 if (true_condition != kInvalidCondition) { | |
5872 EmitBranchOnCondition(compiler, true_condition, labels); | |
5873 } | |
5874 Label done; | 6002 Label done; |
5875 __ Bind(&is_false); | 6003 __ Bind(&is_false); |
5876 __ LoadObject(result, Bool::False()); | 6004 __ LoadObject(result, Bool::False()); |
5877 __ b(&done); | 6005 __ b(&done); |
5878 __ Bind(&is_true); | 6006 __ Bind(&is_true); |
5879 __ LoadObject(result, Bool::True()); | 6007 __ LoadObject(result, Bool::True()); |
5880 __ Bind(&done); | 6008 __ Bind(&done); |
5881 } | 6009 } |
5882 | 6010 |
5883 | 6011 |
5884 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 6012 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
5885 BranchInstr* branch) { | 6013 BranchInstr* branch) { |
| 6014 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6015 |
5886 BranchLabels labels = compiler->CreateBranchLabels(branch); | 6016 BranchLabels labels = compiler->CreateBranchLabels(branch); |
5887 Condition true_condition = EmitComparisonCode(compiler, labels); | 6017 Condition true_condition = EmitComparisonCode(compiler, labels); |
5888 if (true_condition != kInvalidCondition) { | 6018 EmitBranchOnCondition(compiler, true_condition, labels); |
5889 EmitBranchOnCondition(compiler, true_condition, labels); | |
5890 } | |
5891 } | 6019 } |
5892 | 6020 |
5893 | 6021 |
5894 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6022 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
5895 bool opt) const { | 6023 bool opt) const { |
5896 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 6024 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
5897 LocationSummary::kNoCall); | 6025 LocationSummary::kNoCall); |
5898 } | 6026 } |
5899 | 6027 |
5900 | 6028 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5954 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), | 6082 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
5955 kGrowRegExpStackRuntimeEntry, 1, locs()); | 6083 kGrowRegExpStackRuntimeEntry, 1, locs()); |
5956 __ Drop(1); | 6084 __ Drop(1); |
5957 __ Pop(result); | 6085 __ Pop(result); |
5958 } | 6086 } |
5959 | 6087 |
5960 | 6088 |
5961 } // namespace dart | 6089 } // namespace dart |
5962 | 6090 |
5963 #endif // defined TARGET_ARCH_ARM64 | 6091 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |