Index: runtime/vm/intermediate_language_arm.cc |
=================================================================== |
--- runtime/vm/intermediate_language_arm.cc (revision 38346) |
+++ runtime/vm/intermediate_language_arm.cc (working copy) |
@@ -6143,13 +6143,12 @@ |
LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
bool opt) const { |
const intptr_t kNumInputs = 2; |
- const intptr_t kNumTemps = 1; |
+ const intptr_t kNumTemps = 0; |
LocationSummary* summary = new(isolate) LocationSummary( |
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
Location::RequiresRegister())); |
- summary->set_in(1, Location::WritableRegister()); |
- summary->set_temp(0, Location::RequiresRegister()); |
+ summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
Location::RequiresRegister())); |
return summary; |
@@ -6168,66 +6167,123 @@ |
PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
Register left_lo = left_pair->At(0).reg(); |
Register left_hi = left_pair->At(1).reg(); |
- Register shift = locs()->in(1).reg(); |
PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
Register out_lo = out_pair->At(0).reg(); |
Register out_hi = out_pair->At(1).reg(); |
- Register temp = locs()->temp(0).reg(); |
Label* deopt = NULL; |
if (CanDeoptimize()) { |
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
} |
- __ mov(out_lo, Operand(left_lo)); |
- __ mov(out_hi, Operand(left_hi)); |
+ 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)) { |
+ __ b(deopt); |
+ return; |
+ } else if (shift == 0) { |
+ // Nothing to do for zero shift amount. |
+ __ mov(out_lo, Operand(left_lo)); |
+ __ mov(out_hi, Operand(left_hi)); |
+ return; |
+ } |
+ switch (op_kind()) { |
+ case Token::kSHR: { |
+ if (shift < 32) { |
+ __ Lsl(out_lo, left_hi, 32 - shift); |
+ __ orr(out_lo, out_lo, Operand(left_lo, LSR, shift)); |
+ __ Asr(out_hi, left_hi, shift); |
+ } else { |
+ if (shift == 32) { |
+ __ mov(out_lo, Operand(left_hi)); |
+ } else { |
+ __ Asr(out_lo, left_hi, shift - 32); |
+ } |
+ __ Asr(out_hi, left_hi, 31); |
+ } |
+ break; |
+ } |
+ case Token::kSHL: { |
+ if (shift < 32) { |
+ __ Lsr(out_hi, left_lo, 32 - shift); |
+ __ orr(out_hi, out_hi, Operand(left_hi, LSL, shift)); |
+ __ Lsl(out_lo, left_lo, shift); |
+ } else { |
+ if (shift == 32) { |
+ __ mov(out_hi, Operand(left_lo)); |
+ } else { |
+ __ Lsl(out_hi, left_lo, shift - 32); |
+ } |
+ __ mov(out_lo, Operand(0)); |
+ } |
+ // Check for overflow. |
+ if (can_overflow()) { |
+ // Compare high word from input with shifted high word from output. |
+ if (shift > 31) { |
+ __ cmp(left_hi, Operand(out_hi)); |
+ } else { |
+ __ cmp(left_hi, Operand(out_hi, ASR, shift)); |
+ } |
+ // Overflow if they aren't equal. |
+ __ b(deopt, NE); |
+ } |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } else { |
+ // Code for a variable shift amount. |
+ Register shift = locs()->in(1).reg(); |
- // Untag shift count. |
- __ SmiUntag(shift); |
+ // Untag shift count. |
+ __ SmiUntag(shift); |
- // Deopt if shift is larger than 63 or less than 0. |
- if (has_shift_count_check()) { |
- __ CompareImmediate(shift, kMintShiftCountLimit); |
- __ b(deopt, HI); |
- } |
+ // Deopt if shift is larger than 63 or less than 0. |
+ if (has_shift_count_check()) { |
+ __ CompareImmediate(shift, kMintShiftCountLimit); |
+ __ b(deopt, HI); |
+ } |
- switch (op_kind()) { |
- case Token::kSHR: { |
- __ cmp(shift, Operand(32)); |
+ __ mov(out_lo, Operand(left_lo)); |
+ __ mov(out_hi, Operand(left_hi)); |
- __ mov(out_lo, Operand(out_hi), HI); |
- __ Asr(out_hi, out_hi, 31, HI); |
- __ sub(shift, shift, Operand(32), HI); |
+ switch (op_kind()) { |
+ case Token::kSHR: { |
+ __ cmp(shift, Operand(32)); |
- __ rsb(temp, shift, Operand(32)); |
- __ mov(temp, Operand(out_hi, LSL, temp)); |
- __ orr(out_lo, temp, Operand(out_lo, LSR, shift)); |
- __ Asr(out_hi, out_hi, shift); |
- break; |
- } |
- case Token::kSHL: { |
- __ rsbs(temp, shift, Operand(32)); |
- __ sub(temp, shift, Operand(32), MI); |
- __ mov(out_hi, Operand(out_lo, LSL, temp), MI); |
- __ mov(out_hi, Operand(out_hi, LSL, shift), PL); |
- __ orr(out_hi, out_hi, Operand(out_lo, LSR, temp), PL); |
- __ mov(out_lo, Operand(out_lo, LSL, shift)); |
+ __ mov(out_lo, Operand(out_hi), HI); |
+ __ Asr(out_hi, out_hi, 31, HI); |
+ __ sub(shift, shift, Operand(32), HI); |
- // Check for overflow. |
- if (can_overflow()) { |
- // Copy high word from output. |
- __ mov(temp, Operand(out_hi)); |
- // Shift copy right. |
- __ Asr(temp, temp, shift); |
- // Compare with high word from input. |
- __ cmp(temp, Operand(left_hi)); |
- // Overflow if they aren't equal. |
- __ b(deopt, NE); |
+ __ rsb(IP, shift, Operand(32)); |
+ __ mov(IP, Operand(out_hi, LSL, IP)); |
+ __ orr(out_lo, IP, Operand(out_lo, LSR, shift)); |
+ __ Asr(out_hi, out_hi, shift); |
+ break; |
} |
- break; |
+ case Token::kSHL: { |
+ __ rsbs(IP, shift, Operand(32)); |
+ __ sub(IP, shift, Operand(32), MI); |
+ __ mov(out_hi, Operand(out_lo, LSL, IP), MI); |
+ __ mov(out_hi, Operand(out_hi, LSL, shift), PL); |
+ __ orr(out_hi, out_hi, Operand(out_lo, LSR, IP), PL); |
+ __ mov(out_lo, Operand(out_lo, LSL, shift)); |
+ |
+ // Check for overflow. |
+ if (can_overflow()) { |
+ // Compare high word from input with shifted high word from output. |
+ __ cmp(left_hi, Operand(out_hi, ASR, shift)); |
+ // Overflow if they aren't equal. |
+ __ b(deopt, NE); |
+ } |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
} |
- default: |
- UNREACHABLE(); |
- break; |
} |
if (FLAG_throw_on_javascript_int_overflow) { |