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 |