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

Side by Side Diff: runtime/vm/intermediate_language_x64.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_mips.cc ('k') | no next file » | 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 case BELOW_EQUAL: return ABOVE; 116 case BELOW_EQUAL: return ABOVE;
117 case ABOVE: return BELOW_EQUAL; 117 case ABOVE: return BELOW_EQUAL;
118 case ABOVE_EQUAL: return BELOW; 118 case ABOVE_EQUAL: return BELOW;
119 default: 119 default:
120 UNIMPLEMENTED(); 120 UNIMPLEMENTED();
121 return EQUAL; 121 return EQUAL;
122 } 122 }
123 } 123 }
124 124
125 125
126 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
127 if (!val->BindsToConstant()) {
128 return false;
129 }
130
131 const Object& bound_constant = val->BoundConstant();
132 if (!bound_constant.IsSmi()) {
133 return false;
134 }
135
136 *smi_value = Smi::Cast(bound_constant).Value();
137 return true;
138 }
139
140
141 // Detect pattern when one value is zero and another is a power of 2. 126 // Detect pattern when one value is zero and another is a power of 2.
142 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 127 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
143 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 128 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
144 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 129 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
145 } 130 }
146 131
147 132
148 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
149 Value* v1,
150 Value* v2) {
151 if (!(comparison->IsStrictCompare() &&
152 !comparison->AsStrictCompare()->needs_number_check()) &&
153 !(comparison->IsEqualityCompare() &&
154 (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
155 return false;
156 }
157
158 intptr_t v1_value, v2_value;
159
160 if (!BindsToSmiConstant(v1, &v1_value) ||
161 !BindsToSmiConstant(v2, &v2_value)) {
162 return false;
163 }
164
165 return false;
166 }
167
168
169 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 133 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
170 const intptr_t kNumInputs = 2; 134 const intptr_t kNumInputs = 2;
171 const intptr_t kNumTemps = 0; 135 const intptr_t kNumTemps = 0;
172 LocationSummary* locs = 136 LocationSummary* locs =
173 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 137 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
174 locs->set_in(0, Location::RegisterOrConstant(left())); 138 locs->set_in(0, Location::RegisterOrConstant(left()));
175 locs->set_in(1, Location::RegisterOrConstant(right())); 139 locs->set_in(1, Location::RegisterOrConstant(right()));
176 // TODO(vegorov): support byte register constraints in the register allocator. 140 // TODO(vegorov): support byte register constraints in the register allocator.
177 locs->set_out(Location::RegisterLocation(RDX)); 141 locs->set_out(Location::RegisterLocation(RDX));
178 return locs; 142 return locs;
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 case BELOW_EQUAL: return ABOVE_EQUAL; 402 case BELOW_EQUAL: return ABOVE_EQUAL;
439 case ABOVE: return BELOW; 403 case ABOVE: return BELOW;
440 case ABOVE_EQUAL: return BELOW_EQUAL; 404 case ABOVE_EQUAL: return BELOW_EQUAL;
441 default: 405 default:
442 UNIMPLEMENTED(); 406 UNIMPLEMENTED();
443 return EQUAL; 407 return EQUAL;
444 } 408 }
445 } 409 }
446 410
447 411
412 static void EmitBranchOnValue(FlowGraphCompiler* compiler,
413 TargetEntryInstr* true_successor,
414 TargetEntryInstr* false_successor,
415 bool value) {
416 if (value && !compiler->CanFallThroughTo(true_successor)) {
417 __ jmp(compiler->GetJumpLabel(true_successor));
418 } else if (!value && !compiler->CanFallThroughTo(false_successor)) {
419 __ jmp(compiler->GetJumpLabel(false_successor));
420 }
421 }
422
423
424 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
425 TargetEntryInstr* true_successor,
426 TargetEntryInstr* false_successor,
427 Condition true_condition) {
428 if (compiler->CanFallThroughTo(false_successor)) {
429 // If the next block is the false successor, fall through to it.
430 __ j(true_condition, compiler->GetJumpLabel(true_successor));
431 } else {
432 // If the next block is not the false successor, branch to it.
433 Condition false_condition = NegateCondition(true_condition);
434 __ j(false_condition, compiler->GetJumpLabel(false_successor));
435
436 // Fall through or jump to the true successor.
437 if (!compiler->CanFallThroughTo(true_successor)) {
438 __ jmp(compiler->GetJumpLabel(true_successor));
439 }
440 }
441 }
442
443
448 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 444 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
449 const LocationSummary& locs, 445 const LocationSummary& locs,
450 Token::Kind kind, 446 Token::Kind kind,
451 BranchInstr* branch) { 447 BranchInstr* branch) {
452 Location left = locs.in(0); 448 Location left = locs.in(0);
453 Location right = locs.in(1); 449 Location right = locs.in(1);
454 ASSERT(!left.IsConstant() || !right.IsConstant()); 450 ASSERT(!left.IsConstant() || !right.IsConstant());
455 451
456 Condition true_condition = TokenKindToSmiCondition(kind); 452 Condition true_condition = TokenKindToSmiCondition(kind);
457 453
458 if (left.IsConstant()) { 454 if (left.IsConstant()) {
459 __ CompareObject(right.reg(), left.constant(), PP); 455 __ CompareObject(right.reg(), left.constant(), PP);
460 true_condition = FlipCondition(true_condition); 456 true_condition = FlipCondition(true_condition);
461 } else if (right.IsConstant()) { 457 } else if (right.IsConstant()) {
462 __ CompareObject(left.reg(), right.constant(), PP); 458 __ CompareObject(left.reg(), right.constant(), PP);
463 } else if (right.IsStackSlot()) { 459 } else if (right.IsStackSlot()) {
464 __ cmpq(left.reg(), right.ToStackSlotAddress()); 460 __ cmpq(left.reg(), right.ToStackSlotAddress());
465 } else { 461 } else {
466 __ cmpq(left.reg(), right.reg()); 462 __ cmpq(left.reg(), right.reg());
467 } 463 }
468 464
469 if (branch != NULL) { 465 if (branch != NULL) {
470 branch->EmitBranchOnCondition(compiler, true_condition); 466 EmitBranchOnCondition(compiler,
467 branch->true_successor(),
468 branch->false_successor(),
469 true_condition);
471 } else { 470 } else {
472 Register result = locs.out().reg(); 471 Register result = locs.out().reg();
473 Label done, is_true; 472 Label done, is_true;
474 __ j(true_condition, &is_true); 473 __ j(true_condition, &is_true);
475 __ LoadObject(result, Bool::False(), PP); 474 __ LoadObject(result, Bool::False(), PP);
476 __ jmp(&done); 475 __ jmp(&done);
477 __ Bind(&is_true); 476 __ Bind(&is_true);
478 __ LoadObject(result, Bool::True(), PP); 477 __ LoadObject(result, Bool::True(), PP);
479 __ Bind(&done); 478 __ Bind(&done);
480 } 479 }
481 } 480 }
482 481
483 482
484 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 483 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
485 switch (kind) { 484 switch (kind) {
486 case Token::kEQ: return EQUAL; 485 case Token::kEQ: return EQUAL;
487 case Token::kNE: return NOT_EQUAL; 486 case Token::kNE: return NOT_EQUAL;
488 case Token::kLT: return BELOW; 487 case Token::kLT: return BELOW;
489 case Token::kGT: return ABOVE; 488 case Token::kGT: return ABOVE;
490 case Token::kLTE: return BELOW_EQUAL; 489 case Token::kLTE: return BELOW_EQUAL;
491 case Token::kGTE: return ABOVE_EQUAL; 490 case Token::kGTE: return ABOVE_EQUAL;
492 default: 491 default:
493 UNREACHABLE(); 492 UNREACHABLE();
494 return OVERFLOW; 493 return OVERFLOW;
495 } 494 }
496 } 495 }
497 496
498 497
498 static void EmitDoubleCompareBranch(FlowGraphCompiler* compiler,
499 Condition true_condition,
500 FpuRegister left,
501 FpuRegister right,
502 BranchInstr* branch) {
503 ASSERT(branch != NULL);
504 __ comisd(left, right);
505 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ?
506 branch->true_successor() : branch->false_successor();
507 __ j(PARITY_EVEN, compiler->GetJumpLabel(nan_result));
508 EmitBranchOnCondition(compiler,
509 branch->true_successor(),
510 branch->false_successor(),
511 true_condition);
512 }
513
514
515 static void EmitDoubleCompareBool(FlowGraphCompiler* compiler,
516 Condition true_condition,
517 FpuRegister left,
518 FpuRegister right,
519 Register result) {
520 __ comisd(left, right);
521 Label is_false, is_true, done;
522 // x == NaN -> false, x != NaN -> true.
523 Label* nan_label = (true_condition == NOT_EQUAL) ? &is_true : &is_false;
524 __ j(PARITY_EVEN, nan_label, Assembler::kNearJump);
525 __ j(true_condition, &is_true, Assembler::kNearJump);
526 __ Bind(&is_false);
527 __ LoadObject(result, Bool::False(), PP);
528 __ jmp(&done);
529 __ Bind(&is_true);
530 __ LoadObject(result, Bool::True(), PP);
531 __ Bind(&done);
532 }
533
534
499 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 535 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
500 const LocationSummary& locs, 536 const LocationSummary& locs,
501 Token::Kind kind, 537 Token::Kind kind,
502 BranchInstr* branch) { 538 BranchInstr* branch) {
503 XmmRegister left = locs.in(0).fpu_reg(); 539 XmmRegister left = locs.in(0).fpu_reg();
504 XmmRegister right = locs.in(1).fpu_reg(); 540 XmmRegister right = locs.in(1).fpu_reg();
505 541
506 Condition true_condition = TokenKindToDoubleCondition(kind); 542 Condition true_condition = TokenKindToDoubleCondition(kind);
507 if (branch != NULL) { 543 if (branch != NULL) {
508 compiler->EmitDoubleCompareBranch( 544 EmitDoubleCompareBranch(compiler, true_condition, left, right, branch);
509 true_condition, left, right, branch);
510 } else { 545 } else {
511 compiler->EmitDoubleCompareBool( 546 EmitDoubleCompareBool(compiler, true_condition,
512 true_condition, left, right, locs.out().reg()); 547 left, right, locs.out().reg());
513 } 548 }
514 } 549 }
515 550
516 551
517 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 552 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
518 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); 553 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
519 BranchInstr* kNoBranch = NULL; 554 BranchInstr* kNoBranch = NULL;
520 if (operation_cid() == kSmiCid) { 555 if (operation_cid() == kSmiCid) {
521 // Deoptimizes if both arguments not Smi. 556 // Deoptimizes if both arguments not Smi.
522 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); 557 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 Register left_reg = locs()->in(0).reg(); 608 Register left_reg = locs()->in(0).reg();
574 Location right = locs()->in(1); 609 Location right = locs()->in(1);
575 if (right.IsConstant()) { 610 if (right.IsConstant()) {
576 ASSERT(right.constant().IsSmi()); 611 ASSERT(right.constant().IsSmi());
577 const int64_t imm = 612 const int64_t imm =
578 reinterpret_cast<int64_t>(right.constant().raw()); 613 reinterpret_cast<int64_t>(right.constant().raw());
579 __ TestImmediate(left_reg, Immediate(imm), PP); 614 __ TestImmediate(left_reg, Immediate(imm), PP);
580 } else { 615 } else {
581 __ testq(left_reg, right.reg()); 616 __ testq(left_reg, right.reg());
582 } 617 }
583 branch->EmitBranchOnCondition(compiler, branch_condition); 618 EmitBranchOnCondition(compiler,
619 branch->true_successor(),
620 branch->false_successor(),
621 branch_condition);
584 } 622 }
585 623
586 624
587 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 625 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
588 const intptr_t kNumInputs = 2; 626 const intptr_t kNumInputs = 2;
589 const intptr_t kNumTemps = 0; 627 const intptr_t kNumTemps = 0;
590 if (operation_cid() == kDoubleCid) { 628 if (operation_cid() == kDoubleCid) {
591 LocationSummary* summary = 629 LocationSummary* summary =
592 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 630 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
593 summary->set_in(0, Location::RequiresFpuRegister()); 631 summary->set_in(0, Location::RequiresFpuRegister());
(...skipping 3716 matching lines...) Expand 10 before | Expand all | Expand 10 after
4310 } 4348 }
4311 4349
4312 // We can fall through if the successor is the next block in the list. 4350 // We can fall through if the successor is the next block in the list.
4313 // Otherwise, we need a jump. 4351 // Otherwise, we need a jump.
4314 if (!compiler->CanFallThroughTo(successor())) { 4352 if (!compiler->CanFallThroughTo(successor())) {
4315 __ jmp(compiler->GetJumpLabel(successor())); 4353 __ jmp(compiler->GetJumpLabel(successor()));
4316 } 4354 }
4317 } 4355 }
4318 4356
4319 4357
4320 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
4321 bool value) {
4322 if (value && !compiler->CanFallThroughTo(true_successor())) {
4323 __ jmp(compiler->GetJumpLabel(true_successor()));
4324 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
4325 __ jmp(compiler->GetJumpLabel(false_successor()));
4326 }
4327 }
4328
4329
4330 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
4331 Condition true_condition) {
4332 if (compiler->CanFallThroughTo(false_successor())) {
4333 // If the next block is the false successor, fall through to it.
4334 __ j(true_condition, compiler->GetJumpLabel(true_successor()));
4335 } else {
4336 // If the next block is not the false successor, branch to it.
4337 Condition false_condition = NegateCondition(true_condition);
4338 __ j(false_condition, compiler->GetJumpLabel(false_successor()));
4339
4340 // Fall through or jump to the true successor.
4341 if (!compiler->CanFallThroughTo(true_successor())) {
4342 __ jmp(compiler->GetJumpLabel(true_successor()));
4343 }
4344 }
4345 }
4346
4347
4348 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 4358 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
4349 return LocationSummary::Make(0, 4359 return LocationSummary::Make(0,
4350 Location::RequiresRegister(), 4360 Location::RequiresRegister(),
4351 LocationSummary::kNoCall); 4361 LocationSummary::kNoCall);
4352 } 4362 }
4353 4363
4354 4364
4355 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4365 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4356 __ MoveRegister(locs()->out().reg(), CTX); 4366 __ MoveRegister(locs()->out().reg(), CTX);
4357 } 4367 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
4414 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 4424 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
4415 BranchInstr* branch) { 4425 BranchInstr* branch) {
4416 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4426 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4417 Location left = locs()->in(0); 4427 Location left = locs()->in(0);
4418 Location right = locs()->in(1); 4428 Location right = locs()->in(1);
4419 if (left.IsConstant() && right.IsConstant()) { 4429 if (left.IsConstant() && right.IsConstant()) {
4420 // TODO(vegorov): should be eliminated earlier by constant propagation. 4430 // TODO(vegorov): should be eliminated earlier by constant propagation.
4421 const bool result = (kind() == Token::kEQ_STRICT) ? 4431 const bool result = (kind() == Token::kEQ_STRICT) ?
4422 left.constant().raw() == right.constant().raw() : 4432 left.constant().raw() == right.constant().raw() :
4423 left.constant().raw() != right.constant().raw(); 4433 left.constant().raw() != right.constant().raw();
4424 branch->EmitBranchOnValue(compiler, result); 4434 EmitBranchOnValue(compiler,
4435 branch->true_successor(),
4436 branch->false_successor(),
4437 result);
4425 return; 4438 return;
4426 } 4439 }
4427 if (left.IsConstant()) { 4440 if (left.IsConstant()) {
4428 compiler->EmitEqualityRegConstCompare(right.reg(), 4441 compiler->EmitEqualityRegConstCompare(right.reg(),
4429 left.constant(), 4442 left.constant(),
4430 needs_number_check(), 4443 needs_number_check(),
4431 token_pos()); 4444 token_pos());
4432 } else if (right.IsConstant()) { 4445 } else if (right.IsConstant()) {
4433 compiler->EmitEqualityRegConstCompare(left.reg(), 4446 compiler->EmitEqualityRegConstCompare(left.reg(),
4434 right.constant(), 4447 right.constant(),
4435 needs_number_check(), 4448 needs_number_check(),
4436 token_pos()); 4449 token_pos());
4437 } else { 4450 } else {
4438 compiler->EmitEqualityRegRegCompare(left.reg(), 4451 compiler->EmitEqualityRegRegCompare(left.reg(),
4439 right.reg(), 4452 right.reg(),
4440 needs_number_check(), 4453 needs_number_check(),
4441 token_pos()); 4454 token_pos());
4442 } 4455 }
4443 4456
4444 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 4457 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
4445 branch->EmitBranchOnCondition(compiler, true_condition); 4458 EmitBranchOnCondition(compiler,
4459 branch->true_successor(),
4460 branch->false_successor(),
4461 true_condition);
4446 } 4462 }
4447 4463
4448 4464
4449 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 4465 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
4450 const intptr_t kNumInputs = 0; 4466 const intptr_t kNumInputs = 0;
4451 const intptr_t kNumTemps = 1; 4467 const intptr_t kNumTemps = 1;
4452 LocationSummary* result = 4468 LocationSummary* result =
4453 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 4469 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
4454 result->set_out(Location::RegisterLocation(RAX)); 4470 result->set_out(Location::RegisterLocation(RAX));
4455 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. 4471 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
4554 PcDescriptors::kOther, 4570 PcDescriptors::kOther,
4555 locs()); 4571 locs());
4556 __ Drop(2); // Discard type arguments and receiver. 4572 __ Drop(2); // Discard type arguments and receiver.
4557 } 4573 }
4558 4574
4559 } // namespace dart 4575 } // namespace dart
4560 4576
4561 #undef __ 4577 #undef __
4562 4578
4563 #endif // defined TARGET_ARCH_X64 4579 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698