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

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

Issue 817593002: Improve generated MIPS code for conditional expressions and branches by delaying (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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) 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 __ BranchEqual(CMPRES1, Immediate(fp_sp_dist), &stack_ok); 108 __ BranchEqual(CMPRES1, Immediate(fp_sp_dist), &stack_ok);
109 __ break_(0); 109 __ break_(0);
110 110
111 __ Bind(&stack_ok); 111 __ Bind(&stack_ok);
112 #endif 112 #endif
113 __ LeaveDartFrameAndReturn(); 113 __ LeaveDartFrameAndReturn();
114 } 114 }
115 115
116 116
117 static Condition NegateCondition(Condition condition) { 117 static Condition NegateCondition(Condition condition) {
118 switch (condition) { 118 switch (condition.rel_op()) {
119 case EQ: return NE; 119 case AL: condition.set_rel_op(NV); break;
120 case NE: return EQ; 120 case NV: condition.set_rel_op(AL); break;
121 case LT: return GE; 121 case EQ: condition.set_rel_op(NE); break;
122 case LE: return GT; 122 case NE: condition.set_rel_op(EQ); break;
123 case GT: return LE; 123 case LT: condition.set_rel_op(GE); break;
124 case GE: return LT; 124 case LE: condition.set_rel_op(GT); break;
125 case GT: condition.set_rel_op(LE); break;
126 case GE: condition.set_rel_op(LT); break;
127 case ULT: condition.set_rel_op(UGE); break;
128 case ULE: condition.set_rel_op(UGT); break;
129 case UGT: condition.set_rel_op(ULE); break;
130 case UGE: condition.set_rel_op(ULT); break;
125 default: 131 default:
126 UNREACHABLE(); 132 UNREACHABLE();
127 return EQ;
128 } 133 }
129 } 134 return condition;
130
131
132 // Detect pattern when one value is zero and another is a power of 2.
133 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
134 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
135 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
136 } 135 }
137 136
138 137
139 LocationSummary* IfThenElseInstr::MakeLocationSummary(Isolate* isolate, 138 LocationSummary* IfThenElseInstr::MakeLocationSummary(Isolate* isolate,
140 bool opt) const { 139 bool opt) const {
141 comparison()->InitializeLocationSummary(isolate, opt); 140 comparison()->InitializeLocationSummary(isolate, opt);
142 return comparison()->locs(); 141 return comparison()->locs();
143 } 142 }
144 143
145 144
146 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 145 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
147 const Register result = locs()->out(0).reg(); 146 const Register result = locs()->out(0).reg();
148 147
149 Location left = locs()->in(0); 148 intptr_t true_value = if_true_;
150 Location right = locs()->in(1); 149 intptr_t false_value = if_false_;
151 ASSERT(!left.IsConstant() || !right.IsConstant()); 150 bool swapped = false;
151 if (true_value == 0) {
152 // Swap values so that false_value is zero.
153 intptr_t temp = true_value;
154 true_value = false_value;
155 false_value = temp;
156 swapped = true;
157 }
152 158
153 // Clear out register. 159 // Initialize result with the true value.
154 __ mov(result, ZR); 160 __ LoadImmediate(result, Smi::RawValue(true_value));
155 161
156 // Emit comparison code. This must not overwrite the result register. 162 // Emit comparison code. This must not overwrite the result register.
157 BranchLabels labels = { NULL, NULL, NULL }; 163 BranchLabels labels = { NULL, NULL, NULL }; // Emit branch-free code.
158 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); 164 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
159 165 if (swapped) {
160 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); 166 true_condition = NegateCondition(true_condition);
161
162 intptr_t true_value = if_true_;
163 intptr_t false_value = if_false_;
164
165 if (is_power_of_two_kind) {
166 if (true_value == 0) {
167 // We need to have zero in result on true_condition.
168 true_condition = NegateCondition(true_condition);
169 }
170 } else {
171 if (true_value == 0) {
172 // Swap values so that false_value is zero.
173 intptr_t temp = true_value;
174 true_value = false_value;
175 false_value = temp;
176 } else {
177 true_condition = NegateCondition(true_condition);
178 }
179 } 167 }
180 168
181 switch (true_condition) { 169 // Evaluate condition and provide result in CMPRES1.
170 Register left = true_condition.left();
171 Register right = true_condition.right();
172 bool zero_is_false = true; // Zero in CMPRES1 indicates a false condition.
173 switch (true_condition.rel_op()) {
174 case AL: return; // Result holds true_value.
175 case NV: __ LoadImmediate(result, false_value); return;
182 case EQ: 176 case EQ:
183 __ xor_(result, CMPRES1, CMPRES2); 177 zero_is_false = false;
184 __ xori(result, result, Immediate(1)); 178 // fall through.
179 case NE: {
180 if (left == IMM) {
181 __ XorImmediate(CMPRES1, right, true_condition.imm());
182 } else if (right == IMM) {
183 __ XorImmediate(CMPRES1, left, true_condition.imm());
184 } else {
185 __ xor_(CMPRES1, left, right);
186 }
185 break; 187 break;
186 case NE: 188 }
187 __ xor_(result, CMPRES1, CMPRES2); 189 case GE:
190 zero_is_false = false;
191 // fall through.
192 case LT: {
193 if (left == IMM) {
194 __ slti(CMPRES1, right, Immediate(true_condition.imm() + 1));
195 zero_is_false = !zero_is_false;
196 } else if (right == IMM) {
197 __ slti(CMPRES1, left, Immediate(true_condition.imm()));
198 } else {
199 __ slt(CMPRES1, left, right);
200 }
188 break; 201 break;
189 case GT: 202 }
190 __ mov(result, CMPRES2); 203 case LE:
204 zero_is_false = false;
205 // fall through.
206 case GT: {
207 if (left == IMM) {
208 __ slti(CMPRES1, right, Immediate(true_condition.imm()));
209 } else if (right == IMM) {
210 __ slti(CMPRES1, left, Immediate(true_condition.imm() + 1));
211 zero_is_false = !zero_is_false;
212 } else {
213 __ slt(CMPRES1, right, left);
214 }
191 break; 215 break;
192 case GE: 216 }
193 __ xori(result, CMPRES1, Immediate(1)); 217 case UGE:
218 zero_is_false = false;
219 // fall through.
220 case ULT: {
221 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used.
222 __ sltu(CMPRES1, left, right);
194 break; 223 break;
195 case LT: 224 }
196 __ mov(result, CMPRES1); 225 case ULE:
226 zero_is_false = false;
227 // fall through.
228 case UGT: {
229 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used.
230 __ sltu(CMPRES1, right, left);
197 break; 231 break;
198 case LE: 232 }
199 __ xori(result, CMPRES2, Immediate(1));
200 break;
201 default: 233 default:
202 UNREACHABLE(); 234 UNREACHABLE();
203 break;
204 } 235 }
205 236
206 if (is_power_of_two_kind) { 237 // CMPRES1 is the evaluated condition, zero or non-zero, as specified by the
207 const intptr_t shift = 238 // flag zero_is_false.
208 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); 239 Register false_value_reg;
209 __ sll(result, result, shift + kSmiTagSize); 240 if (false_value == 0) {
241 false_value_reg = ZR;
210 } else { 242 } else {
211 __ AddImmediate(result, result, -1); 243 __ LoadImmediate(CMPRES2, Smi::RawValue(false_value));
212 const int32_t val = 244 false_value_reg = CMPRES2;
213 Smi::RawValue(true_value) - Smi::RawValue(false_value); 245 }
214 __ AndImmediate(result, result, val); 246 if (zero_is_false) {
215 if (false_value != 0) { 247 __ movz(result, false_value_reg, CMPRES1);
216 __ AddImmediate(result, result, Smi::RawValue(false_value)); 248 } else {
217 } 249 __ movn(result, false_value_reg, CMPRES1);
218 } 250 }
219 } 251 }
220 252
221 253
222 LocationSummary* ClosureCallInstr::MakeLocationSummary(Isolate* isolate, 254 LocationSummary* ClosureCallInstr::MakeLocationSummary(Isolate* isolate,
223 bool opt) const { 255 bool opt) const {
224 const intptr_t kNumInputs = 1; 256 const intptr_t kNumInputs = 1;
225 const intptr_t kNumTemps = 0; 257 const intptr_t kNumTemps = 0;
226 LocationSummary* summary = new(isolate) LocationSummary( 258 LocationSummary* summary = new(isolate) LocationSummary(
227 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); 259 isolate, kNumInputs, kNumTemps, LocationSummary::kCall);
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 if (value_is_smi == NULL) { 517 if (value_is_smi == NULL) {
486 __ beq(CMPRES1, ZR, &done); 518 __ beq(CMPRES1, ZR, &done);
487 } else { 519 } else {
488 __ beq(CMPRES1, ZR, value_is_smi); 520 __ beq(CMPRES1, ZR, value_is_smi);
489 } 521 }
490 __ LoadClassId(value_cid_reg, value_reg); 522 __ LoadClassId(value_cid_reg, value_reg);
491 __ Bind(&done); 523 __ Bind(&done);
492 } 524 }
493 525
494 526
495 static Condition TokenKindToSmiCondition(Token::Kind kind) { 527 static RelationOperator TokenKindToIntRelOp(Token::Kind kind) {
496 switch (kind) { 528 switch (kind) {
497 case Token::kEQ: return EQ; 529 case Token::kEQ: return EQ;
498 case Token::kNE: return NE; 530 case Token::kNE: return NE;
499 case Token::kLT: return LT; 531 case Token::kLT: return LT;
500 case Token::kGT: return GT; 532 case Token::kGT: return GT;
501 case Token::kLTE: return LE; 533 case Token::kLTE: return LE;
502 case Token::kGTE: return GE; 534 case Token::kGTE: return GE;
503 default: 535 default:
504 UNREACHABLE(); 536 UNREACHABLE();
505 return VS; 537 return NV;
506 } 538 }
507 } 539 }
508 540
509 541
510 // Branches on condition c assuming comparison results in CMPRES1 and CMPRES2. 542 static RelationOperator TokenKindToUintRelOp(Token::Kind kind) {
511 static void EmitBranchAfterCompare( 543 switch (kind) {
512 FlowGraphCompiler* compiler, Condition condition, Label* is_true) { 544 case Token::kEQ: return EQ;
513 switch (condition) { 545 case Token::kNE: return NE;
514 case EQ: __ beq(CMPRES1, CMPRES2, is_true); break; 546 case Token::kLT: return ULT;
515 case NE: __ bne(CMPRES1, CMPRES2, is_true); break; 547 case Token::kGT: return UGT;
516 case GT: __ bne(CMPRES2, ZR, is_true); break; 548 case Token::kLTE: return ULE;
517 case GE: __ beq(CMPRES1, ZR, is_true); break; 549 case Token::kGTE: return UGE;
518 case LT: __ bne(CMPRES1, ZR, is_true); break;
519 case LE: __ beq(CMPRES2, ZR, is_true); break;
520 default: 550 default:
521 UNREACHABLE(); 551 UNREACHABLE();
522 break; 552 return NV;
523 } 553 }
524 } 554 }
525 555
526 556
527 static Condition FlipCondition(Condition condition) { 557 // The comparison code to emit is specified by true_condition.
528 switch (condition) {
529 case EQ: return EQ;
530 case NE: return NE;
531 case LT: return GT;
532 case LE: return GE;
533 case GT: return LT;
534 case GE: return LE;
535 default:
536 UNREACHABLE();
537 return EQ;
538 }
539 }
540
541
542 // The comparison result is in CMPRES1/CMPRES2.
543 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, 558 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
544 Condition true_condition, 559 Condition true_condition,
545 BranchLabels labels) { 560 BranchLabels labels) {
546 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition"); 561 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition");
547 if (labels.fall_through == labels.false_label) { 562 if (labels.fall_through == labels.false_label) {
548 // If the next block is the false successor, fall through to it. 563 // If the next block is the false successor, fall through to it.
549 EmitBranchAfterCompare(compiler, true_condition, labels.true_label); 564 __ BranchOnCondition(true_condition, labels.true_label);
550 } else { 565 } else {
551 // If the next block is not the false successor, branch to it. 566 // If the next block is not the false successor, branch to it.
552 Condition false_condition = NegateCondition(true_condition); 567 Condition false_condition = NegateCondition(true_condition);
553 EmitBranchAfterCompare(compiler, false_condition, labels.false_label); 568 __ BranchOnCondition(false_condition, labels.false_label);
554 // Fall through or jump to the true successor. 569 // Fall through or jump to the true successor.
555 if (labels.fall_through != labels.true_label) { 570 if (labels.fall_through != labels.true_label) {
556 __ b(labels.true_label); 571 __ b(labels.true_label);
557 } 572 }
558 } 573 }
559 } 574 }
560 575
561 576
562 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, 577 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
563 const LocationSummary& locs, 578 const LocationSummary& locs,
564 Token::Kind kind) { 579 Token::Kind kind) {
565 __ TraceSimMsg("EmitSmiComparisonOp"); 580 __ TraceSimMsg("EmitSmiComparisonOp");
566 __ Comment("EmitSmiComparisonOp"); 581 __ Comment("EmitSmiComparisonOp");
567 Location left = locs.in(0); 582 Location left = locs.in(0);
568 Location right = locs.in(1); 583 Location right = locs.in(1);
569 ASSERT(!left.IsConstant() || !right.IsConstant()); 584 ASSERT(!left.IsConstant() || !right.IsConstant());
570 585
571 Condition true_condition = TokenKindToSmiCondition(kind); 586 Register left_reg = CMPRES1;
572 587 Register right_reg = CMPRES2;
573 if (left.IsConstant()) { 588 int16_t imm = 0;
574 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); 589 if (left.IsRegister()) {
575 true_condition = FlipCondition(true_condition); 590 left_reg = left.reg();
576 } else if (right.IsConstant()) {
577 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant());
578 } else { 591 } else {
579 __ slt(CMPRES1, left.reg(), right.reg()); 592 ASSERT(left.IsConstant());
580 __ slt(CMPRES2, right.reg(), left.reg()); 593 if (left.constant().IsSmi()) {
594 int32_t val = reinterpret_cast<int32_t>(left.constant().raw());
595 if (val == 0) {
596 left_reg = ZR;
597 } else if (Condition::IsValidImm(val)) {
598 left_reg = IMM;
599 imm = val;
600 }
601 }
602 if (left_reg == CMPRES1) {
603 __ LoadObject(left_reg, left.constant());
604 }
581 } 605 }
582 return true_condition; 606 if (right.IsRegister()) {
583 } 607 right_reg = right.reg();
584 608 } else {
585 609 ASSERT(right.IsConstant());
586 static Condition TokenKindToMintCondition(Token::Kind kind) { 610 if (right.constant().IsSmi()) {
587 switch (kind) { 611 int32_t val = reinterpret_cast<int32_t>(right.constant().raw());
588 case Token::kEQ: return EQ; 612 if (val == 0) {
589 case Token::kNE: return NE; 613 right_reg = ZR;
590 case Token::kLT: return LT; 614 } else if (Condition::IsValidImm(val)) {
591 case Token::kGT: return GT; 615 right_reg = IMM;
592 case Token::kLTE: return LE; 616 imm = val;
593 case Token::kGTE: return GE; 617 }
594 default: 618 }
595 UNREACHABLE(); 619 if (right_reg == CMPRES2) {
596 return VS; 620 __ LoadObject(right_reg, right.constant());
621 }
597 } 622 }
623 return Condition(left_reg, right_reg, TokenKindToIntRelOp(kind), imm);
598 } 624 }
599 625
600 626
601 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 627 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
602 const LocationSummary& locs, 628 const LocationSummary& locs,
603 Token::Kind kind) { 629 Token::Kind kind,
630 BranchLabels labels) {
604 __ TraceSimMsg("EmitUnboxedMintEqualityOp"); 631 __ TraceSimMsg("EmitUnboxedMintEqualityOp");
605 __ Comment("EmitUnboxedMintEqualityOp"); 632 __ Comment("EmitUnboxedMintEqualityOp");
606 ASSERT(Token::IsEqualityOperator(kind)); 633 ASSERT(Token::IsEqualityOperator(kind));
607 PairLocation* left_pair = locs.in(0).AsPairLocation(); 634 PairLocation* left_pair = locs.in(0).AsPairLocation();
608 Register left_lo = left_pair->At(0).reg(); 635 Register left_lo = left_pair->At(0).reg();
609 Register left_hi = left_pair->At(1).reg(); 636 Register left_hi = left_pair->At(1).reg();
610 PairLocation* right_pair = locs.in(1).AsPairLocation(); 637 PairLocation* right_pair = locs.in(1).AsPairLocation();
611 Register right_lo = right_pair->At(0).reg(); 638 Register right_lo = right_pair->At(0).reg();
612 Register right_hi = right_pair->At(1).reg(); 639 Register right_hi = right_pair->At(1).reg();
613 640
614 __ xor_(CMPRES1, left_lo, right_lo); 641 if (labels.false_label == NULL) {
615 __ xor_(CMPRES2, left_hi, right_hi); 642 // Generate branch-free code.
616 __ or_(CMPRES1, CMPRES1, CMPRES2); 643 __ xor_(CMPRES1, left_lo, right_lo);
617 __ mov(CMPRES2, ZR); 644 __ xor_(AT, left_hi, right_hi);
618 return TokenKindToMintCondition(kind); 645 __ or_(CMPRES1, CMPRES1, AT);
646 return Condition(CMPRES1, ZR, TokenKindToUintRelOp(kind));
647 } else {
648 if (kind == Token::kEQ) {
649 __ bne(left_hi, right_hi, labels.false_label);
650 } else {
651 ASSERT(kind == Token::kNE);
652 __ bne(left_hi, right_hi, labels.true_label);
653 }
654 return Condition(left_lo, right_lo, TokenKindToUintRelOp(kind));
655 }
619 } 656 }
620 657
621 658
622 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 659 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
623 const LocationSummary& locs, 660 const LocationSummary& locs,
624 Token::Kind kind) { 661 Token::Kind kind,
662 BranchLabels labels) {
625 __ TraceSimMsg("EmitUnboxedMintComparisonOp"); 663 __ TraceSimMsg("EmitUnboxedMintComparisonOp");
626 __ Comment("EmitUnboxedMintComparisonOp"); 664 __ Comment("EmitUnboxedMintComparisonOp");
627 PairLocation* left_pair = locs.in(0).AsPairLocation(); 665 PairLocation* left_pair = locs.in(0).AsPairLocation();
628 Register left_lo = left_pair->At(0).reg(); 666 Register left_lo = left_pair->At(0).reg();
629 Register left_hi = left_pair->At(1).reg(); 667 Register left_hi = left_pair->At(1).reg();
630 PairLocation* right_pair = locs.in(1).AsPairLocation(); 668 PairLocation* right_pair = locs.in(1).AsPairLocation();
631 Register right_lo = right_pair->At(0).reg(); 669 Register right_lo = right_pair->At(0).reg();
632 Register right_hi = right_pair->At(1).reg(); 670 Register right_hi = right_pair->At(1).reg();
633 671
634 Label done; 672 if (labels.false_label == NULL) {
635 // Compare upper halves first. 673 // Generate branch-free code (except for skipping the lower words compare).
636 __ slt(CMPRES1, left_hi, right_hi); 674 // Result in CMPRES1, CMPRES2, so that CMPRES1 op CMPRES2 === left op right.
637 __ slt(CMPRES2, right_hi, left_hi); 675 Label done;
638 // If higher words aren't equal, skip comparing lower words. 676 // Compare upper halves first.
639 __ bne(CMPRES1, CMPRES2, &done); 677 __ slt(CMPRES1, right_hi, left_hi);
678 __ slt(CMPRES2, left_hi, right_hi);
679 // If higher words aren't equal, skip comparing lower words.
680 __ bne(CMPRES1, CMPRES2, &done);
640 681
641 __ sltu(CMPRES1, left_lo, right_lo); 682 __ sltu(CMPRES1, right_lo, left_lo);
642 __ sltu(CMPRES2, right_lo, left_lo); 683 __ sltu(CMPRES2, left_lo, right_lo);
643 __ Bind(&done); 684 __ Bind(&done);
644 685 return Condition(CMPRES1, CMPRES2, TokenKindToUintRelOp(kind));
645 return TokenKindToMintCondition(kind); 686 } else {
646 } 687 switch (kind) {
647 688 case Token::kLT:
648 689 case Token::kLTE: {
649 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 690 __ slt(AT, left_hi, right_hi);
650 switch (kind) { 691 __ bne(AT, ZR, labels.true_label);
651 case Token::kEQ: return EQ; 692 __ delay_slot()->slt(AT, right_hi, left_hi);
652 case Token::kNE: return NE; 693 __ bne(AT, ZR, labels.false_label);
653 case Token::kLT: return LT; 694 break;
654 case Token::kGT: return GT; 695 }
655 case Token::kLTE: return LE; 696 case Token::kGT:
656 case Token::kGTE: return GE; 697 case Token::kGTE: {
657 default: 698 __ slt(AT, left_hi, right_hi);
658 UNREACHABLE(); 699 __ bne(AT, ZR, labels.false_label);
659 return VS; 700 __ delay_slot()->slt(AT, right_hi, left_hi);
701 __ bne(AT, ZR, labels.true_label);
702 break;
703 }
704 default:
705 UNREACHABLE();
706 }
707 return Condition(left_lo, right_lo, TokenKindToUintRelOp(kind));
660 } 708 }
661 } 709 }
662 710
663 711
664 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 712 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
665 const LocationSummary& locs, 713 const LocationSummary& locs,
666 Token::Kind kind, 714 Token::Kind kind,
667 BranchLabels labels) { 715 BranchLabels labels) {
668 DRegister left = locs.in(0).fpu_reg(); 716 DRegister left = locs.in(0).fpu_reg();
669 DRegister right = locs.in(1).fpu_reg(); 717 DRegister right = locs.in(1).fpu_reg();
670 718
671 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); 719 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right);
672 720
673 Condition true_condition = TokenKindToDoubleCondition(kind);
674 __ cund(left, right); 721 __ cund(left, right);
675 Label* nan_label = (true_condition == NE) 722 Label* nan_label = (kind == Token::kNE)
676 ? labels.true_label : labels.false_label; 723 ? labels.true_label : labels.false_label;
677 __ bc1t(nan_label); 724 __ bc1t(nan_label);
678 725
679 switch (true_condition) { 726 switch (kind) {
680 case EQ: __ ceqd(left, right); break; 727 case Token::kEQ: __ ceqd(left, right); break;
681 case NE: __ ceqd(left, right); break; 728 case Token::kNE: __ ceqd(left, right); break;
682 case LT: __ coltd(left, right); break; 729 case Token::kLT: __ coltd(left, right); break;
683 case LE: __ coled(left, right); break; 730 case Token::kLTE: __ coled(left, right); break;
684 case GT: __ coltd(right, left); break; 731 case Token::kGT: __ coltd(right, left); break;
685 case GE: __ coled(right, left); break; 732 case Token::kGTE: __ coled(right, left); break;
686 default: { 733 default: {
687 // We should only be passing the above conditions to this function. 734 // We should only be passing the above conditions to this function.
688 UNREACHABLE(); 735 UNREACHABLE();
689 break; 736 break;
690 } 737 }
691 } 738 }
692 739
693 // Ordering is expected to be described by CMPRES1, CMPRES2. 740 if (labels.false_label == NULL) {
694 __ LoadImmediate(TMP, 1); 741 // Generate branch-free code and return result in condition.
695 if (true_condition == NE) { 742 __ LoadImmediate(CMPRES1, 1);
696 __ movf(CMPRES1, ZR); 743 if (kind == Token::kNE) {
697 __ movt(CMPRES1, TMP); 744 __ movf(CMPRES1, ZR);
745 } else {
746 __ movt(CMPRES1, ZR);
747 }
748 return Condition(CMPRES1, ZR, EQ);
698 } else { 749 } else {
699 __ movf(CMPRES1, TMP); 750 if (labels.fall_through == labels.false_label) {
700 __ movt(CMPRES1, ZR); 751 if (kind == Token::kNE) {
752 __ bc1f(labels.true_label);
753 } else {
754 __ bc1t(labels.true_label);
755 }
756 // Since we already branched on true, return the never true condition.
757 return Condition(CMPRES1, CMPRES2, NV);
758 } else {
759 if (kind == Token::kNE) {
760 __ bc1t(labels.false_label);
761 } else {
762 __ bc1f(labels.false_label);
763 }
764 // Since we already branched on false, return the always true condition.
765 return Condition(CMPRES1, CMPRES2, AL);
766 }
701 } 767 }
702 __ mov(CMPRES2, ZR);
703 return EQ;
704 } 768 }
705 769
706 770
707 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 771 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
708 BranchLabels labels) { 772 BranchLabels labels) {
709 if (operation_cid() == kSmiCid) { 773 if (operation_cid() == kSmiCid) {
710 return EmitSmiComparisonOp(compiler, *locs(), kind()); 774 return EmitSmiComparisonOp(compiler, *locs(), kind());
711 } else if (operation_cid() == kMintCid) { 775 } else if (operation_cid() == kMintCid) {
712 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind()); 776 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
713 } else { 777 } else {
714 ASSERT(operation_cid() == kDoubleCid); 778 ASSERT(operation_cid() == kDoubleCid);
715 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 779 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
716 } 780 }
717 } 781 }
718 782
719 783
720 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 784 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
721 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 785 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
722 __ Comment("EqualityCompareInstr"); 786 __ Comment("EqualityCompareInstr");
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 Register left = locs()->in(0).reg(); 832 Register left = locs()->in(0).reg();
769 Location right = locs()->in(1); 833 Location right = locs()->in(1);
770 if (right.IsConstant()) { 834 if (right.IsConstant()) {
771 ASSERT(right.constant().IsSmi()); 835 ASSERT(right.constant().IsSmi());
772 const int32_t imm = 836 const int32_t imm =
773 reinterpret_cast<int32_t>(right.constant().raw()); 837 reinterpret_cast<int32_t>(right.constant().raw());
774 __ AndImmediate(CMPRES1, left, imm); 838 __ AndImmediate(CMPRES1, left, imm);
775 } else { 839 } else {
776 __ and_(CMPRES1, left, right.reg()); 840 __ and_(CMPRES1, left, right.reg());
777 } 841 }
778 __ mov(CMPRES2, ZR); 842 return Condition(CMPRES1, ZR, (kind() == Token::kNE) ? NE : EQ);
779 Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
780 return true_condition;
781 } 843 }
782 844
783 845
784 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 846 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
785 // Never emitted outside of the BranchInstr. 847 // Never emitted outside of the BranchInstr.
786 UNREACHABLE(); 848 UNREACHABLE();
787 } 849 }
788 850
789 851
790 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, 852 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 } 896 }
835 // No match found, deoptimize or false. 897 // No match found, deoptimize or false.
836 if (deopt == NULL) { 898 if (deopt == NULL) {
837 Label* target = result ? labels.false_label : labels.true_label; 899 Label* target = result ? labels.false_label : labels.true_label;
838 if (target != labels.fall_through) { 900 if (target != labels.fall_through) {
839 __ b(target); 901 __ b(target);
840 } 902 }
841 } else { 903 } else {
842 __ b(deopt); 904 __ b(deopt);
843 } 905 }
844 // Dummy result as the last instruction is a jump, any conditional 906 // Dummy result as the last instruction is a jump or fall through.
845 // branch using the result will therefore be skipped. 907 return Condition(CMPRES1, ZR, AL);
846 return EQ;
847 } 908 }
848 909
849 910
850 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, 911 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
851 BranchInstr* branch) { 912 BranchInstr* branch) {
852 BranchLabels labels = compiler->CreateBranchLabels(branch); 913 BranchLabels labels = compiler->CreateBranchLabels(branch);
853 EmitComparisonCode(compiler, labels); 914 EmitComparisonCode(compiler, labels);
854 } 915 }
855 916
856 917
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 summary->set_out(0, Location::RequiresRegister()); 964 summary->set_out(0, Location::RequiresRegister());
904 return summary; 965 return summary;
905 } 966 }
906 967
907 968
908 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 969 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
909 BranchLabels labels) { 970 BranchLabels labels) {
910 if (operation_cid() == kSmiCid) { 971 if (operation_cid() == kSmiCid) {
911 return EmitSmiComparisonOp(compiler, *locs(), kind()); 972 return EmitSmiComparisonOp(compiler, *locs(), kind());
912 } else if (operation_cid() == kMintCid) { 973 } else if (operation_cid() == kMintCid) {
913 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind()); 974 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
914 } else { 975 } else {
915 ASSERT(operation_cid() == kDoubleCid); 976 ASSERT(operation_cid() == kDoubleCid);
916 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 977 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
917 } 978 }
918 } 979 }
919 980
920 981
921 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 982 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
922 __ TraceSimMsg("RelationalOpInstr"); 983 __ TraceSimMsg("RelationalOpInstr");
923 984
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 LocationSummary::kNoCall); 1099 LocationSummary::kNoCall);
1039 } 1100 }
1040 1101
1041 1102
1042 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1103 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1043 __ TraceSimMsg("StringToCharCodeInstr"); 1104 __ TraceSimMsg("StringToCharCodeInstr");
1044 1105
1045 ASSERT(cid_ == kOneByteStringCid); 1106 ASSERT(cid_ == kOneByteStringCid);
1046 Register str = locs()->in(0).reg(); 1107 Register str = locs()->in(0).reg();
1047 Register result = locs()->out(0).reg(); 1108 Register result = locs()->out(0).reg();
1048 Label done, is_one; 1109 ASSERT(str != result);
1110 Label done;
1049 __ lw(result, FieldAddress(str, String::length_offset())); 1111 __ lw(result, FieldAddress(str, String::length_offset()));
1050 __ BranchEqual(result, Immediate(Smi::RawValue(1)), &is_one); 1112 __ BranchNotEqual(result, Immediate(Smi::RawValue(1)), &done);
1051 __ LoadImmediate(result, Smi::RawValue(-1)); 1113 __ delay_slot()->addiu(result, ZR, Immediate(Smi::RawValue(-1)));
1052 __ b(&done);
1053 __ Bind(&is_one);
1054 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); 1114 __ lbu(result, FieldAddress(str, OneByteString::data_offset()));
1055 __ SmiTag(result); 1115 __ SmiTag(result);
1056 __ Bind(&done); 1116 __ Bind(&done);
1057 } 1117 }
1058 1118
1059 1119
1060 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Isolate* isolate, 1120 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Isolate* isolate,
1061 bool opt) const { 1121 bool opt) const {
1062 const intptr_t kNumInputs = 1; 1122 const intptr_t kNumInputs = 1;
1063 const intptr_t kNumTemps = 0; 1123 const intptr_t kNumTemps = 0;
(...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after
2968 ASSERT(shift_count > 0); 3028 ASSERT(shift_count > 0);
2969 __ sra(result, temp, shift_count); 3029 __ sra(result, temp, shift_count);
2970 if (value < 0) { 3030 if (value < 0) {
2971 __ subu(result, ZR, result); 3031 __ subu(result, ZR, result);
2972 } 3032 }
2973 __ SmiTag(result); 3033 __ SmiTag(result);
2974 break; 3034 break;
2975 } 3035 }
2976 case Token::kBIT_AND: { 3036 case Token::kBIT_AND: {
2977 // No overflow check. 3037 // No overflow check.
2978 if (Utils::IsUint(kImmBits, imm)) { 3038 __ AndImmediate(result, left, imm);
2979 __ andi(result, left, Immediate(imm));
2980 } else {
2981 __ LoadImmediate(TMP, imm);
2982 __ and_(result, left, TMP);
2983 }
2984 break; 3039 break;
2985 } 3040 }
2986 case Token::kBIT_OR: { 3041 case Token::kBIT_OR: {
2987 // No overflow check. 3042 // No overflow check.
2988 if (Utils::IsUint(kImmBits, imm)) { 3043 __ OrImmediate(result, left, imm);
2989 __ ori(result, left, Immediate(imm));
2990 } else {
2991 __ LoadImmediate(TMP, imm);
2992 __ or_(result, left, TMP);
2993 }
2994 break; 3044 break;
2995 } 3045 }
2996 case Token::kBIT_XOR: { 3046 case Token::kBIT_XOR: {
2997 // No overflow check. 3047 // No overflow check.
2998 if (Utils::IsUint(kImmBits, imm)) { 3048 __ XorImmediate(result, left, imm);
2999 __ xori(result, left, Immediate(imm));
3000 } else {
3001 __ LoadImmediate(TMP, imm);
3002 __ xor_(result, left, TMP);
3003 }
3004 break; 3049 break;
3005 } 3050 }
3006 case Token::kSHR: { 3051 case Token::kSHR: {
3007 // sarl operation masks the count to 5 bits. 3052 // sarl operation masks the count to 5 bits.
3008 const intptr_t kCountLimit = 0x1F; 3053 const intptr_t kCountLimit = 0x1F;
3009 const intptr_t value = Smi::Cast(constant).Value(); 3054 const intptr_t value = Smi::Cast(constant).Value();
3010 __ TraceSimMsg("kSHR"); 3055 __ TraceSimMsg("kSHR");
3011 __ sra(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); 3056 __ sra(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit));
3012 __ SmiTag(result); 3057 __ SmiTag(result);
3013 break; 3058 break;
(...skipping 2555 matching lines...) Expand 10 before | Expand all | Expand 10 after
5569 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); 5614 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
5570 #if defined(DEBUG) 5615 #if defined(DEBUG)
5571 __ LoadImmediate(S4, kInvalidObjectPointer); 5616 __ LoadImmediate(S4, kInvalidObjectPointer);
5572 __ LoadImmediate(S5, kInvalidObjectPointer); 5617 __ LoadImmediate(S5, kInvalidObjectPointer);
5573 #endif 5618 #endif
5574 } 5619 }
5575 5620
5576 } // namespace dart 5621 } // namespace dart
5577 5622
5578 #endif // defined TARGET_ARCH_MIPS 5623 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698