| 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 |