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

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

Issue 564843002: Initial steps towards cleaning up integer arithmetic IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 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
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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cpu.h" 8 #include "vm/cpu.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_allocator.h" 10 #include "vm/flow_graph_allocator.h"
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 295
296 296
297 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const { 297 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const {
298 MathMinMaxInstr* other_op = other->AsMathMinMax(); 298 MathMinMaxInstr* other_op = other->AsMathMinMax();
299 ASSERT(other_op != NULL); 299 ASSERT(other_op != NULL);
300 return (op_kind() == other_op->op_kind()) && 300 return (op_kind() == other_op->op_kind()) &&
301 (result_cid() == other_op->result_cid()); 301 (result_cid() == other_op->result_cid());
302 } 302 }
303 303
304 304
305 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const { 305 bool BinaryIntegerOpInstr::AttributesEqual(Instruction* other) const {
306 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); 306 ASSERT(other->tag() == tag());
307 ASSERT(other_op != NULL); 307 BinaryIntegerOpInstr* other_op = static_cast<BinaryIntegerOpInstr*>(other);
srdjan 2014/09/11 17:38:11 other->AsBinary... ?
308 return (op_kind() == other_op->op_kind()) && 308 return (op_kind() == other_op->op_kind()) &&
309 (overflow_ == other_op->overflow_) && 309 (can_overflow() == other_op->can_overflow()) &&
310 (is_truncating_ == other_op->is_truncating_); 310 (is_truncating() == other_op->is_truncating());
311 } 311 }
312 312
313 313
314 bool BinaryInt32OpInstr::AttributesEqual(Instruction* other) const {
315 BinaryInt32OpInstr* other_op = other->AsBinaryInt32Op();
316 ASSERT(other_op != NULL);
317 return (op_kind() == other_op->op_kind()) &&
318 (overflow_ == other_op->overflow_) &&
319 (is_truncating_ == other_op->is_truncating_);
320 }
321
322
323 EffectSet LoadFieldInstr::Dependencies() const { 314 EffectSet LoadFieldInstr::Dependencies() const {
324 return immutable_ ? EffectSet::None() : EffectSet::All(); 315 return immutable_ ? EffectSet::None() : EffectSet::All();
325 } 316 }
326 317
327 318
328 bool LoadFieldInstr::AttributesEqual(Instruction* other) const { 319 bool LoadFieldInstr::AttributesEqual(Instruction* other) const {
329 LoadFieldInstr* other_load = other->AsLoadField(); 320 LoadFieldInstr* other_load = other->AsLoadField();
330 ASSERT(other_load != NULL); 321 ASSERT(other_load != NULL);
331 if (field() != NULL) { 322 if (field() != NULL) {
332 return (other_load->field() != NULL) && 323 return (other_load->field() != NULL) &&
(...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 return false; 1193 return false;
1203 1194
1204 case Token::kSHL: 1195 case Token::kSHL:
1205 return true; 1196 return true;
1206 1197
1207 case Token::kMOD: { 1198 case Token::kMOD: {
1208 UNREACHABLE(); 1199 UNREACHABLE();
1209 } 1200 }
1210 1201
1211 default: 1202 default:
1212 return overflow_; 1203 return can_overflow();
1213 } 1204 }
1214 } 1205 }
1215 1206
1216 1207
1217 bool BinarySmiOpInstr::CanDeoptimize() const { 1208 bool BinarySmiOpInstr::CanDeoptimize() const {
1218 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) { 1209 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) {
1219 // If Smi's are bigger than 32-bits, then the instruction could deoptimize 1210 // If Smi's are bigger than 32-bits, then the instruction could deoptimize
1220 // if the result is too big. 1211 // if the result is too big.
1221 return true; 1212 return true;
1222 } 1213 }
1223 switch (op_kind()) { 1214 switch (op_kind()) {
1224 case Token::kBIT_AND: 1215 case Token::kBIT_AND:
1225 case Token::kBIT_OR: 1216 case Token::kBIT_OR:
1226 case Token::kBIT_XOR: 1217 case Token::kBIT_XOR:
1227 return false; 1218 return false;
1228 case Token::kSHR: { 1219 case Token::kSHR: {
1229 // Can't deopt if shift-count is known positive. 1220 // Can't deopt if shift-count is known positive.
1230 Range* right_range = this->right()->definition()->range(); 1221 Range* right_range = this->right()->definition()->range();
1231 return (right_range == NULL) || !right_range->IsPositive(); 1222 return (right_range == NULL) || !right_range->IsPositive();
1232 } 1223 }
1233 case Token::kSHL: { 1224 case Token::kSHL: {
1234 Range* right_range = this->right()->definition()->range(); 1225 Range* right_range = this->right()->definition()->range();
1235 if ((right_range != NULL) && IsTruncating()) { 1226 if ((right_range != NULL) && !can_overflow()) {
1236 // Can deoptimize if right can be negative. 1227 // Can deoptimize if right can be negative.
1237 return !right_range->IsPositive(); 1228 return !right_range->IsPositive();
1238 } 1229 }
1239 return true; 1230 return true;
1240 } 1231 }
1241 case Token::kMOD: { 1232 case Token::kMOD: {
1242 Range* right_range = this->right()->definition()->range(); 1233 Range* right_range = this->right()->definition()->range();
1243 return (right_range == NULL) || right_range->Overlaps(0, 0); 1234 return (right_range == NULL) || right_range->Overlaps(0, 0);
1244 } 1235 }
1245 default: 1236 default:
1246 return overflow_; 1237 return can_overflow();
1247 } 1238 }
1248 } 1239 }
1249 1240
1250 1241
1251 bool BinarySmiOpInstr::RightIsPowerOfTwoConstant() const { 1242 bool BinaryIntegerOpInstr::RightIsPowerOfTwoConstant() const {
1252 if (!right()->definition()->IsConstant()) return false; 1243 if (!right()->definition()->IsConstant()) return false;
1253 const Object& constant = right()->definition()->AsConstant()->value(); 1244 const Object& constant = right()->definition()->AsConstant()->value();
1254 if (!constant.IsSmi()) return false; 1245 if (!constant.IsSmi()) return false;
1255 const intptr_t int_value = Smi::Cast(constant).Value(); 1246 const intptr_t int_value = Smi::Cast(constant).Value();
1256 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); 1247 return Utils::IsPowerOfTwo(Utils::Abs(int_value));
1257 } 1248 }
1258 1249
1259 1250
1251
srdjan 2014/09/11 17:38:11 Two lines instead of three
1260 static bool ToIntegerConstant(Value* value, int64_t* result) { 1252 static bool ToIntegerConstant(Value* value, int64_t* result) {
1261 if (!value->BindsToConstant()) { 1253 if (!value->BindsToConstant()) {
1262 if (value->definition()->IsUnboxDouble()) { 1254 if (value->definition()->IsUnboxDouble()) {
1263 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), 1255 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(),
1264 result); 1256 result);
1265 } 1257 }
1266 return false; 1258 return false;
1267 } 1259 }
1268 1260
1269 const Object& constant = value->BoundConstant(); 1261 const Object& constant = value->BoundConstant();
1270 if (constant.IsDouble()) { 1262 if (constant.IsDouble()) {
1271 const Double& double_constant = Double::Cast(constant); 1263 const Double& double_constant = Double::Cast(constant);
1272 *result = static_cast<int64_t>(double_constant.value()); 1264 *result = static_cast<int64_t>(double_constant.value());
1273 return (static_cast<double>(*result) == double_constant.value()); 1265 return (static_cast<double>(*result) == double_constant.value());
1274 } else if (constant.IsSmi()) { 1266 } else if (constant.IsSmi()) {
1275 *result = Smi::Cast(constant).Value(); 1267 *result = Smi::Cast(constant).Value();
1276 return true; 1268 return true;
1277 } else if (constant.IsMint()) { 1269 } else if (constant.IsMint()) {
1278 *result = Mint::Cast(constant).value(); 1270 *result = Mint::Cast(constant).value();
1279 return true; 1271 return true;
1280 } 1272 }
1281 1273
1282 return false; 1274 return false;
1283 } 1275 }
1284 1276
1285 1277
1286 static Definition* CanonicalizeCommutativeArithmetic( 1278 static Definition* CanonicalizeCommutativeDoubleArithmetic(
1287 Token::Kind op, 1279 Token::Kind op,
1288 intptr_t cid,
1289 Value* left, 1280 Value* left,
1290 Value* right, 1281 Value* right) {
1291 int64_t mask = static_cast<int64_t>(0xFFFFFFFFFFFFFFFFLL)) {
1292 ASSERT((cid == kSmiCid) || (cid == kDoubleCid) || (cid == kMintCid));
1293
1294 int64_t left_value; 1282 int64_t left_value;
1295 if (!ToIntegerConstant(left, &left_value)) { 1283 if (!ToIntegerConstant(left, &left_value)) {
1296 return NULL; 1284 return NULL;
1297 } 1285 }
1298 1286
1299 // Apply truncation mask to left_value. 1287 // Can't apply 0.0 * x -> 0.0 equivalence to double operation because
1300 left_value &= mask; 1288 // 0.0 * NaN is NaN not 0.0.
1301 1289 // Can't apply 0.0 + x -> x to double because 0.0 + (-0.0) is 0.0 not -0.0.
1302 switch (op) { 1290 switch (op) {
1303 case Token::kMUL: 1291 case Token::kMUL:
1304 if (left_value == 1) { 1292 if (left_value == 1) {
1305 if ((cid == kDoubleCid) && 1293 if (right->definition()->representation() != kUnboxedDouble) {
1306 (right->definition()->representation() != kUnboxedDouble)) {
1307 // Can't yet apply the equivalence because representation selection 1294 // Can't yet apply the equivalence because representation selection
1308 // did not run yet. We need it to guarantee that right value is 1295 // did not run yet. We need it to guarantee that right value is
1309 // correctly coerced to double. The second canonicalization pass 1296 // correctly coerced to double. The second canonicalization pass
1310 // will apply this equivalence. 1297 // will apply this equivalence.
1311 return NULL; 1298 return NULL;
1312 } else { 1299 } else {
1313 return right->definition(); 1300 return right->definition();
1314 } 1301 }
1315 } else if ((left_value == 0) && (cid != kDoubleCid)) {
1316 // Can't apply this equivalence to double operation because
1317 // 0.0 * NaN is NaN not 0.0.
1318 return left->definition();
1319 }
1320 break;
1321 case Token::kADD:
1322 if ((left_value == 0) && (cid != kDoubleCid)) {
1323 // Can't apply this equivalence to double operations because
1324 // 0.0 + (-0.0) is 0.0 not -0.0.
1325 return right->definition();
1326 }
1327 break;
1328 case Token::kBIT_AND:
1329 ASSERT(cid != kDoubleCid);
1330 if (left_value == 0) {
1331 return left->definition();
1332 } else if (left_value == mask) {
1333 return right->definition();
1334 }
1335 break;
1336 case Token::kBIT_OR:
1337 ASSERT(cid != kDoubleCid);
1338 if (left_value == 0) {
1339 return right->definition();
1340 } else if (left_value == mask) {
1341 return left->definition();
1342 }
1343 break;
1344 case Token::kBIT_XOR:
1345 ASSERT(cid != kDoubleCid);
1346 if (left_value == 0) {
1347 return right->definition();
1348 } 1302 }
1349 break; 1303 break;
1350 default: 1304 default:
1351 break; 1305 break;
1352 } 1306 }
1353 1307
1354 return NULL; 1308 return NULL;
1355 } 1309 }
1356 1310
1357 1311
(...skipping 24 matching lines...) Expand all
1382 Definition* FloatToDoubleInstr::Canonicalize(FlowGraph* flow_graph) { 1336 Definition* FloatToDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
1383 return HasUses() ? this : NULL; 1337 return HasUses() ? this : NULL;
1384 } 1338 }
1385 1339
1386 1340
1387 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) { 1341 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) {
1388 if (!HasUses()) return NULL; 1342 if (!HasUses()) return NULL;
1389 1343
1390 Definition* result = NULL; 1344 Definition* result = NULL;
1391 1345
1392 result = CanonicalizeCommutativeArithmetic(op_kind(), 1346 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), left(), right());
1393 kDoubleCid,
1394 left(),
1395 right());
1396 if (result == NULL) {
1397 result = CanonicalizeCommutativeArithmetic(op_kind(),
1398 kDoubleCid,
1399 right(),
1400 left());
1401 }
1402 if (result != NULL) { 1347 if (result != NULL) {
1403 return result; 1348 return result;
1404 } 1349 }
1350
1351 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), right(), left());
1352 if (result != NULL) {
1353 return result;
1354 }
1405 1355
1406 if ((op_kind() == Token::kMUL) && 1356 if ((op_kind() == Token::kMUL) &&
1407 (left()->definition() == right()->definition())) { 1357 (left()->definition() == right()->definition())) {
1408 MathUnaryInstr* math_unary = 1358 MathUnaryInstr* math_unary =
1409 new MathUnaryInstr(MathUnaryInstr::kDoubleSquare, 1359 new MathUnaryInstr(MathUnaryInstr::kDoubleSquare,
1410 new Value(left()->definition()), 1360 new Value(left()->definition()),
1411 DeoptimizationTarget()); 1361 DeoptimizationTarget());
1412 flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue); 1362 flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue);
1413 return math_unary; 1363 return math_unary;
1414 } 1364 }
1415 1365
1416 return this; 1366 return this;
1417 } 1367 }
1418 1368
1419 1369
1420 Definition* BinarySmiOpInstr::Canonicalize(FlowGraph* flow_graph) { 1370 static bool IsCommutative(Token::Kind op) {
1421 Definition* result = NULL; 1371 switch (op) {
1422 1372 case Token::kMUL:
1423 result = CanonicalizeCommutativeArithmetic(op_kind(), 1373 case Token::kADD:
1424 kSmiCid, 1374 case Token::kBIT_AND:
1425 left(), 1375 case Token::kBIT_OR:
1426 right()); 1376 case Token::kBIT_XOR:
1427 if (result != NULL) { 1377 return true;
1428 return result; 1378 default:
1429 } 1379 return false;
1430 1380 }
1431 result = CanonicalizeCommutativeArithmetic(op_kind(), 1381 }
1432 kSmiCid, 1382
1433 right(), 1383
1434 left()); 1384 static intptr_t RepresentationBits(Representation r) {
1435 if (result != NULL) { 1385 switch (r) {
1436 return result; 1386 case kTagged:
1387 return kBitsPerWord - 1;
1388 case kUnboxedInt32:
1389 case kUnboxedUint32:
1390 return 32;
1391 case kUnboxedMint:
1392 return 64;
1393 default:
1394 UNREACHABLE();
1395 return 0;
1396 }
1397 }
1398
1399
1400 static int64_t RepresentationMask(Representation r) {
1401 return static_cast<int64_t>(
1402 static_cast<uint64_t>(-1) >> (64 - RepresentationBits(r)));
srdjan 2014/09/11 17:38:11 4 spaces indent
1403 }
1404
1405
1406 UnaryIntegerOpInstr* UnaryIntegerOpInstr::Make(Representation representation,
1407 Token::Kind op_kind,
1408 Value* value,
1409 intptr_t deopt_id,
1410 Range* range) {
1411 UnaryIntegerOpInstr* op = NULL;
1412 switch (representation) {
1413 case kTagged:
1414 op = new UnarySmiOpInstr(op_kind, value, deopt_id);
1415 break;
1416
Cutch 2014/09/11 17:41:53 remove blank lines
1417 case kUnboxedInt32:
1418 return NULL;
1419
1420 case kUnboxedUint32:
1421 op = new UnaryUint32OpInstr(op_kind, value, deopt_id);
1422 break;
1423
1424 case kUnboxedMint:
1425 op = new UnaryMintOpInstr(op_kind, value, deopt_id);
1426 break;
1427
1428 default:
1429 UNREACHABLE();
1430 return NULL;
1431 }
1432
1433 if (op == NULL) {
1434 return op;
1435 }
srdjan 2014/09/11 17:38:11 Instead you could add return NULL to default (remo
Vyacheslav Egorov (Google) 2014/09/11 19:50:47 I would like to ensure that we don't forget to upd
1436
1437 if (!Range::IsUnknown(range)) {
1438 op->set_range(*range);
1439 }
1440
1441 ASSERT(op->representation() == representation);
1442 return op;
1443 }
1444
1445
1446 BinaryIntegerOpInstr* BinaryIntegerOpInstr::Make(Representation representation,
1447 Token::Kind op_kind,
1448 Value* left,
1449 Value* right,
1450 intptr_t deopt_id,
1451 bool can_overflow,
1452 bool is_truncating,
1453 Range* range) {
1454 BinaryIntegerOpInstr* op = NULL;
1455 switch (representation) {
1456 case kTagged:
1457 op = new BinarySmiOpInstr(op_kind, left, right, deopt_id);
1458 break;
1459
Cutch 2014/09/11 17:41:53 ditto
1460 case kUnboxedInt32:
1461 if (!BinaryInt32OpInstr::IsSupported(op_kind, left, right)) {
1462 return NULL;
1463 }
1464 op = new BinaryInt32OpInstr(op_kind, left, right, deopt_id);
1465 break;
1466
1467 case kUnboxedUint32:
1468 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
1469 op = new ShiftUint32OpInstr(op_kind, left, right, deopt_id);
1470 } else {
1471 op = new BinaryUint32OpInstr(op_kind, left, right, deopt_id);
1472 }
1473 break;
1474
1475 case kUnboxedMint:
1476 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
1477 op = new ShiftMintOpInstr(op_kind, left, right, deopt_id);
1478 } else {
1479 op = new BinaryMintOpInstr(op_kind, left, right, deopt_id);
1480 }
1481 break;
1482
1483 default:
1484 UNREACHABLE();
1485 return NULL;
1486 }
1487
1488 if (!Range::IsUnknown(range)) {
1489 op->set_range(*range);
1490 }
1491
1492 op->set_can_overflow(can_overflow);
1493 if (is_truncating) {
1494 op->mark_truncating();
1495 }
1496
1497 ASSERT(op->representation() == representation);
1498 return op;
1499 }
1500
1501
1502 RawInteger* BinaryIntegerOpInstr::Evaluate(const Integer& left,
1503 const Integer& right) const {
1504 Integer& result = Integer::Handle();
1505
1506 switch (op_kind()) {
1507 case Token::kTRUNCDIV:
1508 case Token::kMOD:
1509 // Check right value for zero.
1510 if (right.AsInt64Value() == 0) {
1511 break; // Will throw.
1512 }
1513 // Fall through.
1514 case Token::kADD:
1515 case Token::kSUB:
1516 case Token::kMUL: {
1517 result = left.ArithmeticOp(op_kind(), right);
1518 break;
1519 }
1520 case Token::kSHL:
1521 case Token::kSHR:
1522 if (left.IsSmi() && right.IsSmi() && (Smi::Cast(right).Value() >= 0)) {
1523 result = Smi::Cast(left).ShiftOp(op_kind(), Smi::Cast(right));
1524 }
1525 break;
1526 case Token::kBIT_AND:
1527 case Token::kBIT_OR:
1528 case Token::kBIT_XOR: {
1529 result = left.BitOp(op_kind(), right);
1530 break;
1531 }
1532 case Token::kDIV:
1533 break;
1534 default:
1535 UNREACHABLE();
1536 }
1537
1538 if (!result.IsNull()) {
1539 if (is_truncating()) {
1540 int64_t truncated = result.AsTruncatedInt64Value();
1541 truncated &= RepresentationMask(representation());
1542 result = Integer::New(truncated);
1543 }
1544 result ^= result.CheckAndCanonicalize(NULL);
1545 }
1546
1547 return result.raw();
1548 }
1549
1550
1551 Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
1552 // If both operands are constants evaluate this expression. Might
1553 // occur due to load forwarding after constant propagation pass
1554 // have already been run.
1555 if (left()->BindsToConstant() &&
1556 left()->BoundConstant().IsInteger() &&
1557 right()->BindsToConstant() &&
1558 right()->BoundConstant().IsInteger()) {
1559 const Integer& result = Integer::Handle(
1560 Evaluate(Integer::Cast(left()->BoundConstant()),
1561 Integer::Cast(right()->BoundConstant())));
1562 if (!result.IsNull()) {
1563 return flow_graph->GetConstant(result);
1564 }
1565 }
1566
1567 if (left()->BindsToConstant() &&
1568 !right()->BindsToConstant() &&
1569 IsCommutative(op_kind())) {
1570 Value* l = left();
1571 Value* r = right();
1572 SetInputAt(0, r);
1573 SetInputAt(1, l);
1574 }
1575
1576 int64_t rhs;
1577 if (!ToIntegerConstant(right(), &rhs)) {
1578 return this;
1579 }
1580
1581 const int64_t range_mask = RepresentationMask(representation());
1582 if (is_truncating()) {
1583 switch (op_kind()) {
1584 case Token::kMUL:
1585 case Token::kSUB:
1586 case Token::kADD:
1587 case Token::kBIT_AND:
1588 case Token::kBIT_OR:
1589 case Token::kBIT_XOR:
1590 rhs = (rhs & range_mask);
1591 break;
1592 default:
1593 break;
1594 }
1595 }
1596
1597 switch (op_kind()) {
1598 case Token::kMUL:
1599 if (rhs == 1) {
1600 return left()->definition();
1601 } else if (rhs == 0) {
1602 return right()->definition();
1603 } else if (rhs == 2) {
1604 ConstantInstr* constant_1 =
1605 flow_graph->GetConstant(Smi::Handle(Smi::New(1)));
1606 BinaryIntegerOpInstr* shift =
1607 BinaryIntegerOpInstr::Make(representation(),
1608 Token::kSHL,
1609 left()->CopyWithType(),
1610 new Value(constant_1),
1611 deopt_id_,
1612 can_overflow(),
1613 is_truncating(),
1614 range());
1615 if (shift != NULL) {
1616 flow_graph->InsertBefore(this, shift, env(), FlowGraph::kValue);
1617 return shift;
1618 }
1619 }
1620
1621 break;
1622 case Token::kADD:
1623 if (rhs == 0) {
1624 return left()->definition();
1625 }
1626 break;
1627 case Token::kBIT_AND:
1628 if (rhs == 0) {
1629 return right()->definition();
1630 } else if (rhs == range_mask) {
1631 return left()->definition();
1632 }
1633 break;
1634 case Token::kBIT_OR:
1635 if (rhs == 0) {
1636 return left()->definition();
1637 } else if (rhs == range_mask) {
1638 return right()->definition();
1639 }
1640 break;
1641 case Token::kBIT_XOR:
1642 if (rhs == 0) {
1643 return left()->definition();
1644 } else if (rhs == range_mask) {
1645 UnaryIntegerOpInstr* bit_not =
1646 UnaryIntegerOpInstr::Make(representation(),
1647 Token::kBIT_NOT,
1648 left()->CopyWithType(),
1649 deopt_id_,
1650 range());
1651 if (bit_not != NULL) {
1652 flow_graph->InsertBefore(this, bit_not, env(), FlowGraph::kValue);
1653 return bit_not;
1654 }
1655 }
1656 break;
1657
1658 case Token::kSUB:
1659 if (rhs == 0) {
1660 return left()->definition();
1661 }
1662 break;
1663
1664 case Token::kTRUNCDIV:
1665 if (rhs == 1) {
1666 return left()->definition();
1667 } else if (rhs == -1) {
1668 UnaryIntegerOpInstr* negation =
1669 UnaryIntegerOpInstr::Make(representation(),
1670 Token::kNEGATE,
1671 left()->CopyWithType(),
1672 deopt_id_,
1673 range());
1674 if (negation != NULL) {
1675 flow_graph->InsertBefore(this, negation, env(), FlowGraph::kValue);
1676 return negation;
1677 }
1678 }
1679 break;
1680
1681 case Token::kSHR:
1682 if (rhs == 0) {
1683 return left()->definition();
1684 } else if (rhs < 0) {
1685 DeoptimizeInstr* deopt =
1686 new DeoptimizeInstr(ICData::kDeoptBinarySmiOp, deopt_id_);
1687 flow_graph->InsertBefore(this, deopt, env(), FlowGraph::kEffect);
1688 return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
1689 }
1690 break;
1691
1692 case Token::kSHL: {
1693 const intptr_t kMaxShift = RepresentationBits(representation()) - 1;
1694 if (rhs == 0) {
1695 return left()->definition();
1696 } else if ((rhs < 0) || (rhs >= kMaxShift)) {
1697 if ((rhs < 0) || !is_truncating()) {
1698 DeoptimizeInstr* deopt =
1699 new DeoptimizeInstr(ICData::kDeoptBinarySmiOp, deopt_id_);
1700 flow_graph->InsertBefore(this, deopt, env(), FlowGraph::kEffect);
1701 }
1702 return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
1703 }
1704 break;
1705 }
1706
1707 default:
1708 break;
1437 } 1709 }
1438 1710
1439 return this; 1711 return this;
1440 }
1441
1442
1443 Definition* BinaryMintOpInstr::Canonicalize(FlowGraph* flow_graph) {
1444 Definition* result = NULL;
1445
1446 result = CanonicalizeCommutativeArithmetic(op_kind(),
1447 kMintCid,
1448 left(),
1449 right());
1450 if (result != NULL) {
1451 return result;
1452 }
1453
1454 result = CanonicalizeCommutativeArithmetic(op_kind(),
1455 kMintCid,
1456 right(),
1457 left());
1458 if (result != NULL) {
1459 return result;
1460 }
1461
1462 return this;
1463 }
1464
1465
1466 Definition* BinaryUint32OpInstr::Canonicalize(FlowGraph* flow_graph) {
1467 Definition* result = NULL;
1468
1469 const int64_t truncation_mask = static_cast<int64_t>(0xFFFFFFFF);
1470
1471 result = CanonicalizeCommutativeArithmetic(op_kind(),
1472 kMintCid,
1473 left(),
1474 right(),
1475 truncation_mask);
1476 if (result != NULL) {
1477 return result;
1478 }
1479
1480 result = CanonicalizeCommutativeArithmetic(op_kind(),
1481 kMintCid,
1482 right(),
1483 left(),
1484 truncation_mask);
1485 if (result != NULL) {
1486 return result;
1487 }
1488
1489 return this;
1490 }
1491
1492
1493 Definition* BinaryInt32OpInstr::Canonicalize(FlowGraph* flow_graph) {
1494 Definition* result = NULL;
1495
1496 result = CanonicalizeCommutativeArithmetic(op_kind(),
1497 kSmiCid,
1498 left(),
1499 right());
1500 if (result != NULL) {
1501 return result;
1502 }
1503
1504 result = CanonicalizeCommutativeArithmetic(op_kind(),
1505 kSmiCid,
1506 right(),
1507 left());
1508 if (result != NULL) {
1509 return result;
1510 }
1511
1512 return this;
1513 } 1712 }
1514 1713
1515 1714
1516 // Optimizations that eliminate or simplify individual instructions. 1715 // Optimizations that eliminate or simplify individual instructions.
1517 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { 1716 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) {
1518 return this; 1717 return this;
1519 } 1718 }
1520 1719
1521 1720
1522 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { 1721 Definition* Definition::Canonicalize(FlowGraph* flow_graph) {
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2656 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2855 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2657 compiler->GenerateAssertAssignable(token_pos(), 2856 compiler->GenerateAssertAssignable(token_pos(),
2658 deopt_id(), 2857 deopt_id(),
2659 dst_type(), 2858 dst_type(),
2660 dst_name(), 2859 dst_name(),
2661 locs()); 2860 locs());
2662 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); 2861 ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
2663 } 2862 }
2664 2863
2665 2864
2865 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Isolate* isolate,
2866 bool opt) const {
2867 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kNoCall);
2868 }
2869
2870
2871 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2872 __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_));
2873 }
2874
2875
2666 Environment* Environment::From(Isolate* isolate, 2876 Environment* Environment::From(Isolate* isolate,
2667 const GrowableArray<Definition*>& definitions, 2877 const GrowableArray<Definition*>& definitions,
2668 intptr_t fixed_parameter_count, 2878 intptr_t fixed_parameter_count,
2669 const ParsedFunction* parsed_function) { 2879 const ParsedFunction* parsed_function) {
2670 Environment* env = 2880 Environment* env =
2671 new(isolate) Environment(definitions.length(), 2881 new(isolate) Environment(definitions.length(),
2672 fixed_parameter_count, 2882 fixed_parameter_count,
2673 Isolate::kNoDeoptId, 2883 Isolate::kNoDeoptId,
2674 parsed_function, 2884 parsed_function,
2675 NULL); 2885 NULL);
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
3115 case Token::kTRUNCDIV: return 0; 3325 case Token::kTRUNCDIV: return 0;
3116 case Token::kMOD: return 1; 3326 case Token::kMOD: return 1;
3117 default: UNIMPLEMENTED(); return -1; 3327 default: UNIMPLEMENTED(); return -1;
3118 } 3328 }
3119 } 3329 }
3120 3330
3121 3331
3122 #undef __ 3332 #undef __
3123 3333
3124 } // namespace dart 3334 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698