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

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

Issue 78733002: Generalize if-conversion to arbitrary smi comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: 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_arm.cc ('k') | runtime/vm/intermediate_language_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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 __ j(false_condition, labels.false_label); 338 __ j(false_condition, labels.false_label);
339 339
340 // Fall through or jump to the true successor. 340 // Fall through or jump to the true successor.
341 if (labels.fall_through != labels.true_label) { 341 if (labels.fall_through != labels.true_label) {
342 __ jmp(labels.true_label); 342 __ jmp(labels.true_label);
343 } 343 }
344 } 344 }
345 } 345 }
346 346
347 347
348 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 348 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
349 const LocationSummary& locs, 349 const LocationSummary& locs,
350 Token::Kind kind, 350 Token::Kind kind,
351 BranchLabels labels) { 351 BranchLabels labels) {
352 Location left = locs.in(0); 352 Location left = locs.in(0);
353 Location right = locs.in(1); 353 Location right = locs.in(1);
354 ASSERT(!left.IsConstant() || !right.IsConstant()); 354 ASSERT(!left.IsConstant() || !right.IsConstant());
355 355
356 Condition true_condition = TokenKindToSmiCondition(kind); 356 Condition true_condition = TokenKindToSmiCondition(kind);
357 357
358 if (left.IsConstant()) { 358 if (left.IsConstant()) {
359 __ CompareObject(right.reg(), left.constant()); 359 __ CompareObject(right.reg(), left.constant());
360 true_condition = FlipCondition(true_condition); 360 true_condition = FlipCondition(true_condition);
361 } else if (right.IsConstant()) { 361 } else if (right.IsConstant()) {
362 __ CompareObject(left.reg(), right.constant()); 362 __ CompareObject(left.reg(), right.constant());
363 } else if (right.IsStackSlot()) { 363 } else if (right.IsStackSlot()) {
364 __ cmpl(left.reg(), right.ToStackSlotAddress()); 364 __ cmpl(left.reg(), right.ToStackSlotAddress());
365 } else { 365 } else {
366 __ cmpl(left.reg(), right.reg()); 366 __ cmpl(left.reg(), right.reg());
367 } 367 }
368 EmitBranchOnCondition(compiler, true_condition, labels); 368 return true_condition;
369 } 369 }
370 370
371 371
372 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, 372 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
373 Label* overflow, 373 Label* overflow,
374 XmmRegister result, 374 XmmRegister result,
375 Register tmp) { 375 Register tmp) {
376 // Compare upper half. 376 // Compare upper half.
377 Label check_lower, done; 377 Label check_lower, done;
378 __ pextrd(tmp, result, Immediate(1)); 378 __ pextrd(tmp, result, Immediate(1));
(...skipping 24 matching lines...) Expand all
403 case Token::kGT: return GREATER; 403 case Token::kGT: return GREATER;
404 case Token::kLTE: return LESS_EQUAL; 404 case Token::kLTE: return LESS_EQUAL;
405 case Token::kGTE: return GREATER_EQUAL; 405 case Token::kGTE: return GREATER_EQUAL;
406 default: 406 default:
407 UNREACHABLE(); 407 UNREACHABLE();
408 return OVERFLOW; 408 return OVERFLOW;
409 } 409 }
410 } 410 }
411 411
412 412
413 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, 413 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
414 const LocationSummary& locs, 414 const LocationSummary& locs,
415 Token::Kind kind, 415 Token::Kind kind,
416 BranchLabels labels) { 416 BranchLabels labels) {
417 ASSERT(Token::IsEqualityOperator(kind)); 417 ASSERT(Token::IsEqualityOperator(kind));
418 XmmRegister left = locs.in(0).fpu_reg(); 418 XmmRegister left = locs.in(0).fpu_reg();
419 XmmRegister right = locs.in(1).fpu_reg(); 419 XmmRegister right = locs.in(1).fpu_reg();
420 Register temp = locs.temp(0).reg(); 420 Register temp = locs.temp(0).reg();
421 __ movaps(XMM0, left); 421 __ movaps(XMM0, left);
422 __ pcmpeqq(XMM0, right); 422 __ pcmpeqq(XMM0, right);
423 __ movd(temp, XMM0); 423 __ movd(temp, XMM0);
424 424
425 Condition true_condition = TokenKindToMintCondition(kind); 425 Condition true_condition = TokenKindToMintCondition(kind);
426 __ cmpl(temp, Immediate(-1)); 426 __ cmpl(temp, Immediate(-1));
427 EmitBranchOnCondition(compiler, true_condition, labels); 427 return true_condition;
428 } 428 }
429 429
430 430
431 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, 431 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
432 const LocationSummary& locs, 432 const LocationSummary& locs,
433 Token::Kind kind, 433 Token::Kind kind,
434 BranchLabels labels) { 434 BranchLabels labels) {
435 XmmRegister left = locs.in(0).fpu_reg(); 435 XmmRegister left = locs.in(0).fpu_reg();
436 XmmRegister right = locs.in(1).fpu_reg(); 436 XmmRegister right = locs.in(1).fpu_reg();
437 Register left_tmp = locs.temp(0).reg(); 437 Register left_tmp = locs.temp(0).reg();
438 Register right_tmp = locs.temp(1).reg(); 438 Register right_tmp = locs.temp(1).reg();
439 439
440 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; 440 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
441 switch (kind) { 441 switch (kind) {
442 case Token::kLT: 442 case Token::kLT:
443 hi_cond = LESS; 443 hi_cond = LESS;
444 lo_cond = BELOW; 444 lo_cond = BELOW;
(...skipping 19 matching lines...) Expand all
464 __ pextrd(left_tmp, left, Immediate(1)); 464 __ pextrd(left_tmp, left, Immediate(1));
465 __ pextrd(right_tmp, right, Immediate(1)); 465 __ pextrd(right_tmp, right, Immediate(1));
466 __ cmpl(left_tmp, right_tmp); 466 __ cmpl(left_tmp, right_tmp);
467 __ j(hi_cond, labels.true_label); 467 __ j(hi_cond, labels.true_label);
468 __ j(FlipCondition(hi_cond), labels.false_label); 468 __ j(FlipCondition(hi_cond), labels.false_label);
469 469
470 // If upper is equal, compare lower half. 470 // If upper is equal, compare lower half.
471 __ pextrd(left_tmp, left, Immediate(0)); 471 __ pextrd(left_tmp, left, Immediate(0));
472 __ pextrd(right_tmp, right, Immediate(0)); 472 __ pextrd(right_tmp, right, Immediate(0));
473 __ cmpl(left_tmp, right_tmp); 473 __ cmpl(left_tmp, right_tmp);
474 EmitBranchOnCondition(compiler, lo_cond, labels); 474 return lo_cond;
475 } 475 }
476 476
477 477
478 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 478 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
479 switch (kind) { 479 switch (kind) {
480 case Token::kEQ: return EQUAL; 480 case Token::kEQ: return EQUAL;
481 case Token::kNE: return NOT_EQUAL; 481 case Token::kNE: return NOT_EQUAL;
482 case Token::kLT: return BELOW; 482 case Token::kLT: return BELOW;
483 case Token::kGT: return ABOVE; 483 case Token::kGT: return ABOVE;
484 case Token::kLTE: return BELOW_EQUAL; 484 case Token::kLTE: return BELOW_EQUAL;
485 case Token::kGTE: return ABOVE_EQUAL; 485 case Token::kGTE: return ABOVE_EQUAL;
486 default: 486 default:
487 UNREACHABLE(); 487 UNREACHABLE();
488 return OVERFLOW; 488 return OVERFLOW;
489 } 489 }
490 } 490 }
491 491
492 492
493 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 493 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
494 const LocationSummary& locs, 494 const LocationSummary& locs,
495 Token::Kind kind, 495 Token::Kind kind,
496 BranchLabels labels) { 496 BranchLabels labels) {
497 XmmRegister left = locs.in(0).fpu_reg(); 497 XmmRegister left = locs.in(0).fpu_reg();
498 XmmRegister right = locs.in(1).fpu_reg(); 498 XmmRegister right = locs.in(1).fpu_reg();
499 499
500 __ comisd(left, right); 500 __ comisd(left, right);
501 501
502 Condition true_condition = TokenKindToDoubleCondition(kind); 502 Condition true_condition = TokenKindToDoubleCondition(kind);
503 Label* nan_result = (true_condition == NOT_EQUAL) 503 Label* nan_result = (true_condition == NOT_EQUAL)
504 ? labels.true_label : labels.false_label; 504 ? labels.true_label : labels.false_label;
505 __ j(PARITY_EVEN, nan_result); 505 __ j(PARITY_EVEN, nan_result);
506 EmitBranchOnCondition(compiler, true_condition, labels); 506 return true_condition;
507 }
508
509
510 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
511 BranchLabels labels) {
512 if (operation_cid() == kSmiCid) {
513 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
514 } else if (operation_cid() == kMintCid) {
515 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
516 } else {
517 ASSERT(operation_cid() == kDoubleCid);
518 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
519 }
507 } 520 }
508 521
509 522
510 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 523 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
511 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 524 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
512 525
513 Label is_true, is_false; 526 Label is_true, is_false;
514 BranchLabels labels = { &is_true, &is_false, &is_false }; 527 BranchLabels labels = { &is_true, &is_false, &is_false };
528 Condition true_condition = EmitComparisonCode(compiler, labels);
529 EmitBranchOnCondition(compiler, true_condition, labels);
515 530
516 if (operation_cid() == kSmiCid) {
517 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
518 } else if (operation_cid() == kMintCid) {
519 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
520 } else {
521 ASSERT(operation_cid() == kDoubleCid);
522 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
523 }
524 Register result = locs()->out().reg(); 531 Register result = locs()->out().reg();
525 Label done; 532 Label done;
526 __ Bind(&is_false); 533 __ Bind(&is_false);
527 __ LoadObject(result, Bool::False()); 534 __ LoadObject(result, Bool::False());
528 __ jmp(&done, Assembler::kNearJump); 535 __ jmp(&done, Assembler::kNearJump);
529 __ Bind(&is_true); 536 __ Bind(&is_true);
530 __ LoadObject(result, Bool::True()); 537 __ LoadObject(result, Bool::True());
531 __ Bind(&done); 538 __ Bind(&done);
532 } 539 }
533 540
534 541
535 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 542 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
536 BranchInstr* branch) { 543 BranchInstr* branch) {
537 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 544 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
538 545
539 BranchLabels labels = compiler->CreateBranchLabels(branch); 546 BranchLabels labels = compiler->CreateBranchLabels(branch);
540 547 Condition true_condition = EmitComparisonCode(compiler, labels);
541 if (operation_cid() == kSmiCid) { 548 EmitBranchOnCondition(compiler, true_condition, labels);
542 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
543 } else if (operation_cid() == kMintCid) {
544 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
545 } else {
546 ASSERT(operation_cid() == kDoubleCid);
547 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
548 }
549 } 549 }
550 550
551 551
552 LocationSummary* TestSmiInstr::MakeLocationSummary() const { 552 LocationSummary* TestSmiInstr::MakeLocationSummary() const {
553 const intptr_t kNumInputs = 2; 553 const intptr_t kNumInputs = 2;
554 const intptr_t kNumTemps = 0; 554 const intptr_t kNumTemps = 0;
555 LocationSummary* locs = 555 LocationSummary* locs =
556 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 556 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
557 locs->set_in(0, Location::RequiresRegister()); 557 locs->set_in(0, Location::RequiresRegister());
558 // Only one input can be a constant operand. The case of two constant 558 // Only one input can be a constant operand. The case of two constant
559 // operands should be handled by constant propagation. 559 // operands should be handled by constant propagation.
560 locs->set_in(1, Location::RegisterOrConstant(right())); 560 locs->set_in(1, Location::RegisterOrConstant(right()));
561 return locs; 561 return locs;
562 } 562 }
563 563
564 564
565 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 565 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
566 // Never emitted outside of the BranchInstr. 566 BranchLabels labels) {
567 UNREACHABLE();
568 }
569
570
571 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
572 BranchInstr* branch) {
573 BranchLabels labels = compiler->CreateBranchLabels(branch);
574
575 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
576 Register left = locs()->in(0).reg(); 567 Register left = locs()->in(0).reg();
577 Location right = locs()->in(1); 568 Location right = locs()->in(1);
578 if (right.IsConstant()) { 569 if (right.IsConstant()) {
579 ASSERT(right.constant().IsSmi()); 570 ASSERT(right.constant().IsSmi());
580 const int32_t imm = 571 const int32_t imm =
581 reinterpret_cast<int32_t>(right.constant().raw()); 572 reinterpret_cast<int32_t>(right.constant().raw());
582 __ testl(left, Immediate(imm)); 573 __ testl(left, Immediate(imm));
583 } else { 574 } else {
584 __ testl(left, right.reg()); 575 __ testl(left, right.reg());
585 } 576 }
577 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
578 return true_condition;
579 }
580
581
582 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
583 // Never emitted outside of the BranchInstr.
584 UNREACHABLE();
585 }
586
587
588 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
589 BranchInstr* branch) {
590 BranchLabels labels = compiler->CreateBranchLabels(branch);
591 Condition true_condition = EmitComparisonCode(compiler, labels);
586 EmitBranchOnCondition(compiler, true_condition, labels); 592 EmitBranchOnCondition(compiler, true_condition, labels);
587 } 593 }
588 594
589 595
590 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 596 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
591 const intptr_t kNumInputs = 2; 597 const intptr_t kNumInputs = 2;
592 const intptr_t kNumTemps = 0; 598 const intptr_t kNumTemps = 0;
593 if (operation_cid() == kMintCid) { 599 if (operation_cid() == kMintCid) {
594 const intptr_t kNumTemps = 2; 600 const intptr_t kNumTemps = 2;
595 LocationSummary* locs = 601 LocationSummary* locs =
(...skipping 20 matching lines...) Expand all
616 // Only one input can be a constant operand. The case of two constant 622 // Only one input can be a constant operand. The case of two constant
617 // operands should be handled by constant propagation. 623 // operands should be handled by constant propagation.
618 summary->set_in(1, summary->in(0).IsConstant() 624 summary->set_in(1, summary->in(0).IsConstant()
619 ? Location::RequiresRegister() 625 ? Location::RequiresRegister()
620 : Location::RegisterOrConstant(right())); 626 : Location::RegisterOrConstant(right()));
621 summary->set_out(Location::RequiresRegister()); 627 summary->set_out(Location::RequiresRegister());
622 return summary; 628 return summary;
623 } 629 }
624 630
625 631
632 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
633 BranchLabels labels) {
634 if (operation_cid() == kSmiCid) {
635 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
636 } else if (operation_cid() == kMintCid) {
637 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
638 } else {
639 ASSERT(operation_cid() == kDoubleCid);
640 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
641 }
642 }
643
644
626 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 645 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
627 Label is_true, is_false; 646 Label is_true, is_false;
628 BranchLabels labels = { &is_true, &is_false, &is_false }; 647 BranchLabels labels = { &is_true, &is_false, &is_false };
648 Condition true_condition = EmitComparisonCode(compiler, labels);
649 EmitBranchOnCondition(compiler, true_condition, labels);
629 650
630 if (operation_cid() == kSmiCid) {
631 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
632 } else if (operation_cid() == kMintCid) {
633 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
634 } else {
635 ASSERT(operation_cid() == kDoubleCid);
636 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
637 }
638 Register result = locs()->out().reg(); 651 Register result = locs()->out().reg();
639 Label done; 652 Label done;
640 __ Bind(&is_false); 653 __ Bind(&is_false);
641 __ LoadObject(result, Bool::False()); 654 __ LoadObject(result, Bool::False());
642 __ jmp(&done, Assembler::kNearJump); 655 __ jmp(&done, Assembler::kNearJump);
643 __ Bind(&is_true); 656 __ Bind(&is_true);
644 __ LoadObject(result, Bool::True()); 657 __ LoadObject(result, Bool::True());
645 __ Bind(&done); 658 __ Bind(&done);
646 } 659 }
647 660
648 661
649 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 662 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
650 BranchInstr* branch) { 663 BranchInstr* branch) {
651 BranchLabels labels = compiler->CreateBranchLabels(branch); 664 BranchLabels labels = compiler->CreateBranchLabels(branch);
652 665 Condition true_condition = EmitComparisonCode(compiler, labels);
653 if (operation_cid() == kSmiCid) { 666 EmitBranchOnCondition(compiler, true_condition, labels);
654 EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
655 } else if (operation_cid() == kMintCid) {
656 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
657 } else {
658 ASSERT(operation_cid() == kDoubleCid);
659 EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
660 }
661 } 667 }
662 668
663 669
664 LocationSummary* NativeCallInstr::MakeLocationSummary() const { 670 LocationSummary* NativeCallInstr::MakeLocationSummary() const {
665 const intptr_t kNumInputs = 0; 671 const intptr_t kNumInputs = 0;
666 const intptr_t kNumTemps = 3; 672 const intptr_t kNumTemps = 3;
667 LocationSummary* locs = 673 LocationSummary* locs =
668 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 674 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
669 locs->set_temp(0, Location::RegisterLocation(EAX)); 675 locs->set_temp(0, Location::RegisterLocation(EAX));
670 locs->set_temp(1, Location::RegisterLocation(ECX)); 676 locs->set_temp(1, Location::RegisterLocation(ECX));
(...skipping 3940 matching lines...) Expand 10 before | Expand all | Expand 10 after
4611 // Only one of the inputs can be a constant. Choose register if the first one 4617 // Only one of the inputs can be a constant. Choose register if the first one
4612 // is a constant. 4618 // is a constant.
4613 locs->set_in(1, locs->in(0).IsConstant() 4619 locs->set_in(1, locs->in(0).IsConstant()
4614 ? Location::RequiresRegister() 4620 ? Location::RequiresRegister()
4615 : Location::RegisterOrConstant(right())); 4621 : Location::RegisterOrConstant(right()));
4616 locs->set_out(Location::RequiresRegister()); 4622 locs->set_out(Location::RequiresRegister());
4617 return locs; 4623 return locs;
4618 } 4624 }
4619 4625
4620 4626
4621 static void EmitStrictComparison(FlowGraphCompiler* compiler, 4627 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
4622 StrictCompareInstr* compare, 4628 BranchLabels labels) {
4623 BranchLabels labels) { 4629 Location left = locs()->in(0);
4624 LocationSummary* locs = compare->locs(); 4630 Location right = locs()->in(1);
4625 bool needs_number_check = compare->needs_number_check();
4626 intptr_t token_pos = compare->token_pos();
4627 Token::Kind kind = compare->kind();
4628 Location left = locs->in(0);
4629 Location right = locs->in(1);
4630 ASSERT(!left.IsConstant() || !right.IsConstant()); 4631 ASSERT(!left.IsConstant() || !right.IsConstant());
4631 if (left.IsConstant()) { 4632 if (left.IsConstant()) {
4632 compiler->EmitEqualityRegConstCompare(right.reg(), 4633 compiler->EmitEqualityRegConstCompare(right.reg(),
4633 left.constant(), 4634 left.constant(),
4634 needs_number_check, 4635 needs_number_check(),
4635 token_pos); 4636 token_pos());
4636 } else if (right.IsConstant()) { 4637 } else if (right.IsConstant()) {
4637 compiler->EmitEqualityRegConstCompare(left.reg(), 4638 compiler->EmitEqualityRegConstCompare(left.reg(),
4638 right.constant(), 4639 right.constant(),
4639 needs_number_check, 4640 needs_number_check(),
4640 token_pos); 4641 token_pos());
4641 } else { 4642 } else {
4642 compiler->EmitEqualityRegRegCompare(left.reg(), 4643 compiler->EmitEqualityRegRegCompare(left.reg(),
4643 right.reg(), 4644 right.reg(),
4644 needs_number_check, 4645 needs_number_check(),
4645 token_pos); 4646 token_pos());
4646 } 4647 }
4647 Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 4648 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
4648 EmitBranchOnCondition(compiler, true_condition, labels); 4649 return true_condition;
4649 } 4650 }
4650 4651
4651 4652
4652 // Special code for numbers (compare values instead of references.)
4653 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4653 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4654 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4654 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4655 4655
4656 Label is_true, is_false; 4656 Label is_true, is_false;
4657 BranchLabels labels = { &is_true, &is_false, &is_false }; 4657 BranchLabels labels = { &is_true, &is_false, &is_false };
4658 4658 Condition true_condition = EmitComparisonCode(compiler, labels);
4659 EmitStrictComparison(compiler, this, labels); 4659 EmitBranchOnCondition(compiler, true_condition, labels);
4660 4660
4661 Register result = locs()->out().reg(); 4661 Register result = locs()->out().reg();
4662 Label done; 4662 Label done;
4663 __ Bind(&is_false); 4663 __ Bind(&is_false);
4664 __ LoadObject(result, Bool::False()); 4664 __ LoadObject(result, Bool::False());
4665 __ jmp(&done, Assembler::kNearJump); 4665 __ jmp(&done, Assembler::kNearJump);
4666 __ Bind(&is_true); 4666 __ Bind(&is_true);
4667 __ LoadObject(result, Bool::True()); 4667 __ LoadObject(result, Bool::True());
4668 __ Bind(&done); 4668 __ Bind(&done);
4669 } 4669 }
4670 4670
4671 4671
4672 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 4672 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
4673 BranchInstr* branch) { 4673 BranchInstr* branch) {
4674 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 4674 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
4675 4675
4676 BranchLabels labels = compiler->CreateBranchLabels(branch); 4676 BranchLabels labels = compiler->CreateBranchLabels(branch);
4677 4677 Condition true_condition = EmitComparisonCode(compiler, labels);
4678 EmitStrictComparison(compiler, this, labels); 4678 EmitBranchOnCondition(compiler, true_condition, labels);
4679 } 4679 }
4680 4680
4681 4681
4682 // Detect pattern when one value is zero and another is a power of 2. 4682 // Detect pattern when one value is zero and another is a power of 2.
4683 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { 4683 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
4684 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || 4684 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
4685 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); 4685 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
4686 } 4686 }
4687 4687
4688 4688
4689 LocationSummary* IfThenElseInstr::MakeLocationSummary() const { 4689 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
4690 const intptr_t kNumInputs = 2; 4690 LocationSummary* locs = comparison()->MakeLocationSummary();
4691 const intptr_t kNumTemps = 0;
4692 LocationSummary* locs =
4693 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
4694 locs->set_in(0, Location::RegisterOrConstant(left()));
4695 // Only one of the inputs can be a constant. Choose register if the first one
4696 // is a constant.
4697 locs->set_in(1, locs->in(0).IsConstant()
4698 ? Location::RequiresRegister()
4699 : Location::RegisterOrConstant(right()));
4700 // TODO(vegorov): support byte register constraints in the register allocator. 4691 // TODO(vegorov): support byte register constraints in the register allocator.
4701 locs->set_out(Location::RegisterLocation(EDX)); 4692 locs->set_out(Location::RegisterLocation(EDX));
4702 return locs; 4693 return locs;
4703 } 4694 }
4704 4695
4705 4696
4706 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4697 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4707 ASSERT(locs()->out().reg() == EDX); 4698 ASSERT(locs()->out().reg() == EDX);
4708 ASSERT(Token::IsEqualityOperator(kind()));
4709
4710 Location left = locs()->in(0);
4711 Location right = locs()->in(1);
4712 ASSERT(!left.IsConstant() || !right.IsConstant());
4713 4699
4714 // Clear upper part of the out register. We are going to use setcc on it 4700 // Clear upper part of the out register. We are going to use setcc on it
4715 // which is a byte move. 4701 // which is a byte move.
4716 __ xorl(EDX, EDX); 4702 __ xorl(EDX, EDX);
4717 4703
4718 // Compare left and right. For now only equality comparison is supported. 4704 // Emit comparison code. This must not overwrite the result register.
4719 // TODO(vegorov): reuse code from the other comparison instructions instead of 4705 BranchLabels labels = { NULL, NULL, NULL };
4720 // generating it inline here. 4706 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
4721 if (left.IsConstant()) {
4722 __ CompareObject(right.reg(), left.constant());
4723 } else if (right.IsConstant()) {
4724 __ CompareObject(left.reg(), right.constant());
4725 } else {
4726 __ cmpl(left.reg(), right.reg());
4727 }
4728
4729 Condition true_condition =
4730 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
4731 : NOT_EQUAL;
4732 4707
4733 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); 4708 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
4734 4709
4735 intptr_t true_value = if_true_; 4710 intptr_t true_value = if_true_;
4736 intptr_t false_value = if_false_; 4711 intptr_t false_value = if_false_;
4737 4712
4738 if (is_power_of_two_kind) { 4713 if (is_power_of_two_kind) {
4739 if (true_value == 0) { 4714 if (true_value == 0) {
4740 // We need to have zero in EDX on true_condition. 4715 // We need to have zero in EDX on true_condition.
4741 true_condition = NegateCondition(true_condition); 4716 true_condition = NegateCondition(true_condition);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
4876 PcDescriptors::kOther, 4851 PcDescriptors::kOther,
4877 locs()); 4852 locs());
4878 __ Drop(2); // Discard type arguments and receiver. 4853 __ Drop(2); // Discard type arguments and receiver.
4879 } 4854 }
4880 4855
4881 } // namespace dart 4856 } // namespace dart
4882 4857
4883 #undef __ 4858 #undef __
4884 4859
4885 #endif // defined TARGET_ARCH_IA32 4860 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698