Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(177)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 2937933002: Reduce copying, redundancy & repetition for codegen of comparison instructions (Closed)
Patch Set: Feedback from Slava Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/intermediate_language_dbc.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); 593 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
594 } else if (operation_cid() == kMintCid) { 594 } else if (operation_cid() == kMintCid) {
595 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); 595 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
596 } else { 596 } else {
597 ASSERT(operation_cid() == kDoubleCid); 597 ASSERT(operation_cid() == kDoubleCid);
598 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 598 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
599 } 599 }
600 } 600 }
601 601
602 602
603 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 603 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
604 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
605
606 Label is_true, is_false; 604 Label is_true, is_false;
607 BranchLabels labels = {&is_true, &is_false, &is_false}; 605 BranchLabels labels = {&is_true, &is_false, &is_false};
608 Condition true_condition = EmitComparisonCode(compiler, labels); 606 Condition true_condition = EmitComparisonCode(compiler, labels);
609 EmitBranchOnCondition(compiler, true_condition, labels); 607 if (true_condition != INVALID_CONDITION) {
608 EmitBranchOnCondition(compiler, true_condition, labels);
609 }
610 610
611 Register result = locs()->out(0).reg(); 611 Register result = locs()->out(0).reg();
612 Label done; 612 Label done;
613 __ Bind(&is_false); 613 __ Bind(&is_false);
614 __ LoadObject(result, Bool::False()); 614 __ LoadObject(result, Bool::False());
615 __ jmp(&done, Assembler::kNearJump); 615 __ jmp(&done, Assembler::kNearJump);
616 __ Bind(&is_true); 616 __ Bind(&is_true);
617 __ LoadObject(result, Bool::True()); 617 __ LoadObject(result, Bool::True());
618 __ Bind(&done); 618 __ Bind(&done);
619 } 619 }
620 620
621 621
622 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 622 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
623 BranchInstr* branch) { 623 BranchInstr* branch) {
624 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
625
626 BranchLabels labels = compiler->CreateBranchLabels(branch); 624 BranchLabels labels = compiler->CreateBranchLabels(branch);
627 Condition true_condition = EmitComparisonCode(compiler, labels); 625 Condition true_condition = EmitComparisonCode(compiler, labels);
628 EmitBranchOnCondition(compiler, true_condition, labels); 626 if (true_condition != INVALID_CONDITION) {
627 EmitBranchOnCondition(compiler, true_condition, labels);
628 }
629 } 629 }
630 630
631 631
632 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { 632 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
633 const intptr_t kNumInputs = 2; 633 const intptr_t kNumInputs = 2;
634 const intptr_t kNumTemps = 0; 634 const intptr_t kNumTemps = 0;
635 LocationSummary* locs = new (zone) 635 LocationSummary* locs = new (zone)
636 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 636 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
637 locs->set_in(0, Location::RequiresRegister()); 637 locs->set_in(0, Location::RequiresRegister());
638 // Only one input can be a constant operand. The case of two constant 638 // Only one input can be a constant operand. The case of two constant
(...skipping 12 matching lines...) Expand all
651 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); 651 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw());
652 __ testl(left, Immediate(imm)); 652 __ testl(left, Immediate(imm));
653 } else { 653 } else {
654 __ testl(left, right.reg()); 654 __ testl(left, right.reg());
655 } 655 }
656 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; 656 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
657 return true_condition; 657 return true_condition;
658 } 658 }
659 659
660 660
661 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
662 // Never emitted outside of the BranchInstr.
663 UNREACHABLE();
664 }
665
666
667 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
668 BranchInstr* branch) {
669 BranchLabels labels = compiler->CreateBranchLabels(branch);
670 Condition true_condition = EmitComparisonCode(compiler, labels);
671 EmitBranchOnCondition(compiler, true_condition, labels);
672 }
673
674
675 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, 661 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
676 bool opt) const { 662 bool opt) const {
677 const intptr_t kNumInputs = 1; 663 const intptr_t kNumInputs = 1;
678 const intptr_t kNumTemps = 1; 664 const intptr_t kNumTemps = 1;
679 LocationSummary* locs = new (zone) 665 LocationSummary* locs = new (zone)
680 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
681 locs->set_in(0, Location::RequiresRegister()); 667 locs->set_in(0, Location::RequiresRegister());
682 locs->set_temp(0, Location::RequiresRegister()); 668 locs->set_temp(0, Location::RequiresRegister());
683 locs->set_out(0, Location::RequiresRegister()); 669 locs->set_out(0, Location::RequiresRegister());
684 return locs; 670 return locs;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 // If the cid is not in the list, jump to the opposite label from the cids 702 // If the cid is not in the list, jump to the opposite label from the cids
717 // that are in the list. These must be all the same (see asserts in the 703 // that are in the list. These must be all the same (see asserts in the
718 // constructor). 704 // constructor).
719 Label* target = result ? labels.false_label : labels.true_label; 705 Label* target = result ? labels.false_label : labels.true_label;
720 if (target != labels.fall_through) { 706 if (target != labels.fall_through) {
721 __ jmp(target); 707 __ jmp(target);
722 } 708 }
723 } else { 709 } else {
724 __ jmp(deopt); 710 __ jmp(deopt);
725 } 711 }
726 // Dummy result as the last instruction is a jump, any conditional 712 // Dummy result as this method already did the jump, there's no need
727 // branch using the result will therefore be skipped. 713 // for the caller to branch on a condition.
728 return ZERO; 714 return INVALID_CONDITION;
729 } 715 }
730 716
731 717
732 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
733 BranchInstr* branch) {
734 BranchLabels labels = compiler->CreateBranchLabels(branch);
735 EmitComparisonCode(compiler, labels);
736 }
737
738
739 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
740 Register result_reg = locs()->out(0).reg();
741 Label is_true, is_false, done;
742 BranchLabels labels = {&is_true, &is_false, &is_false};
743 EmitComparisonCode(compiler, labels);
744 __ Bind(&is_false);
745 __ LoadObject(result_reg, Bool::False());
746 __ jmp(&done, Assembler::kNearJump);
747 __ Bind(&is_true);
748 __ LoadObject(result_reg, Bool::True());
749 __ Bind(&done);
750 }
751
752
753 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, 718 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone,
754 bool opt) const { 719 bool opt) const {
755 const intptr_t kNumInputs = 2; 720 const intptr_t kNumInputs = 2;
756 const intptr_t kNumTemps = 0; 721 const intptr_t kNumTemps = 0;
757 if (operation_cid() == kMintCid) { 722 if (operation_cid() == kMintCid) {
758 const intptr_t kNumTemps = 0; 723 const intptr_t kNumTemps = 0;
759 LocationSummary* locs = new (zone) 724 LocationSummary* locs = new (zone)
760 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 725 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
761 locs->set_in(0, Location::Pair(Location::RequiresRegister(), 726 locs->set_in(0, Location::Pair(Location::RequiresRegister(),
762 Location::RequiresRegister())); 727 Location::RequiresRegister()));
(...skipping 30 matching lines...) Expand all
793 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); 758 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
794 } else if (operation_cid() == kMintCid) { 759 } else if (operation_cid() == kMintCid) {
795 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); 760 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
796 } else { 761 } else {
797 ASSERT(operation_cid() == kDoubleCid); 762 ASSERT(operation_cid() == kDoubleCid);
798 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 763 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
799 } 764 }
800 } 765 }
801 766
802 767
803 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
804 Label is_true, is_false;
805 BranchLabels labels = {&is_true, &is_false, &is_false};
806 Condition true_condition = EmitComparisonCode(compiler, labels);
807 EmitBranchOnCondition(compiler, true_condition, labels);
808
809 Register result = locs()->out(0).reg();
810 Label done;
811 __ Bind(&is_false);
812 __ LoadObject(result, Bool::False());
813 __ jmp(&done, Assembler::kNearJump);
814 __ Bind(&is_true);
815 __ LoadObject(result, Bool::True());
816 __ Bind(&done);
817 }
818
819
820 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
821 BranchInstr* branch) {
822 BranchLabels labels = compiler->CreateBranchLabels(branch);
823 Condition true_condition = EmitComparisonCode(compiler, labels);
824 EmitBranchOnCondition(compiler, true_condition, labels);
825 }
826
827
828 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, 768 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
829 bool opt) const { 769 bool opt) const {
830 return MakeCallSummary(zone); 770 return MakeCallSummary(zone);
831 } 771 }
832 772
833 773
834 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
835 SetupNative(); 775 SetupNative();
836 Register result = locs()->out(0).reg(); 776 Register result = locs()->out(0).reg();
837 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); 777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
(...skipping 3150 matching lines...) Expand 10 before | Expand all | Expand 10 after
3988 __ AddImmediate(ESP, Immediate(kDoubleSize)); 3928 __ AddImmediate(ESP, Immediate(kDoubleSize));
3989 // Mask off sign bit. 3929 // Mask off sign bit.
3990 __ andl(temp, Immediate(0x7FFFFFFF)); 3930 __ andl(temp, Immediate(0x7FFFFFFF));
3991 // Compare with +infinity. 3931 // Compare with +infinity.
3992 __ cmpl(temp, Immediate(0x7FF00000)); 3932 __ cmpl(temp, Immediate(0x7FF00000));
3993 return is_negated ? NOT_EQUAL : EQUAL; 3933 return is_negated ? NOT_EQUAL : EQUAL;
3994 } 3934 }
3995 } 3935 }
3996 3936
3997 3937
3998 void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
3999 BranchInstr* branch) {
4000 ASSERT(compiler->is_optimizing());
4001 BranchLabels labels = compiler->CreateBranchLabels(branch);
4002 Condition true_condition = EmitComparisonCode(compiler, labels);
4003 EmitBranchOnCondition(compiler, true_condition, labels);
4004 }
4005
4006
4007 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4008 Label is_true, is_false;
4009 BranchLabels labels = {&is_true, &is_false, &is_false};
4010 Condition true_condition = EmitComparisonCode(compiler, labels);
4011 EmitBranchOnCondition(compiler, true_condition, labels);
4012
4013 Register result = locs()->out(0).reg();
4014 Label done;
4015 __ Bind(&is_false);
4016 __ LoadObject(result, Bool::False());
4017 __ jmp(&done);
4018 __ Bind(&is_true);
4019 __ LoadObject(result, Bool::True());
4020 __ Bind(&done);
4021 }
4022
4023
4024 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, 3938 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
4025 bool opt) const { 3939 bool opt) const {
4026 const intptr_t kNumInputs = 2; 3940 const intptr_t kNumInputs = 2;
4027 const intptr_t kNumTemps = 0; 3941 const intptr_t kNumTemps = 0;
4028 LocationSummary* summary = new (zone) 3942 LocationSummary* summary = new (zone)
4029 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4030 summary->set_in(0, Location::RequiresFpuRegister()); 3944 summary->set_in(0, Location::RequiresFpuRegister());
4031 summary->set_in(1, Location::RequiresFpuRegister()); 3945 summary->set_in(1, Location::RequiresFpuRegister());
4032 summary->set_out(0, Location::SameAsFirstInput()); 3946 summary->set_out(0, Location::SameAsFirstInput());
4033 return summary; 3947 return summary;
(...skipping 2676 matching lines...) Expand 10 before | Expand all | Expand 10 after
6710 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); 6624 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_);
6711 } 6625 }
6712 if (kind() != Token::kEQ_STRICT) { 6626 if (kind() != Token::kEQ_STRICT) {
6713 ASSERT(kind() == Token::kNE_STRICT); 6627 ASSERT(kind() == Token::kNE_STRICT);
6714 true_condition = NegateCondition(true_condition); 6628 true_condition = NegateCondition(true_condition);
6715 } 6629 }
6716 return true_condition; 6630 return true_condition;
6717 } 6631 }
6718 6632
6719 6633
6720 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6721 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
6722
6723 Label is_true, is_false;
6724 BranchLabels labels = {&is_true, &is_false, &is_false};
6725 Condition true_condition = EmitComparisonCode(compiler, labels);
6726 EmitBranchOnCondition(compiler, true_condition, labels);
6727
6728 Register result = locs()->out(0).reg();
6729 Label done;
6730 __ Bind(&is_false);
6731 __ LoadObject(result, Bool::False());
6732 __ jmp(&done, Assembler::kNearJump);
6733 __ Bind(&is_true);
6734 __ LoadObject(result, Bool::True());
6735 __ Bind(&done);
6736 }
6737
6738
6739 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
6740 BranchInstr* branch) {
6741 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
6742
6743 BranchLabels labels = compiler->CreateBranchLabels(branch);
6744 Condition true_condition = EmitComparisonCode(compiler, labels);
6745 EmitBranchOnCondition(compiler, true_condition, labels);
6746 }
6747
6748
6749 // Detect pattern when one value is zero and another is a power of 2. 6634 // Detect pattern when one value is zero and another is a power of 2.
6750 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 6635 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
6751 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 6636 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
6752 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 6637 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
6753 } 6638 }
6754 6639
6755 6640
6756 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, 6641 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone,
6757 bool opt) const { 6642 bool opt) const {
6758 comparison()->InitializeLocationSummary(zone, opt); 6643 comparison()->InitializeLocationSummary(zone, opt);
6759 // TODO(vegorov): support byte register constraints in the register allocator. 6644 // TODO(vegorov): support byte register constraints in the register allocator.
6760 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); 6645 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX));
6761 return comparison()->locs(); 6646 return comparison()->locs();
6762 } 6647 }
6763 6648
6764 6649
6765 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6650 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6766 ASSERT(locs()->out(0).reg() == EDX); 6651 ASSERT(locs()->out(0).reg() == EDX);
6767 6652
6768 // Clear upper part of the out register. We are going to use setcc on it 6653 // Clear upper part of the out register. We are going to use setcc on it
6769 // which is a byte move. 6654 // which is a byte move.
6770 __ xorl(EDX, EDX); 6655 __ xorl(EDX, EDX);
6771 6656
6772 // Emit comparison code. This must not overwrite the result register. 6657 // Emit comparison code. This must not overwrite the result register.
6658 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
6659 // the labels or returning an invalid condition.
6773 BranchLabels labels = {NULL, NULL, NULL}; 6660 BranchLabels labels = {NULL, NULL, NULL};
6774 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); 6661 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
6662 ASSERT(true_condition != INVALID_CONDITION);
6775 6663
6776 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); 6664 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
6777 6665
6778 intptr_t true_value = if_true_; 6666 intptr_t true_value = if_true_;
6779 intptr_t false_value = if_false_; 6667 intptr_t false_value = if_false_;
6780 6668
6781 if (is_power_of_two_kind) { 6669 if (is_power_of_two_kind) {
6782 if (true_value == 0) { 6670 if (true_value == 0) {
6783 // We need to have zero in EDX on true_condition. 6671 // We need to have zero in EDX on true_condition.
6784 true_condition = NegateCondition(true_condition); 6672 true_condition = NegateCondition(true_condition);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
6921 __ Drop(1); 6809 __ Drop(1);
6922 __ popl(result); 6810 __ popl(result);
6923 } 6811 }
6924 6812
6925 6813
6926 } // namespace dart 6814 } // namespace dart
6927 6815
6928 #undef __ 6816 #undef __
6929 6817
6930 #endif // defined TARGET_ARCH_IA32 6818 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_dbc.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698