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

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

Issue 62133002: Cleanup of branch code generation (no change in functionality). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased Created 7 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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 case GT: return LE; 120 case GT: return LE;
121 case GE: return LT; 121 case GE: return LT;
122 default: 122 default:
123 OS::Print("Error: Condition not recognized: %d\n", condition); 123 OS::Print("Error: Condition not recognized: %d\n", condition);
124 UNIMPLEMENTED(); 124 UNIMPLEMENTED();
125 return EQ; 125 return EQ;
126 } 126 }
127 } 127 }
128 128
129 129
130 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
131 if (!val->BindsToConstant()) {
132 return false;
133 }
134
135 const Object& bound_constant = val->BoundConstant();
136 if (!bound_constant.IsSmi()) {
137 return false;
138 }
139
140 *smi_value = Smi::Cast(bound_constant).Value();
141 return true;
142 }
143
144
145 // Detect pattern when one value is zero and another is a power of 2. 130 // Detect pattern when one value is zero and another is a power of 2.
146 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 131 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
147 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 132 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
148 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 133 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
149 } 134 }
150 135
151 136
152 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
153 Value* v1,
154 Value* v2) {
155 if (!(comparison->IsStrictCompare() &&
156 !comparison->AsStrictCompare()->needs_number_check()) &&
157 !(comparison->IsEqualityCompare() &&
158 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
159 return false;
160 }
161
162 intptr_t v1_value, v2_value;
163
164 if (!BindsToSmiConstant(v1, &v1_value) ||
165 !BindsToSmiConstant(v2, &v2_value)) {
166 return false;
167 }
168
169 return true;
170 }
171
172
173 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 137 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
174 const intptr_t kNumInputs = 2; 138 const intptr_t kNumInputs = 2;
175 const intptr_t kNumTemps = 0; 139 const intptr_t kNumTemps = 0;
176 LocationSummary* locs = 140 LocationSummary* locs =
177 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 141 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
178 locs->set_in(0, Location::RegisterOrConstant(left())); 142 locs->set_in(0, Location::RegisterOrConstant(left()));
179 locs->set_in(1, Location::RegisterOrConstant(right())); 143 locs->set_in(1, Location::RegisterOrConstant(right()));
180 locs->set_out(Location::RequiresRegister()); 144 locs->set_out(Location::RequiresRegister());
181 return locs; 145 return locs;
182 } 146 }
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 case LE: return GE; 462 case LE: return GE;
499 case GT: return LT; 463 case GT: return LT;
500 case GE: return LE; 464 case GE: return LE;
501 default: 465 default:
502 UNREACHABLE(); 466 UNREACHABLE();
503 return EQ; 467 return EQ;
504 } 468 }
505 } 469 }
506 470
507 471
472 static void EmitBranchOnValue(FlowGraphCompiler* compiler,
473 TargetEntryInstr* true_successor,
474 TargetEntryInstr* false_successor,
475 bool value) {
476 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue");
477 if (value && !compiler->CanFallThroughTo(true_successor)) {
478 __ b(compiler->GetJumpLabel(true_successor));
479 } else if (!value && !compiler->CanFallThroughTo(false_successor)) {
480 __ b(compiler->GetJumpLabel(false_successor));
481 }
482 }
483
484
485 // The comparison result is in CMPRES1.
486 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
487 TargetEntryInstr* true_successor,
488 TargetEntryInstr* false_successor,
489 Condition true_condition) {
490 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition");
491 if (compiler->CanFallThroughTo(false_successor)) {
492 // If the next block is the false successor, fall through to it.
493 Label* label = compiler->GetJumpLabel(true_successor);
494 EmitBranchAfterCompare(compiler, true_condition, label);
495 } else {
496 // If the next block is not the false successor, branch to it.
497 Condition false_condition = NegateCondition(true_condition);
498 Label* label = compiler->GetJumpLabel(false_successor);
499 EmitBranchAfterCompare(compiler, false_condition, label);
500 // Fall through or jump to the true successor.
501 if (!compiler->CanFallThroughTo(true_successor)) {
502 __ b(compiler->GetJumpLabel(true_successor));
503 }
504 }
505 }
506
507
508 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 508 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
509 const LocationSummary& locs, 509 const LocationSummary& locs,
510 Token::Kind kind, 510 Token::Kind kind,
511 BranchInstr* branch) { 511 BranchInstr* branch) {
512 __ TraceSimMsg("EmitSmiComparisonOp"); 512 __ TraceSimMsg("EmitSmiComparisonOp");
513 __ Comment("EmitSmiComparisonOp"); 513 __ Comment("EmitSmiComparisonOp");
514 Location left = locs.in(0); 514 Location left = locs.in(0);
515 Location right = locs.in(1); 515 Location right = locs.in(1);
516 ASSERT(!left.IsConstant() || !right.IsConstant()); 516 ASSERT(!left.IsConstant() || !right.IsConstant());
517 517
518 Condition true_condition = TokenKindToSmiCondition(kind); 518 Condition true_condition = TokenKindToSmiCondition(kind);
519 519
520 if (left.IsConstant()) { 520 if (left.IsConstant()) {
521 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); 521 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant());
522 true_condition = FlipCondition(true_condition); 522 true_condition = FlipCondition(true_condition);
523 } else if (right.IsConstant()) { 523 } else if (right.IsConstant()) {
524 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); 524 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant());
525 } else { 525 } else {
526 __ slt(CMPRES1, left.reg(), right.reg()); 526 __ slt(CMPRES1, left.reg(), right.reg());
527 __ slt(CMPRES2, right.reg(), left.reg()); 527 __ slt(CMPRES2, right.reg(), left.reg());
528 } 528 }
529 529
530 if (branch != NULL) { 530 if (branch != NULL) {
531 branch->EmitBranchOnCondition(compiler, true_condition); 531 EmitBranchOnCondition(compiler,
532 branch->true_successor(),
533 branch->false_successor(),
534 true_condition);
532 } else { 535 } else {
533 Register result = locs.out().reg(); 536 Register result = locs.out().reg();
534 Label done, is_true; 537 Label done, is_true;
535 EmitBranchAfterCompare(compiler, true_condition, &is_true); 538 EmitBranchAfterCompare(compiler, true_condition, &is_true);
536 __ LoadObject(result, Bool::False()); 539 __ LoadObject(result, Bool::False());
537 __ b(&done); 540 __ b(&done);
538 __ Bind(&is_true); 541 __ Bind(&is_true);
539 __ LoadObject(result, Bool::True()); 542 __ LoadObject(result, Bool::True());
540 __ Bind(&done); 543 __ Bind(&done);
541 } 544 }
(...skipping 24 matching lines...) Expand all
566 case Token::kGT: return GT; 569 case Token::kGT: return GT;
567 case Token::kLTE: return LE; 570 case Token::kLTE: return LE;
568 case Token::kGTE: return GE; 571 case Token::kGTE: return GE;
569 default: 572 default:
570 UNREACHABLE(); 573 UNREACHABLE();
571 return VS; 574 return VS;
572 } 575 }
573 } 576 }
574 577
575 578
579 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler,
580 Condition true_condition,
581 FpuRegister left,
582 FpuRegister right,
583 BranchInstr* branch) {
584 ASSERT(branch != NULL);
585 __ Comment("DoubleCompareBranch");
586 __ cund(left, right);
587 BlockEntryInstr* nan_result = (true_condition == NE) ?
588 branch->true_successor() : branch->false_successor();
589 __ bc1t(compiler->GetJumpLabel(nan_result));
590
591 switch (true_condition) {
592 case EQ: __ ceqd(left, right); break;
593 case NE: __ ceqd(left, right); break;
594 case LT: __ coltd(left, right); break;
595 case LE: __ coled(left, right); break;
596 case GT: __ coltd(right, left); break;
597 case GE: __ coled(right, left); break;
598 default: {
599 // Should only passing the above conditions to this function.
600 UNREACHABLE();
601 break;
602 }
603 }
604
605 __ LoadImmediate(TMP, 1);
606 if (true_condition == NE) {
607 __ movf(CMPRES1, ZR);
608 __ movt(CMPRES1, TMP);
609 } else {
610 __ movf(CMPRES1, TMP);
611 __ movt(CMPRES1, ZR);
612 }
613 __ mov(CMPRES2, ZR);
614
615 // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2.
616 EmitBranchOnCondition(compiler,
617 branch->true_successor(),
618 branch->false_successor(),
619 EQ);
620 }
621
622
623 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler,
624 Condition true_condition,
625 FpuRegister left,
626 FpuRegister right,
627 Register result) {
628 Label done, is_true;
629 Label* nan_label = (true_condition == NE) ? &is_true : &done;
630 __ Comment("DoubleCompareBool");
631 __ LoadObject(result, Bool::False());
632 __ cund(left, right);
633 __ bc1t(nan_label);
634
635 switch (true_condition) {
636 case EQ: __ ceqd(left, right); break;
637 case NE: __ ceqd(left, right); break;
638 case LT: __ coltd(left, right); break;
639 case LE: __ coled(left, right); break;
640 case GT: __ coltd(right, left); break;
641 case GE: __ coled(right, left); break;
642 default: {
643 // Should only passing the above conditions to this function.
644 UNREACHABLE();
645 break;
646 }
647 }
648
649 if (true_condition == NE) {
650 __ bc1t(&done); // False is already in result.
651 } else {
652 __ bc1f(&done);
653 }
654 __ Bind(&is_true);
655 __ LoadObject(result, Bool::True());
656 __ Bind(&done);
657 }
658
659
576 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 660 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
577 const LocationSummary& locs, 661 const LocationSummary& locs,
578 Token::Kind kind, 662 Token::Kind kind,
579 BranchInstr* branch) { 663 BranchInstr* branch) {
580 DRegister left = locs.in(0).fpu_reg(); 664 DRegister left = locs.in(0).fpu_reg();
581 DRegister right = locs.in(1).fpu_reg(); 665 DRegister right = locs.in(1).fpu_reg();
582 666
583 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); 667 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right);
584 668
585 Condition true_condition = TokenKindToDoubleCondition(kind); 669 Condition true_condition = TokenKindToDoubleCondition(kind);
586 if (branch != NULL) { 670 if (branch != NULL) {
587 compiler->EmitDoubleCompareBranch( 671 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch);
588 true_condition, left, right, branch);
589 } else { 672 } else {
590 compiler->EmitDoubleCompareBool( 673 EmitDoubleCompareBool(compiler, true_condition,
591 true_condition, left, right, locs.out().reg()); 674 left, right, locs.out().reg());
592 } 675 }
593 } 676 }
594 677
595 678
596 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 679 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
597 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 680 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
598 BranchInstr* kNoBranch = NULL; 681 BranchInstr* kNoBranch = NULL;
599 __ Comment("EqualityCompareInstr"); 682 __ Comment("EqualityCompareInstr");
600 if (operation_cid() == kSmiCid) { 683 if (operation_cid() == kSmiCid) {
601 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); 684 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 Location right = locs()->in(1); 744 Location right = locs()->in(1);
662 if (right.IsConstant()) { 745 if (right.IsConstant()) {
663 ASSERT(right.constant().IsSmi()); 746 ASSERT(right.constant().IsSmi());
664 const int32_t imm = 747 const int32_t imm =
665 reinterpret_cast<int32_t>(right.constant().raw()); 748 reinterpret_cast<int32_t>(right.constant().raw());
666 __ AndImmediate(CMPRES1, left, imm); 749 __ AndImmediate(CMPRES1, left, imm);
667 } else { 750 } else {
668 __ and_(CMPRES1, left, right.reg()); 751 __ and_(CMPRES1, left, right.reg());
669 } 752 }
670 __ mov(CMPRES2, ZR); 753 __ mov(CMPRES2, ZR);
671 branch->EmitBranchOnCondition(compiler, branch_condition); 754 EmitBranchOnCondition(compiler,
755 branch->true_successor(),
756 branch->false_successor(),
757 branch_condition);
672 } 758 }
673 759
674 760
675 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 761 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
676 const intptr_t kNumInputs = 2; 762 const intptr_t kNumInputs = 2;
677 const intptr_t kNumTemps = 0; 763 const intptr_t kNumTemps = 0;
678 if (operation_cid() == kMintCid) { 764 if (operation_cid() == kMintCid) {
679 const intptr_t kNumTemps = 2; 765 const intptr_t kNumTemps = 2;
680 LocationSummary* locs = 766 LocationSummary* locs =
681 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 767 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 3021 matching lines...) Expand 10 before | Expand all | Expand 10 after
3703 } 3789 }
3704 3790
3705 // We can fall through if the successor is the next block in the list. 3791 // We can fall through if the successor is the next block in the list.
3706 // Otherwise, we need a jump. 3792 // Otherwise, we need a jump.
3707 if (!compiler->CanFallThroughTo(successor())) { 3793 if (!compiler->CanFallThroughTo(successor())) {
3708 __ b(compiler->GetJumpLabel(successor())); 3794 __ b(compiler->GetJumpLabel(successor()));
3709 } 3795 }
3710 } 3796 }
3711 3797
3712 3798
3713 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
3714 bool value) {
3715 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue");
3716 if (value && !compiler->CanFallThroughTo(true_successor())) {
3717 __ b(compiler->GetJumpLabel(true_successor()));
3718 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
3719 __ b(compiler->GetJumpLabel(false_successor()));
3720 }
3721 }
3722
3723
3724 // The comparison result is in CMPRES1.
3725 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
3726 Condition true_condition) {
3727 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition");
3728 if (compiler->CanFallThroughTo(false_successor())) {
3729 // If the next block is the false successor, fall through to it.
3730 Label* label = compiler->GetJumpLabel(true_successor());
3731 EmitBranchAfterCompare(compiler, true_condition, label);
3732 } else {
3733 // If the next block is not the false successor, branch to it.
3734 Condition false_condition = NegateCondition(true_condition);
3735 Label* label = compiler->GetJumpLabel(false_successor());
3736 EmitBranchAfterCompare(compiler, false_condition, label);
3737 // Fall through or jump to the true successor.
3738 if (!compiler->CanFallThroughTo(true_successor())) {
3739 __ b(compiler->GetJumpLabel(true_successor()));
3740 }
3741 }
3742 }
3743
3744
3745 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 3799 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
3746 return LocationSummary::Make(0, 3800 return LocationSummary::Make(0,
3747 Location::RequiresRegister(), 3801 Location::RequiresRegister(),
3748 LocationSummary::kNoCall); 3802 LocationSummary::kNoCall);
3749 } 3803 }
3750 3804
3751 3805
3752 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3806 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3753 __ mov(locs()->out().reg(), CTX); 3807 __ mov(locs()->out().reg(), CTX);
3754 } 3808 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3818 BranchInstr* branch) { 3872 BranchInstr* branch) {
3819 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode"); 3873 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode");
3820 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 3874 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
3821 Location left = locs()->in(0); 3875 Location left = locs()->in(0);
3822 Location right = locs()->in(1); 3876 Location right = locs()->in(1);
3823 if (left.IsConstant() && right.IsConstant()) { 3877 if (left.IsConstant() && right.IsConstant()) {
3824 // TODO(vegorov): should be eliminated earlier by constant propagation. 3878 // TODO(vegorov): should be eliminated earlier by constant propagation.
3825 const bool result = (kind() == Token::kEQ_STRICT) ? 3879 const bool result = (kind() == Token::kEQ_STRICT) ?
3826 left.constant().raw() == right.constant().raw() : 3880 left.constant().raw() == right.constant().raw() :
3827 left.constant().raw() != right.constant().raw(); 3881 left.constant().raw() != right.constant().raw();
3828 branch->EmitBranchOnValue(compiler, result); 3882 EmitBranchOnValue(compiler,
3883 branch->true_successor(),
3884 branch->false_successor(),
3885 result);
3829 return; 3886 return;
3830 } 3887 }
3831 if (left.IsConstant()) { 3888 if (left.IsConstant()) {
3832 compiler->EmitEqualityRegConstCompare(right.reg(), 3889 compiler->EmitEqualityRegConstCompare(right.reg(),
3833 left.constant(), 3890 left.constant(),
3834 needs_number_check(), 3891 needs_number_check(),
3835 token_pos()); 3892 token_pos());
3836 } else if (right.IsConstant()) { 3893 } else if (right.IsConstant()) {
3837 compiler->EmitEqualityRegConstCompare(left.reg(), 3894 compiler->EmitEqualityRegConstCompare(left.reg(),
3838 right.constant(), 3895 right.constant(),
3839 needs_number_check(), 3896 needs_number_check(),
3840 token_pos()); 3897 token_pos());
3841 } else { 3898 } else {
3842 compiler->EmitEqualityRegRegCompare(left.reg(), 3899 compiler->EmitEqualityRegRegCompare(left.reg(),
3843 right.reg(), 3900 right.reg(),
3844 needs_number_check(), 3901 needs_number_check(),
3845 token_pos()); 3902 token_pos());
3846 } 3903 }
3847 3904
3848 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; 3905 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
3849 branch->EmitBranchOnCondition(compiler, true_condition); 3906 EmitBranchOnCondition(compiler,
3907 branch->true_successor(),
3908 branch->false_successor(),
3909 true_condition);
3850 } 3910 }
3851 3911
3852 3912
3853 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { 3913 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
3854 return LocationSummary::Make(1, 3914 return LocationSummary::Make(1,
3855 Location::RequiresRegister(), 3915 Location::RequiresRegister(),
3856 LocationSummary::kNoCall); 3916 LocationSummary::kNoCall);
3857 } 3917 }
3858 3918
3859 3919
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3927 compiler->GenerateCall(token_pos(), 3987 compiler->GenerateCall(token_pos(),
3928 &label, 3988 &label,
3929 PcDescriptors::kOther, 3989 PcDescriptors::kOther,
3930 locs()); 3990 locs());
3931 __ Drop(2); // Discard type arguments and receiver. 3991 __ Drop(2); // Discard type arguments and receiver.
3932 } 3992 }
3933 3993
3934 } // namespace dart 3994 } // namespace dart
3935 3995
3936 #endif // defined TARGET_ARCH_MIPS 3996 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698