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

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

Issue 11344011: Relational comparisons for unboxed mints. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: better test coverage Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 __ LoadObject(result, compiler->bool_true()); 638 __ LoadObject(result, compiler->bool_true());
639 __ Bind(&done); 639 __ Bind(&done);
640 } 640 }
641 } 641 }
642 642
643 643
644 static Condition TokenKindToMintCondition(Token::Kind kind) { 644 static Condition TokenKindToMintCondition(Token::Kind kind) {
645 switch (kind) { 645 switch (kind) {
646 case Token::kEQ: return EQUAL; 646 case Token::kEQ: return EQUAL;
647 case Token::kNE: return NOT_EQUAL; 647 case Token::kNE: return NOT_EQUAL;
648 case Token::kLT: return LESS;
649 case Token::kGT: return GREATER;
650 case Token::kLTE: return LESS_EQUAL;
651 case Token::kGTE: return GREATER_EQUAL;
648 default: 652 default:
649 UNIMPLEMENTED(); 653 UNREACHABLE();
650 return OVERFLOW; 654 return OVERFLOW;
651 } 655 }
652 } 656 }
653 657
654 658
655 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 659 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
656 const LocationSummary& locs, 660 const LocationSummary& locs,
657 Token::Kind kind, 661 Token::Kind kind,
658 BranchInstr* branch) { 662 BranchInstr* branch) {
659 ASSERT(Token::IsEqualityOperator(kind)); 663 ASSERT(Token::IsEqualityOperator(kind));
(...skipping 15 matching lines...) Expand all
675 __ j(true_condition, &is_true); 679 __ j(true_condition, &is_true);
676 __ LoadObject(result, compiler->bool_false()); 680 __ LoadObject(result, compiler->bool_false());
677 __ jmp(&done); 681 __ jmp(&done);
678 __ Bind(&is_true); 682 __ Bind(&is_true);
679 __ LoadObject(result, compiler->bool_true()); 683 __ LoadObject(result, compiler->bool_true());
680 __ Bind(&done); 684 __ Bind(&done);
681 } 685 }
682 } 686 }
683 687
684 688
689 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
690 const LocationSummary& locs,
691 Token::Kind kind,
692 BranchInstr* branch) {
srdjan 2012/10/29 19:30:25 Isn't it slower to unbox Mint's for comparison, vs
Florian Schneider 2012/10/30 12:09:04 Yes, in the worst cast where we have two boxed min
693 XmmRegister left = locs.in(0).xmm_reg();
694 XmmRegister right = locs.in(1).xmm_reg();
695 Register left_tmp = locs.temp(0).reg();
696 Register right_tmp = locs.temp(1).reg();
697 Register result = branch == NULL ? locs.out().reg() : kNoRegister;
698
699 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
700 switch (kind) {
701 case Token::kLT:
702 hi_cond = LESS;
703 lo_cond = BELOW;
704 break;
705 case Token::kGT:
706 hi_cond = GREATER;
707 lo_cond = ABOVE;
708 break;
709 case Token::kLTE:
710 hi_cond = LESS;
711 lo_cond = BELOW_EQUAL;
712 break;
713 case Token::kGTE:
714 hi_cond = GREATER;
715 lo_cond = ABOVE_EQUAL;
716 break;
717 default:
718 break;
719 }
720 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW);
721 Label is_true, is_false;
722 // Compare upper halves first.
723 __ pextrd(left_tmp, left, Immediate(1));
724 __ pextrd(right_tmp, right, Immediate(1));
725 __ cmpl(left_tmp, right_tmp);
726 if (branch != NULL) {
727 __ j(hi_cond, compiler->GetBlockLabel(branch->true_successor()));
728 __ j(FlowGraphCompiler::FlipCondition(hi_cond),
729 compiler->GetBlockLabel(branch->false_successor()));
730 } else {
731 __ j(hi_cond, &is_true);
732 __ j(FlowGraphCompiler::FlipCondition(hi_cond), &is_false);
733 }
734
735 // If upper is equal, compare lower half.
736 __ pextrd(left_tmp, left, Immediate(0));
737 __ pextrd(right_tmp, right, Immediate(0));
738 __ cmpl(left_tmp, right_tmp);
739 if (branch != NULL) {
740 branch->EmitBranchOnCondition(compiler, lo_cond);
741 } else {
742 Label done;
743 __ j(lo_cond, &is_true);
744 __ Bind(&is_false);
745 __ LoadObject(result, compiler->bool_false());
746 __ jmp(&done);
747 __ Bind(&is_true);
748 __ LoadObject(result, compiler->bool_true());
749 __ Bind(&done);
750 }
751 }
752
753
685 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 754 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
686 switch (kind) { 755 switch (kind) {
687 case Token::kEQ: return EQUAL; 756 case Token::kEQ: return EQUAL;
688 case Token::kNE: return NOT_EQUAL; 757 case Token::kNE: return NOT_EQUAL;
689 case Token::kLT: return BELOW; 758 case Token::kLT: return BELOW;
690 case Token::kGT: return ABOVE; 759 case Token::kGT: return ABOVE;
691 case Token::kLTE: return BELOW_EQUAL; 760 case Token::kLTE: return BELOW_EQUAL;
692 case Token::kGTE: return ABOVE_EQUAL; 761 case Token::kGTE: return ABOVE_EQUAL;
693 default: 762 default:
694 UNREACHABLE(); 763 UNREACHABLE();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 } 863 }
795 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 864 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
796 __ CompareObject(EAX, compiler->bool_true()); 865 __ CompareObject(EAX, compiler->bool_true());
797 branch->EmitBranchOnCondition(compiler, branch_condition); 866 branch->EmitBranchOnCondition(compiler, branch_condition);
798 } 867 }
799 868
800 869
801 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 870 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
802 const intptr_t kNumInputs = 2; 871 const intptr_t kNumInputs = 2;
803 const intptr_t kNumTemps = 0; 872 const intptr_t kNumTemps = 0;
873 if (operands_class_id() == kMintCid) {
874 const intptr_t kNumTemps = 2;
875 LocationSummary* locs =
876 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
877 locs->set_in(0, Location::RequiresXmmRegister());
878 locs->set_in(1, Location::RequiresXmmRegister());
879 locs->set_temp(0, Location::RequiresRegister());
880 locs->set_temp(1, Location::RequiresRegister());
881 locs->set_out(Location::RequiresRegister());
882 return locs;
883 }
804 if (operands_class_id() == kDoubleCid) { 884 if (operands_class_id() == kDoubleCid) {
805 LocationSummary* summary = 885 LocationSummary* summary =
806 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 886 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
807 summary->set_in(0, Location::RequiresXmmRegister()); 887 summary->set_in(0, Location::RequiresXmmRegister());
808 summary->set_in(1, Location::RequiresXmmRegister()); 888 summary->set_in(1, Location::RequiresXmmRegister());
809 summary->set_out(Location::RequiresRegister()); 889 summary->set_out(Location::RequiresRegister());
810 return summary; 890 return summary;
811 } else if (operands_class_id() == kSmiCid) { 891 } else if (operands_class_id() == kSmiCid) {
812 LocationSummary* summary = 892 LocationSummary* summary =
813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 893 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 10 matching lines...) Expand all
824 locs->set_out(Location::RegisterLocation(EAX)); 904 locs->set_out(Location::RegisterLocation(EAX));
825 return locs; 905 return locs;
826 } 906 }
827 907
828 908
829 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 909 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
830 if (operands_class_id() == kSmiCid) { 910 if (operands_class_id() == kSmiCid) {
831 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); 911 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
832 return; 912 return;
833 } 913 }
914 if (operands_class_id() == kMintCid) {
915 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
916 return;
917 }
834 if (operands_class_id() == kDoubleCid) { 918 if (operands_class_id() == kDoubleCid) {
835 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); 919 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
836 return; 920 return;
837 } 921 }
838 922
839 // Push arguments for the call. 923 // Push arguments for the call.
840 // TODO(fschneider): Split this instruction into different types to avoid 924 // TODO(fschneider): Split this instruction into different types to avoid
841 // explicitly pushing arguments to the call here. 925 // explicitly pushing arguments to the call here.
842 Register left = locs()->in(0).reg(); 926 Register left = locs()->in(0).reg();
843 Register right = locs()->in(1).reg(); 927 Register right = locs()->in(1).reg();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 locs()); 967 locs());
884 } 968 }
885 969
886 970
887 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 971 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
888 BranchInstr* branch) { 972 BranchInstr* branch) {
889 if (operands_class_id() == kSmiCid) { 973 if (operands_class_id() == kSmiCid) {
890 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 974 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
891 return; 975 return;
892 } 976 }
977 if (operands_class_id() == kMintCid) {
978 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
979 return;
980 }
893 if (operands_class_id() == kDoubleCid) { 981 if (operands_class_id() == kDoubleCid) {
894 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); 982 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
895 return; 983 return;
896 } 984 }
897 EmitNativeCode(compiler); 985 EmitNativeCode(compiler);
898 __ CompareObject(EAX, compiler->bool_true()); 986 __ CompareObject(EAX, compiler->bool_true());
899 branch->EmitBranchOnCondition(compiler, EQUAL); 987 branch->EmitBranchOnCondition(compiler, EQUAL);
900 } 988 }
901 989
902 990
(...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after
2437 case Token::kBIT_AND: __ andpd(left, right); break; 2525 case Token::kBIT_AND: __ andpd(left, right); break;
2438 case Token::kBIT_OR: __ orpd(left, right); break; 2526 case Token::kBIT_OR: __ orpd(left, right); break;
2439 case Token::kBIT_XOR: __ xorpd(left, right); break; 2527 case Token::kBIT_XOR: __ xorpd(left, right); break;
2440 case Token::kADD: 2528 case Token::kADD:
2441 case Token::kSUB: { 2529 case Token::kSUB: {
2442 Register lo = locs()->temp(0).reg(); 2530 Register lo = locs()->temp(0).reg();
2443 Register hi = locs()->temp(1).reg(); 2531 Register hi = locs()->temp(1).reg();
2444 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2532 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2445 kDeoptBinaryMintOp); 2533 kDeoptBinaryMintOp);
2446 Label done, overflow; 2534 Label done, overflow;
2447 __ pextrd(lo, right, Immediate(0)); // Lower half left 2535 __ pextrd(lo, right, Immediate(0)); // Lower half
2448 __ pextrd(hi, right, Immediate(1)); // Upper half left 2536 __ pextrd(hi, right, Immediate(1)); // Upper half
2449 __ subl(ESP, Immediate(2 * kWordSize)); 2537 __ subl(ESP, Immediate(2 * kWordSize));
2450 __ movq(Address(ESP, 0), left); 2538 __ movq(Address(ESP, 0), left);
2451 if (op_kind() == Token::kADD) { 2539 if (op_kind() == Token::kADD) {
2452 __ addl(Address(ESP, 0), lo); 2540 __ addl(Address(ESP, 0), lo);
2453 __ adcl(Address(ESP, 1 * kWordSize), hi); 2541 __ adcl(Address(ESP, 1 * kWordSize), hi);
2454 } else { 2542 } else {
2455 __ subl(Address(ESP, 0), lo); 2543 __ subl(Address(ESP, 0), lo);
2456 __ sbbl(Address(ESP, 1 * kWordSize), hi); 2544 __ sbbl(Address(ESP, 1 * kWordSize), hi);
2457 } 2545 }
2458 __ j(OVERFLOW, &overflow); 2546 __ j(OVERFLOW, &overflow);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2558 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 2646 __ pcmpeqq(XMM0, XMM0); // Generate all 1's.
2559 __ pxor(value, XMM0); 2647 __ pxor(value, XMM0);
2560 } 2648 }
2561 2649
2562 2650
2563 } // namespace dart 2651 } // namespace dart
2564 2652
2565 #undef __ 2653 #undef __
2566 2654
2567 #endif // defined TARGET_ARCH_X64 2655 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698