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

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

Issue 14057004: Convert diamond shaped control flow into a single conditional instruction. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Florian's comments Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 3585 matching lines...) Expand 10 before | Expand all | Expand 10 after
3596 compiler->EmitEqualityRegRegCompare(left.reg(), 3596 compiler->EmitEqualityRegRegCompare(left.reg(),
3597 right.reg(), 3597 right.reg(),
3598 needs_number_check()); 3598 needs_number_check());
3599 } 3599 }
3600 3600
3601 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 3601 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
3602 branch->EmitBranchOnCondition(compiler, true_condition); 3602 branch->EmitBranchOnCondition(compiler, true_condition);
3603 } 3603 }
3604 3604
3605 3605
3606 static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) {
3607 if (!val->BindsToConstant()) {
3608 return false;
3609 }
3610
3611 const Object& bound_constant = val->BoundConstant();
3612 if (!bound_constant.IsSmi()) {
3613 return false;
3614 }
3615
3616 *smi_value = Smi::Cast(bound_constant).Value();
3617 return true;
3618 }
3619
3620
3621 // Detect pattern when one value is zero and another is a power of 2.
3622 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) {
3623 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) ||
3624 (Utils::IsPowerOfTwo(v2) && (v1 == 0));
3625 }
3626
3627
3628 // Detect pattern when one value is increment of another.
3629 static bool IsIncrementKind(intptr_t v1, intptr_t v2) {
3630 return ((v1 == v2 + 1) || (v1 + 1 == v2));
3631 }
3632
3633
3634 bool IfThenElseInstr::IsSupported() {
3635 return true;
3636 }
3637
3638
3639 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
3640 Value* v1,
3641 Value* v2) {
3642 if (!(comparison->IsStrictCompare() &&
3643 !comparison->AsStrictCompare()->needs_number_check()) &&
3644 !(comparison->IsEqualityCompare() &&
3645 (comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) {
3646 return false;
3647 }
3648
3649 intptr_t v1_value, v2_value;
3650
3651 if (!BindsToSmiConstant(v1, &v1_value) ||
3652 !BindsToSmiConstant(v2, &v2_value)) {
3653 return false;
3654 }
3655
3656 if (IsPowerOfTwoKind(v1_value, v2_value) ||
3657 IsIncrementKind(v1_value, v2_value)) {
3658 return true;
3659 }
3660
3661 return false;
3662 }
3663
3664
3665 LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
3666 const intptr_t kNumInputs = 2;
3667 const intptr_t kNumTemps = 0;
3668 LocationSummary* locs =
3669 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3670 locs->set_in(0, Location::RegisterOrConstant(left()));
3671 locs->set_in(1, Location::RegisterOrConstant(right()));
3672 // TODO(vegorov): support byte register constraints in the register allocator.
3673 locs->set_out(Location::RegisterLocation(EDX));
3674 return locs;
3675 }
3676
3677
3678 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3679 ASSERT(locs()->out().reg() == EDX);
3680 ASSERT(Token::IsEqualityOperator(kind()));
3681
3682 Location left = locs()->in(0);
3683 Location right = locs()->in(1);
3684 ASSERT(!left.IsConstant() || !right.IsConstant());
3685
3686 // Clear upper part of the out register. We are going to use setcc on it
3687 // which is a byte move.
3688 __ xorl(EDX, EDX);
3689
3690 // Compare left and right. For now only equality comparison is supported.
3691 // TODO(vegorov): reuse code from the other comparison instructions instead of
3692 // generating it inline here.
3693 if (left.IsConstant()) {
3694 __ CompareObject(right.reg(), left.constant());
3695 } else if (right.IsConstant()) {
3696 __ CompareObject(left.reg(), right.constant());
3697 } else {
3698 __ cmpl(left.reg(), right.reg());
3699 }
3700
3701 Condition true_condition =
3702 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
3703 : NOT_EQUAL;
3704
3705 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
3706
3707 const intptr_t base = Utils::Minimum(if_true_, if_false_);
3708
3709 if (if_true_ == base) {
3710 // We need to have zero in EDX on true_condition.
3711 true_condition = NegateCondition(true_condition);
3712 }
3713
3714 __ setcc(true_condition, DL);
3715
3716 if (is_power_of_two_kind) {
3717 const intptr_t shift =
3718 Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_));
3719 __ shll(EDX, Immediate(shift + kSmiTagSize));
3720 } else {
3721 ASSERT(kSmiTagSize == 1);
3722 __ leal(EDX, Address(EDX, TIMES_2, base << kSmiTagSize));
3723 }
3724 }
3725
3726
3606 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3727 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3607 // The arguments to the stub include the closure, as does the arguments 3728 // The arguments to the stub include the closure, as does the arguments
3608 // descriptor. 3729 // descriptor.
3609 Register temp_reg = locs()->temp(0).reg(); 3730 Register temp_reg = locs()->temp(0).reg();
3610 int argument_count = ArgumentCount(); 3731 int argument_count = ArgumentCount();
3611 const Array& arguments_descriptor = 3732 const Array& arguments_descriptor =
3612 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, 3733 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
3613 argument_names())); 3734 argument_names()));
3614 __ LoadObject(temp_reg, arguments_descriptor); 3735 __ LoadObject(temp_reg, arguments_descriptor);
3615 compiler->GenerateDartCall(deopt_id(), 3736 compiler->GenerateDartCall(deopt_id(),
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3719 PcDescriptors::kOther, 3840 PcDescriptors::kOther,
3720 locs()); 3841 locs());
3721 __ Drop(2); // Discard type arguments and receiver. 3842 __ Drop(2); // Discard type arguments and receiver.
3722 } 3843 }
3723 3844
3724 } // namespace dart 3845 } // namespace dart
3725 3846
3726 #undef __ 3847 #undef __
3727 3848
3728 #endif // defined TARGET_ARCH_IA32 3849 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698