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

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 17176004: Fix more register allocation bugs in optimized code on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | tests/language/language.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 2136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 } 2147 }
2148 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2148 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2149 const bool right_needs_check = 2149 const bool right_needs_check =
2150 (right_range == NULL) || 2150 (right_range == NULL) ||
2151 !right_range->IsWithin(0, max_right - 1); 2151 !right_range->IsWithin(0, max_right - 1);
2152 if (right_needs_check) { 2152 if (right_needs_check) {
2153 __ cmp(right, 2153 __ cmp(right,
2154 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right)))); 2154 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right))));
2155 __ b(deopt, CS); 2155 __ b(deopt, CS);
2156 } 2156 }
2157 __ SmiUntag(right); 2157 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
2158 __ Lsl(result, left, right); 2158 __ Lsl(result, left, IP);
2159 } 2159 }
2160 return; 2160 return;
2161 } 2161 }
2162 2162
2163 const bool right_needs_check = 2163 const bool right_needs_check =
2164 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 2164 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2165 if (is_truncating) { 2165 if (is_truncating) {
2166 if (right_needs_check) { 2166 if (right_needs_check) {
2167 const bool right_may_be_negative = 2167 const bool right_may_be_negative =
2168 (right_range == NULL) || 2168 (right_range == NULL) ||
2169 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); 2169 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
2170 if (right_may_be_negative) { 2170 if (right_may_be_negative) {
2171 ASSERT(shift_left->CanDeoptimize()); 2171 ASSERT(shift_left->CanDeoptimize());
2172 __ cmp(right, ShifterOperand(0)); 2172 __ cmp(right, ShifterOperand(0));
2173 __ b(deopt, MI); 2173 __ b(deopt, MI);
2174 } 2174 }
2175 2175
2176 __ cmp(right, 2176 __ cmp(right,
2177 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 2177 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2178 __ mov(result, ShifterOperand(0), CS); 2178 __ mov(result, ShifterOperand(0), CS);
2179 __ SmiUntag(right, CC); 2179 __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC.
2180 __ Lsl(result, left, right, CC); 2180 __ Lsl(result, left, IP, CC);
2181 } else { 2181 } else {
2182 __ SmiUntag(right); 2182 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
2183 __ Lsl(result, left, right); 2183 __ Lsl(result, left, IP);
2184 } 2184 }
2185 } else { 2185 } else {
2186 if (right_needs_check) { 2186 if (right_needs_check) {
2187 ASSERT(shift_left->CanDeoptimize()); 2187 ASSERT(shift_left->CanDeoptimize());
2188 __ cmp(right, 2188 __ cmp(right,
2189 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 2189 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2190 __ b(deopt, CS); 2190 __ b(deopt, CS);
2191 } 2191 }
2192 // Left is not a constant. 2192 // Left is not a constant.
2193 // Check if count too large for handling it inlined. 2193 // Check if count too large for handling it inlined.
2194 __ SmiUntag(right); 2194 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
2195 // Overflow test (preserve left and right); 2195 // Overflow test (preserve left, right, and IP);
2196 __ Lsl(IP, left, right); 2196 Register temp = locs.temp(0).reg();
2197 __ cmp(left, ShifterOperand(IP, ASR, right)); 2197 __ Lsl(temp, left, IP);
2198 __ cmp(left, ShifterOperand(temp, ASR, IP));
2198 __ b(deopt, NE); // Overflow. 2199 __ b(deopt, NE); // Overflow.
2199 // Shift for result now we know there is no overflow. 2200 // Shift for result now we know there is no overflow.
2200 __ Lsl(result, left, right); 2201 __ Lsl(result, left, IP);
2201 } 2202 }
2202 } 2203 }
2203 2204
2204 2205
2205 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2206 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
2206 const intptr_t kNumInputs = 2; 2207 const intptr_t kNumInputs = 2;
2207 const intptr_t kNumTemps = 0; 2208 const intptr_t kNumTemps = 0;
2208 LocationSummary* summary = 2209 LocationSummary* summary =
2209 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2210 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2210 if (op_kind() == Token::kTRUNCDIV) { 2211 if (op_kind() == Token::kTRUNCDIV) {
2212 summary->set_in(0, Location::RequiresRegister());
2211 if (RightIsPowerOfTwoConstant()) { 2213 if (RightIsPowerOfTwoConstant()) {
2212 summary->set_in(0, Location::RequiresRegister());
2213 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2214 ConstantInstr* right_constant = right()->definition()->AsConstant();
2214 summary->set_in(1, Location::Constant(right_constant->value())); 2215 summary->set_in(1, Location::Constant(right_constant->value()));
2215 summary->set_out(Location::RequiresRegister());
2216 } else { 2216 } else {
2217 // Both inputs must be writable because they will be untagged. 2217 summary->set_in(1, Location::RequiresRegister());
2218 summary->set_in(0, Location::WritableRegister());
2219 summary->set_in(1, Location::WritableRegister());
2220 summary->set_out(Location::RequiresRegister());
2221 } 2218 }
2219 summary->AddTemp(Location::RequiresRegister());
2220 summary->set_out(Location::RequiresRegister());
2222 return summary; 2221 return summary;
2223 } 2222 }
2224 summary->set_in(0, Location::RequiresRegister()); 2223 summary->set_in(0, Location::RequiresRegister());
2225 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2224 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
2225 if (((op_kind() == Token::kSHL) && !is_truncating()) ||
2226 (op_kind() == Token::kSHR)) {
2227 summary->AddTemp(Location::RequiresRegister());
2228 }
2226 // We make use of 3-operand instructions by not requiring result register 2229 // We make use of 3-operand instructions by not requiring result register
2227 // to be identical to first input register as on Intel. 2230 // to be identical to first input register as on Intel.
2228 summary->set_out(Location::RequiresRegister()); 2231 summary->set_out(Location::RequiresRegister());
2229 return summary; 2232 return summary;
2230 } 2233 }
2231 2234
2232 2235
2233 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2236 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2234 if (op_kind() == Token::kSHL) { 2237 if (op_kind() == Token::kSHL) {
2235 EmitSmiShiftLeft(compiler, this); 2238 EmitSmiShiftLeft(compiler, this);
2236 return; 2239 return;
2237 } 2240 }
2238 2241
2239 ASSERT(!is_truncating()); 2242 ASSERT(!is_truncating());
2240 Register left = locs()->in(0).reg(); 2243 Register left = locs()->in(0).reg();
2241 Register result = locs()->out().reg(); 2244 Register result = locs()->out().reg();
2242 Label* deopt = NULL; 2245 Label* deopt = NULL;
2243 if (CanDeoptimize()) { 2246 if (CanDeoptimize()) {
2244 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); 2247 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
2245 } 2248 }
2246 2249
2247 if (locs()->in(1).IsConstant()) { 2250 if (locs()->in(1).IsConstant()) {
2248 const Object& constant = locs()->in(1).constant(); 2251 const Object& constant = locs()->in(1).constant();
2249 ASSERT(constant.IsSmi()); 2252 ASSERT(constant.IsSmi());
2250 int32_t imm = reinterpret_cast<int32_t>(constant.raw()); 2253 int32_t imm = reinterpret_cast<int32_t>(constant.raw());
2251 switch (op_kind()) { 2254 switch (op_kind()) {
2252 case Token::kSUB: { 2255 case Token::kSUB: {
2253 imm = -imm; // TODO(regis): What if deopt != NULL && imm == 0x80000000? 2256 imm = -imm; // TODO(regis): What if deopt != NULL && imm == 0x80000000?
2254 // Fall through. 2257 // Fall through.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2298 __ b(deopt, EQ); 2301 __ b(deopt, EQ);
2299 __ rsb(result, left, ShifterOperand(0)); 2302 __ rsb(result, left, ShifterOperand(0));
2300 break; 2303 break;
2301 } 2304 }
2302 ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value))); 2305 ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
2303 const intptr_t shift_count = 2306 const intptr_t shift_count =
2304 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; 2307 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2305 ASSERT(kSmiTagSize == 1); 2308 ASSERT(kSmiTagSize == 1);
2306 __ mov(IP, ShifterOperand(left, ASR, 31)); 2309 __ mov(IP, ShifterOperand(left, ASR, 31));
2307 ASSERT(shift_count > 1); // 1, -1 case handled above. 2310 ASSERT(shift_count > 1); // 1, -1 case handled above.
2308 __ add(left, left, ShifterOperand(IP, LSR, 32 - shift_count)); 2311 Register temp = locs()->temp(0).reg();
2312 __ add(temp, left, ShifterOperand(IP, LSR, 32 - shift_count));
2309 ASSERT(shift_count > 0); 2313 ASSERT(shift_count > 0);
2310 __ mov(result, ShifterOperand(left, ASR, shift_count)); 2314 __ mov(result, ShifterOperand(temp, ASR, shift_count));
2311 if (value < 0) { 2315 if (value < 0) {
2312 __ rsb(result, result, ShifterOperand(0)); 2316 __ rsb(result, result, ShifterOperand(0));
2313 } 2317 }
2314 __ SmiTag(result); 2318 __ SmiTag(result);
2315 break; 2319 break;
2316 } 2320 }
2317 case Token::kBIT_AND: { 2321 case Token::kBIT_AND: {
2318 // No overflow check. 2322 // No overflow check.
2319 ShifterOperand shifter_op; 2323 ShifterOperand shifter_op;
2320 if (ShifterOperand::CanHold(imm, &shifter_op)) { 2324 if (ShifterOperand::CanHold(imm, &shifter_op)) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2393 case Token::kSUB: { 2397 case Token::kSUB: {
2394 if (deopt == NULL) { 2398 if (deopt == NULL) {
2395 __ sub(result, left, ShifterOperand(right)); 2399 __ sub(result, left, ShifterOperand(right));
2396 } else { 2400 } else {
2397 __ subs(result, left, ShifterOperand(right)); 2401 __ subs(result, left, ShifterOperand(right));
2398 __ b(deopt, VS); 2402 __ b(deopt, VS);
2399 } 2403 }
2400 break; 2404 break;
2401 } 2405 }
2402 case Token::kMUL: { 2406 case Token::kMUL: {
2403 __ SmiUntag(left); 2407 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP.
2404 if (deopt == NULL) { 2408 if (deopt == NULL) {
2405 __ mul(result, left, right); 2409 __ mul(result, IP, right);
2406 } else { 2410 } else {
2407 __ smull(result, IP, left, right); 2411 __ smull(result, IP, IP, right);
2408 // IP: result bits 32..63. 2412 // IP: result bits 32..63.
2409 __ cmp(IP, ShifterOperand(result, ASR, 31)); 2413 __ cmp(IP, ShifterOperand(result, ASR, 31));
2410 __ b(deopt, NE); 2414 __ b(deopt, NE);
2411 } 2415 }
2412 break; 2416 break;
2413 } 2417 }
2414 case Token::kBIT_AND: { 2418 case Token::kBIT_AND: {
2415 // No overflow check. 2419 // No overflow check.
2416 __ and_(result, left, ShifterOperand(right)); 2420 __ and_(result, left, ShifterOperand(right));
2417 break; 2421 break;
2418 } 2422 }
2419 case Token::kBIT_OR: { 2423 case Token::kBIT_OR: {
2420 // No overflow check. 2424 // No overflow check.
2421 __ orr(result, left, ShifterOperand(right)); 2425 __ orr(result, left, ShifterOperand(right));
2422 break; 2426 break;
2423 } 2427 }
2424 case Token::kBIT_XOR: { 2428 case Token::kBIT_XOR: {
2425 // No overflow check. 2429 // No overflow check.
2426 __ eor(result, left, ShifterOperand(right)); 2430 __ eor(result, left, ShifterOperand(right));
2427 break; 2431 break;
2428 } 2432 }
2429 case Token::kTRUNCDIV: { 2433 case Token::kTRUNCDIV: {
2430 // Handle divide by zero in runtime. 2434 // Handle divide by zero in runtime.
2431 __ cmp(right, ShifterOperand(0)); 2435 __ cmp(right, ShifterOperand(0));
2432 __ b(deopt, EQ); 2436 __ b(deopt, EQ);
2433 __ SmiUntag(left); 2437 Register temp = locs()->temp(0).reg();
2434 __ SmiUntag(right); 2438 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
2439 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
2435 if (!CPUFeatures::integer_division_supported()) { 2440 if (!CPUFeatures::integer_division_supported()) {
2436 UNIMPLEMENTED(); 2441 UNIMPLEMENTED();
2437 } 2442 }
2438 __ sdiv(result, left, right); 2443 __ sdiv(result, temp, IP);
2439 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 2444 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2440 // case we cannot tag the result. 2445 // case we cannot tag the result.
2441 __ CompareImmediate(result, 0x40000000); 2446 __ CompareImmediate(result, 0x40000000);
2442 __ b(deopt, EQ); 2447 __ b(deopt, EQ);
2443 __ SmiTag(result); 2448 __ SmiTag(result);
2444 break; 2449 break;
2445 } 2450 }
2446 case Token::kSHR: { 2451 case Token::kSHR: {
2447 if (CanDeoptimize()) { 2452 if (CanDeoptimize()) {
2448 __ CompareImmediate(right, 0); 2453 __ CompareImmediate(right, 0);
2449 __ b(deopt, LT); 2454 __ b(deopt, LT);
2450 } 2455 }
2451 __ SmiUntag(right); 2456 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
2452 // sarl operation masks the count to 5 bits. 2457 // sarl operation masks the count to 5 bits.
2453 const intptr_t kCountLimit = 0x1F; 2458 const intptr_t kCountLimit = 0x1F;
2454 Range* right_range = this->right()->definition()->range(); 2459 Range* right_range = this->right()->definition()->range();
2455 if ((right_range == NULL) || 2460 if ((right_range == NULL) ||
2456 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2461 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2457 __ CompareImmediate(right, kCountLimit); 2462 __ CompareImmediate(IP, kCountLimit);
2458 __ LoadImmediate(right, kCountLimit, GT); 2463 __ LoadImmediate(IP, kCountLimit, GT);
2459 } 2464 }
2460 __ SmiUntag(left); 2465 Register temp = locs()->temp(0).reg();
2461 __ Asr(result, left, right); 2466 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
2467 __ Asr(result, temp, IP);
2462 __ SmiTag(result); 2468 __ SmiTag(result);
2463 break; 2469 break;
2464 } 2470 }
2465 case Token::kDIV: { 2471 case Token::kDIV: {
2466 // Dispatches to 'Double./'. 2472 // Dispatches to 'Double./'.
2467 // TODO(srdjan): Implement as conversion to double and double division. 2473 // TODO(srdjan): Implement as conversion to double and double division.
2468 UNREACHABLE(); 2474 UNREACHABLE();
2469 break; 2475 break;
2470 } 2476 }
2471 case Token::kMOD: { 2477 case Token::kMOD: {
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3612 compiler->GenerateCall(token_pos(), 3618 compiler->GenerateCall(token_pos(),
3613 &label, 3619 &label,
3614 PcDescriptors::kOther, 3620 PcDescriptors::kOther,
3615 locs()); 3621 locs());
3616 __ Drop(2); // Discard type arguments and receiver. 3622 __ Drop(2); // Discard type arguments and receiver.
3617 } 3623 }
3618 3624
3619 } // namespace dart 3625 } // namespace dart
3620 3626
3621 #endif // defined TARGET_ARCH_ARM 3627 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698