Chromium Code Reviews| Index: runtime/vm/intermediate_language_ia32.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_ia32.cc (revision 14174) |
| +++ runtime/vm/intermediate_language_ia32.cc (working copy) |
| @@ -645,8 +645,12 @@ |
| switch (kind) { |
| case Token::kEQ: return EQUAL; |
| case Token::kNE: return NOT_EQUAL; |
| + case Token::kLT: return LESS; |
| + case Token::kGT: return GREATER; |
| + case Token::kLTE: return LESS_EQUAL; |
| + case Token::kGTE: return GREATER_EQUAL; |
| default: |
| - UNIMPLEMENTED(); |
| + UNREACHABLE(); |
| return OVERFLOW; |
| } |
| } |
| @@ -682,6 +686,71 @@ |
| } |
| +static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| + const LocationSummary& locs, |
| + Token::Kind kind, |
| + BranchInstr* branch) { |
|
srdjan
2012/10/29 19:30:25
Isn't it slower to unbox Mint's for comparison, vs
Florian Schneider
2012/10/30 12:09:04
Yes, in the worst cast where we have two boxed min
|
| + XmmRegister left = locs.in(0).xmm_reg(); |
| + XmmRegister right = locs.in(1).xmm_reg(); |
| + Register left_tmp = locs.temp(0).reg(); |
| + Register right_tmp = locs.temp(1).reg(); |
| + Register result = branch == NULL ? locs.out().reg() : kNoRegister; |
| + |
| + Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; |
| + switch (kind) { |
| + case Token::kLT: |
| + hi_cond = LESS; |
| + lo_cond = BELOW; |
| + break; |
| + case Token::kGT: |
| + hi_cond = GREATER; |
| + lo_cond = ABOVE; |
| + break; |
| + case Token::kLTE: |
| + hi_cond = LESS; |
| + lo_cond = BELOW_EQUAL; |
| + break; |
| + case Token::kGTE: |
| + hi_cond = GREATER; |
| + lo_cond = ABOVE_EQUAL; |
| + break; |
| + default: |
| + break; |
| + } |
| + ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); |
| + Label is_true, is_false; |
| + // Compare upper halves first. |
| + __ pextrd(left_tmp, left, Immediate(1)); |
| + __ pextrd(right_tmp, right, Immediate(1)); |
| + __ cmpl(left_tmp, right_tmp); |
| + if (branch != NULL) { |
| + __ j(hi_cond, compiler->GetBlockLabel(branch->true_successor())); |
| + __ j(FlowGraphCompiler::FlipCondition(hi_cond), |
| + compiler->GetBlockLabel(branch->false_successor())); |
| + } else { |
| + __ j(hi_cond, &is_true); |
| + __ j(FlowGraphCompiler::FlipCondition(hi_cond), &is_false); |
| + } |
| + |
| + // If upper is equal, compare lower half. |
| + __ pextrd(left_tmp, left, Immediate(0)); |
| + __ pextrd(right_tmp, right, Immediate(0)); |
| + __ cmpl(left_tmp, right_tmp); |
| + if (branch != NULL) { |
| + branch->EmitBranchOnCondition(compiler, lo_cond); |
| + } else { |
| + Label done; |
| + __ j(lo_cond, &is_true); |
| + __ Bind(&is_false); |
| + __ LoadObject(result, compiler->bool_false()); |
| + __ jmp(&done); |
| + __ Bind(&is_true); |
| + __ LoadObject(result, compiler->bool_true()); |
| + __ Bind(&done); |
| + } |
| +} |
| + |
| + |
| static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| switch (kind) { |
| case Token::kEQ: return EQUAL; |
| @@ -801,6 +870,17 @@ |
| LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| const intptr_t kNumInputs = 2; |
| const intptr_t kNumTemps = 0; |
| + if (operands_class_id() == kMintCid) { |
| + const intptr_t kNumTemps = 2; |
| + LocationSummary* locs = |
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| + locs->set_in(0, Location::RequiresXmmRegister()); |
| + locs->set_in(1, Location::RequiresXmmRegister()); |
| + locs->set_temp(0, Location::RequiresRegister()); |
| + locs->set_temp(1, Location::RequiresRegister()); |
| + locs->set_out(Location::RequiresRegister()); |
| + return locs; |
| + } |
| if (operands_class_id() == kDoubleCid) { |
| LocationSummary* summary = |
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| @@ -831,6 +911,10 @@ |
| EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| return; |
| } |
| + if (operands_class_id() == kMintCid) { |
| + EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); |
| + return; |
| + } |
| if (operands_class_id() == kDoubleCid) { |
| EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| return; |
| @@ -890,6 +974,10 @@ |
| EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| return; |
| } |
| + if (operands_class_id() == kMintCid) { |
| + EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| + return; |
| + } |
| if (operands_class_id() == kDoubleCid) { |
| EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| return; |
| @@ -2444,8 +2532,8 @@ |
| Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| kDeoptBinaryMintOp); |
| Label done, overflow; |
| - __ pextrd(lo, right, Immediate(0)); // Lower half left |
| - __ pextrd(hi, right, Immediate(1)); // Upper half left |
| + __ pextrd(lo, right, Immediate(0)); // Lower half |
| + __ pextrd(hi, right, Immediate(1)); // Upper half |
| __ subl(ESP, Immediate(2 * kWordSize)); |
| __ movq(Address(ESP, 0), left); |
| if (op_kind() == Token::kADD) { |