| Index: runtime/vm/intermediate_language_ia32.cc
|
| diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
|
| index a07b68266aa6c77c2e1bfa3ad41cd8b46ed1ddd3..0f7e539d967aad2b69294c044735593cee73b264 100644
|
| --- a/runtime/vm/intermediate_language_ia32.cc
|
| +++ b/runtime/vm/intermediate_language_ia32.cc
|
| @@ -31,7 +31,13 @@ LocationSummary* Computation::MakeCallSummary() {
|
|
|
| void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| computation()->EmitNativeCode(compiler);
|
| - __ pushl(locs()->out().reg());
|
| + if (locs()->out().kind() == Location::kRegister) {
|
| + // TODO(vegorov): this should really happen only for comparisons fused
|
| + // with branches. Currrently IR does not provide an easy way to remove
|
| + // instructions from the graph so we just leave fused comparison in it
|
| + // but change its result location to be NoLocation.
|
| + __ pushl(locs()->out().reg());
|
| + }
|
| }
|
|
|
|
|
| @@ -163,9 +169,9 @@ void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| // Check that the type of the value is allowed in conditional context.
|
| // Call the runtime if the object is not bool::true or bool::false.
|
| Label done;
|
| - __ CompareObject(obj, Bool::ZoneHandle(Bool::True()));
|
| + __ CompareObject(obj, compiler->bool_true());
|
| __ j(EQUAL, &done, Assembler::kNearJump);
|
| - __ CompareObject(obj, Bool::ZoneHandle(Bool::False()));
|
| + __ CompareObject(obj, compiler->bool_false());
|
| __ j(EQUAL, &done, Assembler::kNearJump);
|
|
|
| __ pushl(Immediate(Smi::RawValue(token_index()))); // Source location.
|
| @@ -186,7 +192,9 @@ LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
|
| LocationSummary* locs = new LocationSummary(2, 0);
|
| locs->set_in(0, Location::RequiresRegister());
|
| locs->set_in(1, Location::RequiresRegister());
|
| - locs->set_out(Location::RegisterLocation(EAX));
|
| + if (!is_fused_with_branch()) {
|
| + locs->set_out(Location::RegisterLocation(EAX));
|
| + }
|
| return locs;
|
| }
|
|
|
| @@ -194,23 +202,25 @@ LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
|
| void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| Register left = locs()->in(0).reg();
|
| Register right = locs()->in(1).reg();
|
| - Register result = locs()->out().reg();
|
| - ASSERT(locs()->out().reg() == EAX);
|
|
|
| - const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
| - const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
| const Immediate raw_null =
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| - Label done, load_true, non_null_compare;
|
| + Label done, non_null_compare;
|
| __ cmpl(left, raw_null);
|
| __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump);
|
| // Comparison with NULL is "===".
|
| __ cmpl(left, right);
|
| - __ j(EQUAL, &load_true, Assembler::kNearJump);
|
| - __ LoadObject(result, bool_false);
|
| - __ jmp(&done, Assembler::kNearJump);
|
| - __ Bind(&load_true);
|
| - __ LoadObject(result, bool_true);
|
| + if (!is_fused_with_branch()) {
|
| + Register result = locs()->out().reg();
|
| + Label load_true;
|
| + __ j(EQUAL, &load_true, Assembler::kNearJump);
|
| + __ LoadObject(result, compiler->bool_false());
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + __ Bind(&load_true);
|
| + __ LoadObject(result, compiler->bool_true());
|
| + } else {
|
| + fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
|
| + }
|
| __ jmp(&done);
|
|
|
| __ Bind(&non_null_compare);
|
| @@ -228,6 +238,13 @@ void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| kNumberOfArguments,
|
| kNoArgumentNames,
|
| kNumArgumentsChecked);
|
| + ASSERT(fused_with_branch() != NULL || locs()->out().reg() == EAX);
|
| +
|
| + if (fused_with_branch() != NULL) {
|
| + __ CompareObject(EAX, compiler->bool_true());
|
| + fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
|
| + }
|
| +
|
| __ Bind(&done);
|
| }
|
|
|
| @@ -239,7 +256,9 @@ LocationSummary* RelationalOpComp::MakeLocationSummary() const {
|
| LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps);
|
| summary->set_in(0, Location::RequiresRegister());
|
| summary->set_in(1, Location::RequiresRegister());
|
| - summary->set_out(Location::RequiresRegister());
|
| + if (!is_fused_with_branch()) {
|
| + summary->set_out(Location::RequiresRegister());
|
| + }
|
| summary->set_temp(0, Location::RequiresRegister());
|
| return summary;
|
| }
|
| @@ -267,7 +286,6 @@ static void EmitSmiRelationalOp(FlowGraphCompiler* compiler,
|
| RelationalOpComp* comp) {
|
| Register left = comp->locs()->in(0).reg();
|
| Register right = comp->locs()->in(1).reg();
|
| - Register result = comp->locs()->out().reg();
|
| Register temp = comp->locs()->temp(0).reg();
|
| Label* deopt = compiler->AddDeoptStub(comp->cid(),
|
| comp->token_index(),
|
| @@ -279,18 +297,23 @@ static void EmitSmiRelationalOp(FlowGraphCompiler* compiler,
|
| __ orl(temp, right);
|
| __ testl(temp, Immediate(kSmiTagMask));
|
| __ j(NOT_ZERO, deopt);
|
| - const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
| - const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
| - Condition condition = TokenKindToSmiCondition(comp->kind());
|
|
|
| - Label done, is_true;
|
| + Condition true_condition = TokenKindToSmiCondition(comp->kind());
|
| __ cmpl(left, right);
|
| - __ j(condition, &is_true);
|
| - __ LoadObject(result, bool_false);
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, bool_true);
|
| - __ Bind(&done);
|
| +
|
| + if (comp->is_fused_with_branch()) {
|
| + comp->fused_with_branch()->EmitBranchOnCondition(compiler, true_condition);
|
| + } else {
|
| + Register result = comp->locs()->out().reg();
|
| + Label done, is_true;
|
| +
|
| + __ j(true_condition, &is_true);
|
| + __ LoadObject(result, compiler->bool_false());
|
| + __ jmp(&done);
|
| + __ Bind(&is_true);
|
| + __ LoadObject(result, compiler->bool_true());
|
| + __ Bind(&done);
|
| + }
|
| }
|
|
|
|
|
| @@ -312,7 +335,6 @@ static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler,
|
| RelationalOpComp* comp) {
|
| Register left = comp->locs()->in(0).reg();
|
| Register right = comp->locs()->in(1).reg();
|
| - Register result = comp->locs()->out().reg();
|
| // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
|
| Register temp = comp->locs()->temp(0).reg();
|
| Label* deopt = compiler->AddDeoptStub(comp->cid(),
|
| @@ -323,19 +345,26 @@ static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler,
|
| right);
|
| compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
|
| compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
|
| - const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
| - const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
| +
|
| Condition true_condition = TokenKindToDoubleCondition(comp->kind());
|
| - Label is_false, is_true, done;
|
| __ comisd(XMM0, XMM1);
|
| - __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
|
| - __ j(true_condition, &is_true, Assembler::kNearJump);
|
| - __ Bind(&is_false);
|
| - __ LoadObject(result, bool_false);
|
| - __ jmp(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadObject(result, bool_true);
|
| - __ Bind(&done);
|
| +
|
| + if (comp->is_fused_with_branch()) {
|
| + BranchInstr* branch = comp->fused_with_branch();
|
| + __ j(PARITY_EVEN, compiler->GetBlockLabel(branch->false_successor()));
|
| + branch->EmitBranchOnCondition(compiler, true_condition);
|
| + } else {
|
| + Register result = comp->locs()->out().reg();
|
| + Label is_false, is_true, done;
|
| + __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
|
| + __ j(true_condition, &is_true, Assembler::kNearJump);
|
| + __ Bind(&is_false);
|
| + __ LoadObject(result, compiler->bool_false());
|
| + __ jmp(&done);
|
| + __ Bind(&is_true);
|
| + __ LoadObject(result, compiler->bool_true());
|
| + __ Bind(&done);
|
| + }
|
| }
|
|
|
|
|
| @@ -1426,10 +1455,11 @@ void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
| LocationSummary* ToDoubleComp::MakeLocationSummary() const {
|
| const intptr_t kNumInputs = 1;
|
| - const intptr_t kNumTemps = 1;
|
| if (from() == kDouble) {
|
| + const intptr_t kNumTemps = 1;
|
| LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps);
|
| locs->set_in(0, Location::RequiresRegister());
|
| + locs->set_temp(0, Location::RequiresRegister());
|
| locs->set_out(Location::SameAsFirstInput());
|
| return locs;
|
| } else {
|
|
|