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

Unified Diff: runtime/vm/intermediate_language_ia32.cc

Issue 387733002: Specialize mint shift code on ia32 for a constant shift amount. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/disassembler_ia32.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language_ia32.cc
===================================================================
--- runtime/vm/intermediate_language_ia32.cc (revision 38138)
+++ runtime/vm/intermediate_language_ia32.cc (working copy)
@@ -5610,7 +5610,7 @@
if (index_loc.IsConstant()) {
Register length = length_loc.reg();
- const Object& index = Smi::Cast(index_loc.constant());
+ const Smi& index = Smi::Cast(index_loc.constant());
__ cmpl(length, Immediate(reinterpret_cast<int32_t>(index.raw())));
__ j(BELOW_EQUAL, deopt);
} else if (length_loc.IsConstant()) {
@@ -5897,7 +5897,7 @@
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::Pair(Location::RequiresRegister(),
Location::RequiresRegister()));
- summary->set_in(1, Location::RegisterLocation(ECX));
+ summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
if ((op_kind() == Token::kSHL) && CanDeoptimize()) {
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
@@ -5929,82 +5929,155 @@
if (CanDeoptimize()) {
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
}
- // Deoptimize if shift count is > 63.
- // sarl operation masks the count to 5 bits and
- // shrd is undefined with count > operand size (32)
- __ SmiUntag(ECX);
- if (has_shift_count_check()) {
- __ cmpl(ECX, Immediate(kMintShiftCountLimit));
- __ j(ABOVE, deopt);
- }
- // TODO(regis): Specialize code for constant shift amount.
- Label large_shift, done;
- switch (op_kind()) {
- case Token::kSHR: {
- __ cmpl(ECX, Immediate(31));
- __ j(ABOVE, &large_shift);
-
- __ shrd(left_lo, left_hi); // Shift count in CL.
- __ sarl(left_hi, ECX); // Shift count in CL.
- __ jmp(&done, Assembler::kNearJump);
-
- __ Bind(&large_shift);
- __ subl(ECX, Immediate(32));
- __ movl(left_lo, left_hi); // Shift by 32.
- __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
- __ sarl(left_lo, ECX); // Shift count - 32 in CL.
- break;
+ if (locs()->in(1).IsConstant()) {
+ // Code for a constant shift amount.
+ ASSERT(locs()->in(1).constant().IsSmi());
+ const int32_t shift =
+ reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1;
+ if ((shift < 0) || (shift > kMintShiftCountLimit)) {
+ __ jmp(deopt);
+ return;
+ } else if (shift == 0) {
+ // Nothing to do for zero shift amount.
+ return;
}
- case Token::kSHL: {
- if (can_overflow()) {
- Register temp1 = locs()->temp(0).reg();
- Register temp2 = locs()->temp(1).reg();
- __ movl(temp1, left_hi); // Preserve high 32 bits.
+ switch (op_kind()) {
+ case Token::kSHR: {
+ if (shift > 31) {
+ __ movl(left_lo, left_hi); // Shift by 32.
+ __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
+ if (shift > 32) {
+ __ sarl(left_lo, Immediate(shift - 32));
+ }
+ } else {
+ __ shrd(left_lo, left_hi, Immediate(shift));
+ __ sarl(left_hi, Immediate(shift));
+ }
+ break;
+ }
+ case Token::kSHL: {
+ if (can_overflow()) {
+ Register temp1 = locs()->temp(0).reg();
+ Register temp2 = locs()->temp(1).reg();
+ __ movl(temp1, left_hi); // Preserve high 32 bits.
+ if (shift > 31) {
+ __ movl(left_hi, left_lo); // Shift by 32.
+ __ xorl(left_lo, left_lo); // Zero left_lo.
+ if (shift > 32) {
+ __ shll(left_hi, Immediate(shift - 32));
+ }
+ // Check for overflow by sign extending the high 32 bits
+ // and comparing with the input.
+ __ movl(temp2, left_hi);
+ __ sarl(temp2, Immediate(31));
+ __ cmpl(temp1, temp2);
+ __ j(NOT_EQUAL, deopt);
+ } else {
+ __ shld(left_hi, left_lo, Immediate(shift));
+ __ shll(left_lo, Immediate(shift));
+ // Check for overflow by shifting back the high 32 bits
+ // and comparing with the input.
+ __ movl(temp2, left_hi);
+ __ sarl(temp2, Immediate(shift));
+ __ cmpl(temp1, temp2);
+ __ j(NOT_EQUAL, deopt);
+ }
+ } else {
+ if (shift > 31) {
+ __ movl(left_hi, left_lo); // Shift by 32.
+ __ xorl(left_lo, left_lo); // Zero left_lo.
+ if (shift > 32) {
+ __ shll(left_hi, Immediate(shift - 32));
+ }
+ } else {
+ __ shld(left_hi, left_lo, Immediate(shift));
+ __ shll(left_lo, Immediate(shift));
+ }
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ } else {
+ // Code for a variable shift amount.
+ // Deoptimize if shift count is > 63.
+ // sarl operation masks the count to 5 bits and
+ // shrd is undefined with count > operand size (32)
+ __ SmiUntag(ECX);
+ if (has_shift_count_check()) {
+ __ cmpl(ECX, Immediate(kMintShiftCountLimit));
+ __ j(ABOVE, deopt);
+ }
+ Label done, large_shift;
+ switch (op_kind()) {
+ case Token::kSHR: {
__ cmpl(ECX, Immediate(31));
__ j(ABOVE, &large_shift);
- __ shld(left_hi, left_lo); // Shift count in CL.
- __ shll(left_lo, ECX); // Shift count in CL.
- // Check for overflow by shifting back the high 32 bits
- // and comparing with the input.
- __ movl(temp2, left_hi);
- __ sarl(temp2, ECX);
- __ cmpl(temp1, temp2);
- __ j(NOT_EQUAL, deopt);
+ __ shrd(left_lo, left_hi); // Shift count in CL.
+ __ sarl(left_hi, ECX); // Shift count in CL.
__ jmp(&done, Assembler::kNearJump);
__ Bind(&large_shift);
__ subl(ECX, Immediate(32));
- __ movl(left_hi, left_lo); // Shift by 32.
- __ xorl(left_lo, left_lo); // Zero left_lo.
- __ shll(left_hi, ECX); // Shift count in CL.
- // Check for overflow by sign extending the high 32 bits
- // and comparing with the input.
- __ movl(temp2, left_hi);
- __ sarl(temp2, Immediate(31));
- __ cmpl(temp1, temp2);
- __ j(NOT_EQUAL, deopt);
- } else {
- __ cmpl(ECX, Immediate(31));
- __ j(ABOVE, &large_shift);
+ __ movl(left_lo, left_hi); // Shift by 32.
+ __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
+ __ sarl(left_lo, ECX); // Shift count - 32 in CL.
+ break;
+ }
+ case Token::kSHL: {
+ if (can_overflow()) {
+ Register temp1 = locs()->temp(0).reg();
+ Register temp2 = locs()->temp(1).reg();
+ __ movl(temp1, left_hi); // Preserve high 32 bits.
+ __ cmpl(ECX, Immediate(31));
+ __ j(ABOVE, &large_shift);
- __ shld(left_hi, left_lo); // Shift count in CL.
- __ shll(left_lo, ECX); // Shift count in CL.
- __ jmp(&done, Assembler::kNearJump);
+ __ shld(left_hi, left_lo); // Shift count in CL.
+ __ shll(left_lo, ECX); // Shift count in CL.
+ // Check for overflow by shifting back the high 32 bits
+ // and comparing with the input.
+ __ movl(temp2, left_hi);
+ __ sarl(temp2, ECX);
+ __ cmpl(temp1, temp2);
+ __ j(NOT_EQUAL, deopt);
+ __ jmp(&done, Assembler::kNearJump);
- __ Bind(&large_shift);
- __ subl(ECX, Immediate(32));
- __ movl(left_hi, left_lo); // Shift by 32.
- __ xorl(left_lo, left_lo); // Zero left_lo.
- __ shll(left_hi, ECX); // Shift count in CL.
+ __ Bind(&large_shift);
+ __ subl(ECX, Immediate(32));
+ __ movl(left_hi, left_lo); // Shift by 32.
+ __ xorl(left_lo, left_lo); // Zero left_lo.
+ __ shll(left_hi, ECX); // Shift count in CL.
+ // Check for overflow by sign extending the high 32 bits
+ // and comparing with the input.
+ __ movl(temp2, left_hi);
+ __ sarl(temp2, Immediate(31));
+ __ cmpl(temp1, temp2);
+ __ j(NOT_EQUAL, deopt);
+ } else {
+ __ cmpl(ECX, Immediate(31));
+ __ j(ABOVE, &large_shift);
+
+ __ shld(left_hi, left_lo); // Shift count in CL.
+ __ shll(left_lo, ECX); // Shift count in CL.
+ __ jmp(&done, Assembler::kNearJump);
+
+ __ Bind(&large_shift);
+ __ subl(ECX, Immediate(32));
+ __ movl(left_hi, left_lo); // Shift by 32.
+ __ xorl(left_lo, left_lo); // Zero left_lo.
+ __ shll(left_hi, ECX); // Shift count in CL.
+ }
+ break;
}
- break;
+ default:
+ UNREACHABLE();
+ break;
}
- default:
- UNREACHABLE();
- break;
+ __ Bind(&done);
}
- __ Bind(&done);
if (FLAG_throw_on_javascript_int_overflow) {
EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
}
« no previous file with comments | « runtime/vm/disassembler_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698