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

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
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/intrinsifier_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_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 const Location left = locs.in(0);
568 Location right = locs.in(1); 583 const Location right = locs.in(1);
569 ASSERT(!left.IsConstant() || !right.IsConstant()); 584 ASSERT(!left.IsConstant() || !right.IsConstant());
585 ASSERT(left.IsRegister() || left.IsConstant());
586 ASSERT(right.IsRegister() || right.IsConstant());
570 587
571 Condition true_condition = TokenKindToSmiCondition(kind); 588 int16_t imm = 0;
572 589 const Register left_reg = left.IsRegister() ?
573 if (left.IsConstant()) { 590 left.reg() : __ LoadConditionOperand(CMPRES1, left.constant(), &imm);
574 __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); 591 const Register right_reg = right.IsRegister() ?
575 true_condition = FlipCondition(true_condition); 592 right.reg() : __ LoadConditionOperand(CMPRES2, right.constant(), &imm);
576 } else if (right.IsConstant()) { 593 return Condition(left_reg, right_reg, TokenKindToIntRelOp(kind), imm);
577 __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant());
578 } else {
579 __ slt(CMPRES1, left.reg(), right.reg());
580 __ slt(CMPRES2, right.reg(), left.reg());
581 }
582 return true_condition;
583 }
584
585
586 static Condition TokenKindToMintCondition(Token::Kind kind) {
587 switch (kind) {
588 case Token::kEQ: return EQ;
589 case Token::kNE: return NE;
590 case Token::kLT: return LT;
591 case Token::kGT: return GT;
592 case Token::kLTE: return LE;
593 case Token::kGTE: return GE;
594 default:
595 UNREACHABLE();
596 return VS;
597 }
598 } 594 }
599 595
600 596
601 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 597 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
602 const LocationSummary& locs, 598 const LocationSummary& locs,
603 Token::Kind kind) { 599 Token::Kind kind,
600 BranchLabels labels) {
604 __ TraceSimMsg("EmitUnboxedMintEqualityOp"); 601 __ TraceSimMsg("EmitUnboxedMintEqualityOp");
605 __ Comment("EmitUnboxedMintEqualityOp"); 602 __ Comment("EmitUnboxedMintEqualityOp");
606 ASSERT(Token::IsEqualityOperator(kind)); 603 ASSERT(Token::IsEqualityOperator(kind));
607 PairLocation* left_pair = locs.in(0).AsPairLocation(); 604 PairLocation* left_pair = locs.in(0).AsPairLocation();
608 Register left_lo = left_pair->At(0).reg(); 605 Register left_lo = left_pair->At(0).reg();
609 Register left_hi = left_pair->At(1).reg(); 606 Register left_hi = left_pair->At(1).reg();
610 PairLocation* right_pair = locs.in(1).AsPairLocation(); 607 PairLocation* right_pair = locs.in(1).AsPairLocation();
611 Register right_lo = right_pair->At(0).reg(); 608 Register right_lo = right_pair->At(0).reg();
612 Register right_hi = right_pair->At(1).reg(); 609 Register right_hi = right_pair->At(1).reg();
613 610
614 __ xor_(CMPRES1, left_lo, right_lo); 611 if (labels.false_label == NULL) {
615 __ xor_(CMPRES2, left_hi, right_hi); 612 // Generate branch-free code.
616 __ or_(CMPRES1, CMPRES1, CMPRES2); 613 __ xor_(CMPRES1, left_lo, right_lo);
617 __ mov(CMPRES2, ZR); 614 __ xor_(AT, left_hi, right_hi);
618 return TokenKindToMintCondition(kind); 615 __ or_(CMPRES1, CMPRES1, AT);
616 return Condition(CMPRES1, ZR, TokenKindToUintRelOp(kind));
617 } else {
618 if (kind == Token::kEQ) {
619 __ bne(left_hi, right_hi, labels.false_label);
620 } else {
621 ASSERT(kind == Token::kNE);
622 __ bne(left_hi, right_hi, labels.true_label);
623 }
624 return Condition(left_lo, right_lo, TokenKindToUintRelOp(kind));
625 }
619 } 626 }
620 627
621 628
622 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 629 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
623 const LocationSummary& locs, 630 const LocationSummary& locs,
624 Token::Kind kind) { 631 Token::Kind kind,
632 BranchLabels labels) {
625 __ TraceSimMsg("EmitUnboxedMintComparisonOp"); 633 __ TraceSimMsg("EmitUnboxedMintComparisonOp");
626 __ Comment("EmitUnboxedMintComparisonOp"); 634 __ Comment("EmitUnboxedMintComparisonOp");
627 PairLocation* left_pair = locs.in(0).AsPairLocation(); 635 PairLocation* left_pair = locs.in(0).AsPairLocation();
628 Register left_lo = left_pair->At(0).reg(); 636 Register left_lo = left_pair->At(0).reg();
629 Register left_hi = left_pair->At(1).reg(); 637 Register left_hi = left_pair->At(1).reg();
630 PairLocation* right_pair = locs.in(1).AsPairLocation(); 638 PairLocation* right_pair = locs.in(1).AsPairLocation();
631 Register right_lo = right_pair->At(0).reg(); 639 Register right_lo = right_pair->At(0).reg();
632 Register right_hi = right_pair->At(1).reg(); 640 Register right_hi = right_pair->At(1).reg();
633 641
634 Label done; 642 if (labels.false_label == NULL) {
635 // Compare upper halves first. 643 // Generate branch-free code (except for skipping the lower words compare).
636 __ slt(CMPRES1, left_hi, right_hi); 644 // Result in CMPRES1, CMPRES2, so that CMPRES1 op CMPRES2 === left op right.
637 __ slt(CMPRES2, right_hi, left_hi); 645 Label done;
638 // If higher words aren't equal, skip comparing lower words. 646 // Compare upper halves first.
639 __ bne(CMPRES1, CMPRES2, &done); 647 __ slt(CMPRES1, right_hi, left_hi);
648 __ slt(CMPRES2, left_hi, right_hi);
649 // If higher words aren't equal, skip comparing lower words.
650 __ bne(CMPRES1, CMPRES2, &done);
640 651
641 __ sltu(CMPRES1, left_lo, right_lo); 652 __ sltu(CMPRES1, right_lo, left_lo);
642 __ sltu(CMPRES2, right_lo, left_lo); 653 __ sltu(CMPRES2, left_lo, right_lo);
643 __ Bind(&done); 654 __ Bind(&done);
644 655 return Condition(CMPRES1, CMPRES2, TokenKindToUintRelOp(kind));
645 return TokenKindToMintCondition(kind); 656 } else {
646 } 657 switch (kind) {
647 658 case Token::kLT:
648 659 case Token::kLTE: {
649 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 660 __ slt(AT, left_hi, right_hi);
650 switch (kind) { 661 __ bne(AT, ZR, labels.true_label);
651 case Token::kEQ: return EQ; 662 __ delay_slot()->slt(AT, right_hi, left_hi);
652 case Token::kNE: return NE; 663 __ bne(AT, ZR, labels.false_label);
653 case Token::kLT: return LT; 664 break;
654 case Token::kGT: return GT; 665 }
655 case Token::kLTE: return LE; 666 case Token::kGT:
656 case Token::kGTE: return GE; 667 case Token::kGTE: {
657 default: 668 __ slt(AT, left_hi, right_hi);
658 UNREACHABLE(); 669 __ bne(AT, ZR, labels.false_label);
659 return VS; 670 __ delay_slot()->slt(AT, right_hi, left_hi);
671 __ bne(AT, ZR, labels.true_label);
672 break;
673 }
674 default:
675 UNREACHABLE();
676 }
677 return Condition(left_lo, right_lo, TokenKindToUintRelOp(kind));
660 } 678 }
661 } 679 }
662 680
663 681
664 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 682 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
665 const LocationSummary& locs, 683 const LocationSummary& locs,
666 Token::Kind kind, 684 Token::Kind kind,
667 BranchLabels labels) { 685 BranchLabels labels) {
668 DRegister left = locs.in(0).fpu_reg(); 686 DRegister left = locs.in(0).fpu_reg();
669 DRegister right = locs.in(1).fpu_reg(); 687 DRegister right = locs.in(1).fpu_reg();
670 688
671 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); 689 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right);
672 690
673 Condition true_condition = TokenKindToDoubleCondition(kind);
674 __ cund(left, right); 691 __ cund(left, right);
675 Label* nan_label = (true_condition == NE) 692 Label* nan_label = (kind == Token::kNE)
676 ? labels.true_label : labels.false_label; 693 ? labels.true_label : labels.false_label;
677 __ bc1t(nan_label); 694 __ bc1t(nan_label);
678 695
679 switch (true_condition) { 696 switch (kind) {
680 case EQ: __ ceqd(left, right); break; 697 case Token::kEQ: __ ceqd(left, right); break;
681 case NE: __ ceqd(left, right); break; 698 case Token::kNE: __ ceqd(left, right); break;
682 case LT: __ coltd(left, right); break; 699 case Token::kLT: __ coltd(left, right); break;
683 case LE: __ coled(left, right); break; 700 case Token::kLTE: __ coled(left, right); break;
684 case GT: __ coltd(right, left); break; 701 case Token::kGT: __ coltd(right, left); break;
685 case GE: __ coled(right, left); break; 702 case Token::kGTE: __ coled(right, left); break;
686 default: { 703 default: {
687 // We should only be passing the above conditions to this function. 704 // We should only be passing the above conditions to this function.
688 UNREACHABLE(); 705 UNREACHABLE();
689 break; 706 break;
690 } 707 }
691 } 708 }
692 709
693 // Ordering is expected to be described by CMPRES1, CMPRES2. 710 if (labels.false_label == NULL) {
694 __ LoadImmediate(TMP, 1); 711 // Generate branch-free code and return result in condition.
695 if (true_condition == NE) { 712 __ LoadImmediate(CMPRES1, 1);
696 __ movf(CMPRES1, ZR); 713 if (kind == Token::kNE) {
697 __ movt(CMPRES1, TMP); 714 __ movf(CMPRES1, ZR);
715 } else {
716 __ movt(CMPRES1, ZR);
717 }
718 return Condition(CMPRES1, ZR, EQ);
698 } else { 719 } else {
699 __ movf(CMPRES1, TMP); 720 if (labels.fall_through == labels.false_label) {
700 __ movt(CMPRES1, ZR); 721 if (kind == Token::kNE) {
722 __ bc1f(labels.true_label);
723 } else {
724 __ bc1t(labels.true_label);
725 }
726 // Since we already branched on true, return the never true condition.
727 return Condition(CMPRES1, CMPRES2, NV);
728 } else {
729 if (kind == Token::kNE) {
730 __ bc1t(labels.false_label);
731 } else {
732 __ bc1f(labels.false_label);
733 }
734 // Since we already branched on false, return the always true condition.
735 return Condition(CMPRES1, CMPRES2, AL);
736 }
701 } 737 }
702 __ mov(CMPRES2, ZR);
703 return EQ;
704 } 738 }
705 739
706 740
707 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 741 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
708 BranchLabels labels) { 742 BranchLabels labels) {
709 if (operation_cid() == kSmiCid) { 743 if (operation_cid() == kSmiCid) {
710 return EmitSmiComparisonOp(compiler, *locs(), kind()); 744 return EmitSmiComparisonOp(compiler, *locs(), kind());
711 } else if (operation_cid() == kMintCid) { 745 } else if (operation_cid() == kMintCid) {
712 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind()); 746 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
713 } else { 747 } else {
714 ASSERT(operation_cid() == kDoubleCid); 748 ASSERT(operation_cid() == kDoubleCid);
715 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 749 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
716 } 750 }
717 } 751 }
718 752
719 753
720 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 754 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
721 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 755 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
722 __ Comment("EqualityCompareInstr"); 756 __ Comment("EqualityCompareInstr");
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 Register left = locs()->in(0).reg(); 802 Register left = locs()->in(0).reg();
769 Location right = locs()->in(1); 803 Location right = locs()->in(1);
770 if (right.IsConstant()) { 804 if (right.IsConstant()) {
771 ASSERT(right.constant().IsSmi()); 805 ASSERT(right.constant().IsSmi());
772 const int32_t imm = 806 const int32_t imm =
773 reinterpret_cast<int32_t>(right.constant().raw()); 807 reinterpret_cast<int32_t>(right.constant().raw());
774 __ AndImmediate(CMPRES1, left, imm); 808 __ AndImmediate(CMPRES1, left, imm);
775 } else { 809 } else {
776 __ and_(CMPRES1, left, right.reg()); 810 __ and_(CMPRES1, left, right.reg());
777 } 811 }
778 __ mov(CMPRES2, ZR); 812 return Condition(CMPRES1, ZR, (kind() == Token::kNE) ? NE : EQ);
779 Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
780 return true_condition;
781 } 813 }
782 814
783 815
784 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 816 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
785 // Never emitted outside of the BranchInstr. 817 // Never emitted outside of the BranchInstr.
786 UNREACHABLE(); 818 UNREACHABLE();
787 } 819 }
788 820
789 821
790 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, 822 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 } 866 }
835 // No match found, deoptimize or false. 867 // No match found, deoptimize or false.
836 if (deopt == NULL) { 868 if (deopt == NULL) {
837 Label* target = result ? labels.false_label : labels.true_label; 869 Label* target = result ? labels.false_label : labels.true_label;
838 if (target != labels.fall_through) { 870 if (target != labels.fall_through) {
839 __ b(target); 871 __ b(target);
840 } 872 }
841 } else { 873 } else {
842 __ b(deopt); 874 __ b(deopt);
843 } 875 }
844 // Dummy result as the last instruction is a jump, any conditional 876 // Dummy result as the last instruction is a jump or fall through.
845 // branch using the result will therefore be skipped. 877 return Condition(CMPRES1, ZR, AL);
846 return EQ;
847 } 878 }
848 879
849 880
850 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, 881 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
851 BranchInstr* branch) { 882 BranchInstr* branch) {
852 BranchLabels labels = compiler->CreateBranchLabels(branch); 883 BranchLabels labels = compiler->CreateBranchLabels(branch);
853 EmitComparisonCode(compiler, labels); 884 EmitComparisonCode(compiler, labels);
854 } 885 }
855 886
856 887
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 summary->set_out(0, Location::RequiresRegister()); 934 summary->set_out(0, Location::RequiresRegister());
904 return summary; 935 return summary;
905 } 936 }
906 937
907 938
908 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 939 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
909 BranchLabels labels) { 940 BranchLabels labels) {
910 if (operation_cid() == kSmiCid) { 941 if (operation_cid() == kSmiCid) {
911 return EmitSmiComparisonOp(compiler, *locs(), kind()); 942 return EmitSmiComparisonOp(compiler, *locs(), kind());
912 } else if (operation_cid() == kMintCid) { 943 } else if (operation_cid() == kMintCid) {
913 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind()); 944 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
914 } else { 945 } else {
915 ASSERT(operation_cid() == kDoubleCid); 946 ASSERT(operation_cid() == kDoubleCid);
916 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); 947 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
917 } 948 }
918 } 949 }
919 950
920 951
921 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 952 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
922 __ TraceSimMsg("RelationalOpInstr"); 953 __ TraceSimMsg("RelationalOpInstr");
923 954
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 LocationSummary::kNoCall); 1069 LocationSummary::kNoCall);
1039 } 1070 }
1040 1071
1041 1072
1042 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1073 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1043 __ TraceSimMsg("StringToCharCodeInstr"); 1074 __ TraceSimMsg("StringToCharCodeInstr");
1044 1075
1045 ASSERT(cid_ == kOneByteStringCid); 1076 ASSERT(cid_ == kOneByteStringCid);
1046 Register str = locs()->in(0).reg(); 1077 Register str = locs()->in(0).reg();
1047 Register result = locs()->out(0).reg(); 1078 Register result = locs()->out(0).reg();
1048 Label done, is_one; 1079 ASSERT(str != result);
1080 Label done;
1049 __ lw(result, FieldAddress(str, String::length_offset())); 1081 __ lw(result, FieldAddress(str, String::length_offset()));
1050 __ BranchEqual(result, Immediate(Smi::RawValue(1)), &is_one); 1082 __ BranchNotEqual(result, Immediate(Smi::RawValue(1)), &done);
1051 __ LoadImmediate(result, Smi::RawValue(-1)); 1083 __ delay_slot()->addiu(result, ZR, Immediate(Smi::RawValue(-1)));
1052 __ b(&done);
1053 __ Bind(&is_one);
1054 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); 1084 __ lbu(result, FieldAddress(str, OneByteString::data_offset()));
1055 __ SmiTag(result); 1085 __ SmiTag(result);
1056 __ Bind(&done); 1086 __ Bind(&done);
1057 } 1087 }
1058 1088
1059 1089
1060 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Isolate* isolate, 1090 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Isolate* isolate,
1061 bool opt) const { 1091 bool opt) const {
1062 const intptr_t kNumInputs = 1; 1092 const intptr_t kNumInputs = 1;
1063 const intptr_t kNumTemps = 0; 1093 const intptr_t kNumTemps = 0;
(...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after
2968 ASSERT(shift_count > 0); 2998 ASSERT(shift_count > 0);
2969 __ sra(result, temp, shift_count); 2999 __ sra(result, temp, shift_count);
2970 if (value < 0) { 3000 if (value < 0) {
2971 __ subu(result, ZR, result); 3001 __ subu(result, ZR, result);
2972 } 3002 }
2973 __ SmiTag(result); 3003 __ SmiTag(result);
2974 break; 3004 break;
2975 } 3005 }
2976 case Token::kBIT_AND: { 3006 case Token::kBIT_AND: {
2977 // No overflow check. 3007 // No overflow check.
2978 if (Utils::IsUint(kImmBits, imm)) { 3008 __ AndImmediate(result, left, imm);
2979 __ andi(result, left, Immediate(imm));
2980 } else {
2981 __ LoadImmediate(TMP, imm);
2982 __ and_(result, left, TMP);
2983 }
2984 break; 3009 break;
2985 } 3010 }
2986 case Token::kBIT_OR: { 3011 case Token::kBIT_OR: {
2987 // No overflow check. 3012 // No overflow check.
2988 if (Utils::IsUint(kImmBits, imm)) { 3013 __ OrImmediate(result, left, imm);
2989 __ ori(result, left, Immediate(imm));
2990 } else {
2991 __ LoadImmediate(TMP, imm);
2992 __ or_(result, left, TMP);
2993 }
2994 break; 3014 break;
2995 } 3015 }
2996 case Token::kBIT_XOR: { 3016 case Token::kBIT_XOR: {
2997 // No overflow check. 3017 // No overflow check.
2998 if (Utils::IsUint(kImmBits, imm)) { 3018 __ XorImmediate(result, left, imm);
2999 __ xori(result, left, Immediate(imm));
3000 } else {
3001 __ LoadImmediate(TMP, imm);
3002 __ xor_(result, left, TMP);
3003 }
3004 break; 3019 break;
3005 } 3020 }
3006 case Token::kSHR: { 3021 case Token::kSHR: {
3007 // sarl operation masks the count to 5 bits. 3022 // sarl operation masks the count to 5 bits.
3008 const intptr_t kCountLimit = 0x1F; 3023 const intptr_t kCountLimit = 0x1F;
3009 const intptr_t value = Smi::Cast(constant).Value(); 3024 const intptr_t value = Smi::Cast(constant).Value();
3010 __ TraceSimMsg("kSHR"); 3025 __ TraceSimMsg("kSHR");
3011 __ sra(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); 3026 __ sra(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit));
3012 __ SmiTag(result); 3027 __ SmiTag(result);
3013 break; 3028 break;
(...skipping 2555 matching lines...) Expand 10 before | Expand all | Expand 10 after
5569 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); 5584 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
5570 #if defined(DEBUG) 5585 #if defined(DEBUG)
5571 __ LoadImmediate(S4, kInvalidObjectPointer); 5586 __ LoadImmediate(S4, kInvalidObjectPointer);
5572 __ LoadImmediate(S5, kInvalidObjectPointer); 5587 __ LoadImmediate(S5, kInvalidObjectPointer);
5573 #endif 5588 #endif
5574 } 5589 }
5575 5590
5576 } // namespace dart 5591 } // namespace dart
5577 5592
5578 #endif // defined TARGET_ARCH_MIPS 5593 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698