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

Side by Side Diff: runtime/vm/intermediate_language_arm.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.cc ('k') | runtime/vm/intermediate_language_ia32.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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 case LS: return HI; 121 case LS: return HI;
122 case HI: return LS; 122 case HI: return LS;
123 case CS: return CC; 123 case CS: return CC;
124 default: 124 default:
125 UNREACHABLE(); 125 UNREACHABLE();
126 return EQ; 126 return EQ;
127 } 127 }
128 } 128 }
129 129
130 130
131 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
132 if (!val->BindsToConstant()) {
133 return false;
134 }
135
136 const Object& bound_constant = val->BoundConstant();
137 if (!bound_constant.IsSmi()) {
138 return false;
139 }
140
141 *smi_value = Smi::Cast(bound_constant).Value();
142 return true;
143 }
144
145
146 // Detect pattern when one value is zero and another is a power of 2. 131 // Detect pattern when one value is zero and another is a power of 2.
147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 132 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 133 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
149 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 134 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
150 } 135 }
151 136
152 137
153 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
154 Value* v1,
155 Value* v2) {
156 if (!(comparison->IsStrictCompare() &&
157 !comparison->AsStrictCompare()->needs_number_check()) &&
158 !(comparison->IsEqualityCompare() &&
159 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
160 return false;
161 }
162
163 intptr_t v1_value, v2_value;
164
165 if (!BindsToSmiConstant(v1, &v1_value) ||
166 !BindsToSmiConstant(v2, &v2_value)) {
167 return false;
168 }
169
170 return true;
171 }
172
173
174 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 138 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
175 const intptr_t kNumInputs = 2; 139 const intptr_t kNumInputs = 2;
176 const intptr_t kNumTemps = 0; 140 const intptr_t kNumTemps = 0;
177 LocationSummary* locs = 141 LocationSummary* locs =
178 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 142 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
179 locs->set_in(0, Location::RegisterOrConstant(left())); 143 locs->set_in(0, Location::RegisterOrConstant(left()));
180 locs->set_in(1, Location::RegisterOrConstant(right())); 144 locs->set_in(1, Location::RegisterOrConstant(right()));
181 locs->set_out(Location::RequiresRegister()); 145 locs->set_out(Location::RequiresRegister());
182 return locs; 146 return locs;
183 } 147 }
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 case LS: return CS; 440 case LS: return CS;
477 case HI: return CC; 441 case HI: return CC;
478 case CS: return LS; 442 case CS: return LS;
479 default: 443 default:
480 UNREACHABLE(); 444 UNREACHABLE();
481 return EQ; 445 return EQ;
482 } 446 }
483 } 447 }
484 448
485 449
450 static void EmitBranchOnValue(FlowGraphCompiler* compiler,
451 TargetEntryInstr* true_successor,
452 TargetEntryInstr* false_successor,
453 bool value) {
454 if (value && !compiler->CanFallThroughTo(true_successor)) {
455 __ b(compiler->GetJumpLabel(true_successor));
456 } else if (!value && !compiler->CanFallThroughTo(false_successor)) {
457 __ b(compiler->GetJumpLabel(false_successor));
458 }
459 }
460
461
462 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
463 TargetEntryInstr* true_successor,
464 TargetEntryInstr* false_successor,
465 Condition true_condition) {
466 if (compiler->CanFallThroughTo(false_successor)) {
467 // If the next block is the false successor we will fall through to it.
468 __ b(compiler->GetJumpLabel(true_successor), true_condition);
469 } else {
470 // If the next block is not the false successor we will branch to it.
471 Condition false_condition = NegateCondition(true_condition);
472 __ b(compiler->GetJumpLabel(false_successor), false_condition);
473
474 // Fall through or jump to the true successor.
475 if (!compiler->CanFallThroughTo(true_successor)) {
476 __ b(compiler->GetJumpLabel(true_successor));
477 }
478 }
479 }
480
481
486 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 482 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
487 const LocationSummary& locs, 483 const LocationSummary& locs,
488 Token::Kind kind, 484 Token::Kind kind,
489 BranchInstr* branch) { 485 BranchInstr* branch) {
490 Location left = locs.in(0); 486 Location left = locs.in(0);
491 Location right = locs.in(1); 487 Location right = locs.in(1);
492 ASSERT(!left.IsConstant() || !right.IsConstant()); 488 ASSERT(!left.IsConstant() || !right.IsConstant());
493 489
494 Condition true_condition = TokenKindToSmiCondition(kind); 490 Condition true_condition = TokenKindToSmiCondition(kind);
495 491
496 if (left.IsConstant()) { 492 if (left.IsConstant()) {
497 __ CompareObject(right.reg(), left.constant()); 493 __ CompareObject(right.reg(), left.constant());
498 true_condition = FlipCondition(true_condition); 494 true_condition = FlipCondition(true_condition);
499 } else if (right.IsConstant()) { 495 } else if (right.IsConstant()) {
500 __ CompareObject(left.reg(), right.constant()); 496 __ CompareObject(left.reg(), right.constant());
501 } else { 497 } else {
502 __ cmp(left.reg(), ShifterOperand(right.reg())); 498 __ cmp(left.reg(), ShifterOperand(right.reg()));
503 } 499 }
504 500
505 if (branch != NULL) { 501 if (branch != NULL) {
506 branch->EmitBranchOnCondition(compiler, true_condition); 502 EmitBranchOnCondition(compiler,
503 branch->true_successor(),
504 branch->false_successor(),
505 true_condition);
507 } else { 506 } else {
508 Register result = locs.out().reg(); 507 Register result = locs.out().reg();
509 __ LoadObject(result, Bool::True(), true_condition); 508 __ LoadObject(result, Bool::True(), true_condition);
510 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); 509 __ LoadObject(result, Bool::False(), NegateCondition(true_condition));
511 } 510 }
512 } 511 }
513 512
514 513
515 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 514 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
516 const LocationSummary& locs, 515 const LocationSummary& locs,
(...skipping 19 matching lines...) Expand all
536 case Token::kGT: return GT; 535 case Token::kGT: return GT;
537 case Token::kLTE: return LE; 536 case Token::kLTE: return LE;
538 case Token::kGTE: return GE; 537 case Token::kGTE: return GE;
539 default: 538 default:
540 UNREACHABLE(); 539 UNREACHABLE();
541 return VS; 540 return VS;
542 } 541 }
543 } 542 }
544 543
545 544
545 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler,
546 Condition true_condition,
547 FpuRegister left,
548 FpuRegister right,
549 BranchInstr* branch) {
550 ASSERT(branch != NULL);
551 DRegister dleft = EvenDRegisterOf(left);
552 DRegister dright = EvenDRegisterOf(right);
553 __ vcmpd(dleft, dright);
554 __ vmstat();
555 BlockEntryInstr* nan_result = (true_condition == NE) ?
556 branch->true_successor() : branch->false_successor();
557 __ b(compiler->GetJumpLabel(nan_result), VS);
558 EmitBranchOnCondition(compiler,
559 branch->true_successor(),
560 branch->false_successor(),
561 true_condition);
562 }
563
564
565 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler,
566 Condition true_condition,
567 FpuRegister left,
568 FpuRegister right,
569 Register result) {
570 DRegister dleft = EvenDRegisterOf(left);
571 DRegister dright = EvenDRegisterOf(right);
572 __ vcmpd(dleft, dright);
573 __ vmstat();
574 __ LoadObject(result, Bool::False());
575 Label done;
576 if (true_condition != NE) {
577 __ b(&done, VS); // x == NaN -> false, x != NaN -> true.
578 }
579 __ LoadObject(result, Bool::True(), true_condition);
580 __ Bind(&done);
581 }
582
583
546 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 584 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
547 const LocationSummary& locs, 585 const LocationSummary& locs,
548 Token::Kind kind, 586 Token::Kind kind,
549 BranchInstr* branch) { 587 BranchInstr* branch) {
550 QRegister left = locs.in(0).fpu_reg(); 588 QRegister left = locs.in(0).fpu_reg();
551 QRegister right = locs.in(1).fpu_reg(); 589 QRegister right = locs.in(1).fpu_reg();
552 590
553 Condition true_condition = TokenKindToDoubleCondition(kind); 591 Condition true_condition = TokenKindToDoubleCondition(kind);
554 if (branch != NULL) { 592 if (branch != NULL) {
555 compiler->EmitDoubleCompareBranch( 593 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch);
556 true_condition, left, right, branch);
557 } else { 594 } else {
558 compiler->EmitDoubleCompareBool( 595 EmitDoubleCompareBool(compiler, true_condition,
559 true_condition, left, right, locs.out().reg()); 596 left, right, locs.out().reg());
560 } 597 }
561 } 598 }
562 599
563 600
564 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 601 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
565 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 602 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
566 BranchInstr* kNoBranch = NULL; 603 BranchInstr* kNoBranch = NULL;
567 if (operation_cid() == kSmiCid) { 604 if (operation_cid() == kSmiCid) {
568 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); 605 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
569 return; 606 return;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 Register left = locs()->in(0).reg(); 662 Register left = locs()->in(0).reg();
626 Location right = locs()->in(1); 663 Location right = locs()->in(1);
627 if (right.IsConstant()) { 664 if (right.IsConstant()) {
628 ASSERT(right.constant().IsSmi()); 665 ASSERT(right.constant().IsSmi());
629 const int32_t imm = 666 const int32_t imm =
630 reinterpret_cast<int32_t>(right.constant().raw()); 667 reinterpret_cast<int32_t>(right.constant().raw());
631 __ TestImmediate(left, imm); 668 __ TestImmediate(left, imm);
632 } else { 669 } else {
633 __ tst(left, ShifterOperand(right.reg())); 670 __ tst(left, ShifterOperand(right.reg()));
634 } 671 }
635 branch->EmitBranchOnCondition(compiler, branch_condition); 672 EmitBranchOnCondition(compiler,
673 branch->true_successor(),
674 branch->false_successor(),
675 branch_condition);
636 } 676 }
637 677
638 678
639 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 679 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
640 const intptr_t kNumInputs = 2; 680 const intptr_t kNumInputs = 2;
641 const intptr_t kNumTemps = 0; 681 const intptr_t kNumTemps = 0;
642 if (operation_cid() == kMintCid) { 682 if (operation_cid() == kMintCid) {
643 const intptr_t kNumTemps = 2; 683 const intptr_t kNumTemps = 2;
644 LocationSummary* locs = 684 LocationSummary* locs =
645 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 685 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 3728 matching lines...) Expand 10 before | Expand all | Expand 10 after
4374 } 4414 }
4375 4415
4376 // We can fall through if the successor is the next block in the list. 4416 // We can fall through if the successor is the next block in the list.
4377 // Otherwise, we need a jump. 4417 // Otherwise, we need a jump.
4378 if (!compiler->CanFallThroughTo(successor())) { 4418 if (!compiler->CanFallThroughTo(successor())) {
4379 __ b(compiler->GetJumpLabel(successor())); 4419 __ b(compiler->GetJumpLabel(successor()));
4380 } 4420 }
4381 } 4421 }
4382 4422
4383 4423
4384 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
4385 bool value) {
4386 if (value && !compiler->CanFallThroughTo(true_successor())) {
4387 __ b(compiler->GetJumpLabel(true_successor()));
4388 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
4389 __ b(compiler->GetJumpLabel(false_successor()));
4390 }
4391 }
4392
4393
4394 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
4395 Condition true_condition) {
4396 if (compiler->CanFallThroughTo(false_successor())) {
4397 // If the next block is the false successor we will fall through to it.
4398 __ b(compiler->GetJumpLabel(true_successor()), true_condition);
4399 } else {
4400 // If the next block is not the false successor we will branch to it.
4401 Condition false_condition = NegateCondition(true_condition);
4402 __ b(compiler->GetJumpLabel(false_successor()), false_condition);
4403
4404 // Fall through or jump to the true successor.
4405 if (!compiler->CanFallThroughTo(true_successor())) {
4406 __ b(compiler->GetJumpLabel(true_successor()));
4407 }
4408 }
4409 }
4410
4411
4412 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 4424 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
4413 return LocationSummary::Make(0, 4425 return LocationSummary::Make(0,
4414 Location::RequiresRegister(), 4426 Location::RequiresRegister(),
4415 LocationSummary::kNoCall); 4427 LocationSummary::kNoCall);
4416 } 4428 }
4417 4429
4418 4430
4419 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4431 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4420 __ mov(locs()->out().reg(), ShifterOperand(CTX)); 4432 __ mov(locs()->out().reg(), ShifterOperand(CTX));
4421 } 4433 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
4473 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 4485 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
4474 BranchInstr* branch) { 4486 BranchInstr* branch) {
4475 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4487 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4476 Location left = locs()->in(0); 4488 Location left = locs()->in(0);
4477 Location right = locs()->in(1); 4489 Location right = locs()->in(1);
4478 if (left.IsConstant() && right.IsConstant()) { 4490 if (left.IsConstant() && right.IsConstant()) {
4479 // TODO(vegorov): should be eliminated earlier by constant propagation. 4491 // TODO(vegorov): should be eliminated earlier by constant propagation.
4480 const bool result = (kind() == Token::kEQ_STRICT) ? 4492 const bool result = (kind() == Token::kEQ_STRICT) ?
4481 left.constant().raw() == right.constant().raw() : 4493 left.constant().raw() == right.constant().raw() :
4482 left.constant().raw() != right.constant().raw(); 4494 left.constant().raw() != right.constant().raw();
4483 branch->EmitBranchOnValue(compiler, result); 4495 EmitBranchOnValue(compiler,
4496 branch->true_successor(),
4497 branch->false_successor(),
4498 result);
4484 return; 4499 return;
4485 } 4500 }
4486 if (left.IsConstant()) { 4501 if (left.IsConstant()) {
4487 compiler->EmitEqualityRegConstCompare(right.reg(), 4502 compiler->EmitEqualityRegConstCompare(right.reg(),
4488 left.constant(), 4503 left.constant(),
4489 needs_number_check(), 4504 needs_number_check(),
4490 token_pos()); 4505 token_pos());
4491 } else if (right.IsConstant()) { 4506 } else if (right.IsConstant()) {
4492 compiler->EmitEqualityRegConstCompare(left.reg(), 4507 compiler->EmitEqualityRegConstCompare(left.reg(),
4493 right.constant(), 4508 right.constant(),
4494 needs_number_check(), 4509 needs_number_check(),
4495 token_pos()); 4510 token_pos());
4496 } else { 4511 } else {
4497 compiler->EmitEqualityRegRegCompare(left.reg(), 4512 compiler->EmitEqualityRegRegCompare(left.reg(),
4498 right.reg(), 4513 right.reg(),
4499 needs_number_check(), 4514 needs_number_check(),
4500 token_pos()); 4515 token_pos());
4501 } 4516 }
4502 4517
4503 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; 4518 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
4504 branch->EmitBranchOnCondition(compiler, true_condition); 4519 EmitBranchOnCondition(compiler,
4520 branch->true_successor(),
4521 branch->false_successor(),
4522 true_condition);
4505 } 4523 }
4506 4524
4507 4525
4508 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { 4526 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
4509 return LocationSummary::Make(1, 4527 return LocationSummary::Make(1,
4510 Location::RequiresRegister(), 4528 Location::RequiresRegister(),
4511 LocationSummary::kNoCall); 4529 LocationSummary::kNoCall);
4512 } 4530 }
4513 4531
4514 4532
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
4578 compiler->GenerateCall(token_pos(), 4596 compiler->GenerateCall(token_pos(),
4579 &label, 4597 &label,
4580 PcDescriptors::kOther, 4598 PcDescriptors::kOther,
4581 locs()); 4599 locs());
4582 __ Drop(2); // Discard type arguments and receiver. 4600 __ Drop(2); // Discard type arguments and receiver.
4583 } 4601 }
4584 4602
4585 } // namespace dart 4603 } // namespace dart
4586 4604
4587 #endif // defined TARGET_ARCH_ARM 4605 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698