| Index: runtime/vm/intermediate_language_arm.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_arm.cc (revision 24190)
|
| +++ runtime/vm/intermediate_language_arm.cc (working copy)
|
| @@ -2154,8 +2154,8 @@
|
| ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right))));
|
| __ b(deopt, CS);
|
| }
|
| - __ SmiUntag(right);
|
| - __ Lsl(result, left, right);
|
| + __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
|
| + __ Lsl(result, left, IP);
|
| }
|
| return;
|
| }
|
| @@ -2176,11 +2176,11 @@
|
| __ cmp(right,
|
| ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
|
| __ mov(result, ShifterOperand(0), CS);
|
| - __ SmiUntag(right, CC);
|
| - __ Lsl(result, left, right, CC);
|
| + __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC.
|
| + __ Lsl(result, left, IP, CC);
|
| } else {
|
| - __ SmiUntag(right);
|
| - __ Lsl(result, left, right);
|
| + __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
|
| + __ Lsl(result, left, IP);
|
| }
|
| } else {
|
| if (right_needs_check) {
|
| @@ -2191,13 +2191,14 @@
|
| }
|
| // Left is not a constant.
|
| // Check if count too large for handling it inlined.
|
| - __ SmiUntag(right);
|
| - // Overflow test (preserve left and right);
|
| - __ Lsl(IP, left, right);
|
| - __ cmp(left, ShifterOperand(IP, ASR, right));
|
| + __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
|
| + // Overflow test (preserve left, right, and IP);
|
| + Register temp = locs.temp(0).reg();
|
| + __ Lsl(temp, left, IP);
|
| + __ cmp(left, ShifterOperand(temp, ASR, IP));
|
| __ b(deopt, NE); // Overflow.
|
| // Shift for result now we know there is no overflow.
|
| - __ Lsl(result, left, right);
|
| + __ Lsl(result, left, IP);
|
| }
|
| }
|
|
|
| @@ -2208,21 +2209,23 @@
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| if (op_kind() == Token::kTRUNCDIV) {
|
| + summary->set_in(0, Location::RequiresRegister());
|
| if (RightIsPowerOfTwoConstant()) {
|
| - summary->set_in(0, Location::RequiresRegister());
|
| ConstantInstr* right_constant = right()->definition()->AsConstant();
|
| summary->set_in(1, Location::Constant(right_constant->value()));
|
| - summary->set_out(Location::RequiresRegister());
|
| } else {
|
| - // Both inputs must be writable because they will be untagged.
|
| - summary->set_in(0, Location::WritableRegister());
|
| - summary->set_in(1, Location::WritableRegister());
|
| - summary->set_out(Location::RequiresRegister());
|
| + summary->set_in(1, Location::RequiresRegister());
|
| }
|
| + summary->AddTemp(Location::RequiresRegister());
|
| + summary->set_out(Location::RequiresRegister());
|
| return summary;
|
| }
|
| summary->set_in(0, Location::RequiresRegister());
|
| summary->set_in(1, Location::RegisterOrSmiConstant(right()));
|
| + if (((op_kind() == Token::kSHL) && !is_truncating()) ||
|
| + (op_kind() == Token::kSHR)) {
|
| + summary->AddTemp(Location::RequiresRegister());
|
| + }
|
| // We make use of 3-operand instructions by not requiring result register
|
| // to be identical to first input register as on Intel.
|
| summary->set_out(Location::RequiresRegister());
|
| @@ -2241,7 +2244,7 @@
|
| Register result = locs()->out().reg();
|
| Label* deopt = NULL;
|
| if (CanDeoptimize()) {
|
| - deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
| + deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
| }
|
|
|
| if (locs()->in(1).IsConstant()) {
|
| @@ -2305,9 +2308,10 @@
|
| ASSERT(kSmiTagSize == 1);
|
| __ mov(IP, ShifterOperand(left, ASR, 31));
|
| ASSERT(shift_count > 1); // 1, -1 case handled above.
|
| - __ add(left, left, ShifterOperand(IP, LSR, 32 - shift_count));
|
| + Register temp = locs()->temp(0).reg();
|
| + __ add(temp, left, ShifterOperand(IP, LSR, 32 - shift_count));
|
| ASSERT(shift_count > 0);
|
| - __ mov(result, ShifterOperand(left, ASR, shift_count));
|
| + __ mov(result, ShifterOperand(temp, ASR, shift_count));
|
| if (value < 0) {
|
| __ rsb(result, result, ShifterOperand(0));
|
| }
|
| @@ -2400,11 +2404,11 @@
|
| break;
|
| }
|
| case Token::kMUL: {
|
| - __ SmiUntag(left);
|
| + __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP.
|
| if (deopt == NULL) {
|
| - __ mul(result, left, right);
|
| + __ mul(result, IP, right);
|
| } else {
|
| - __ smull(result, IP, left, right);
|
| + __ smull(result, IP, IP, right);
|
| // IP: result bits 32..63.
|
| __ cmp(IP, ShifterOperand(result, ASR, 31));
|
| __ b(deopt, NE);
|
| @@ -2430,12 +2434,13 @@
|
| // Handle divide by zero in runtime.
|
| __ cmp(right, ShifterOperand(0));
|
| __ b(deopt, EQ);
|
| - __ SmiUntag(left);
|
| - __ SmiUntag(right);
|
| + Register temp = locs()->temp(0).reg();
|
| + __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
|
| + __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
|
| if (!CPUFeatures::integer_division_supported()) {
|
| UNIMPLEMENTED();
|
| }
|
| - __ sdiv(result, left, right);
|
| + __ sdiv(result, temp, IP);
|
| // Check the corner case of dividing the 'MIN_SMI' with -1, in which
|
| // case we cannot tag the result.
|
| __ CompareImmediate(result, 0x40000000);
|
| @@ -2448,17 +2453,18 @@
|
| __ CompareImmediate(right, 0);
|
| __ b(deopt, LT);
|
| }
|
| - __ SmiUntag(right);
|
| + __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
|
| // sarl operation masks the count to 5 bits.
|
| const intptr_t kCountLimit = 0x1F;
|
| Range* right_range = this->right()->definition()->range();
|
| if ((right_range == NULL) ||
|
| !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
|
| - __ CompareImmediate(right, kCountLimit);
|
| - __ LoadImmediate(right, kCountLimit, GT);
|
| + __ CompareImmediate(IP, kCountLimit);
|
| + __ LoadImmediate(IP, kCountLimit, GT);
|
| }
|
| - __ SmiUntag(left);
|
| - __ Asr(result, left, right);
|
| + Register temp = locs()->temp(0).reg();
|
| + __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
|
| + __ Asr(result, temp, IP);
|
| __ SmiTag(result);
|
| break;
|
| }
|
|
|