OLD | NEW |
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/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 | 377 |
378 | 378 |
379 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value) | 379 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value) |
380 : ConstantInstr(value), constant_address_(0) { | 380 : ConstantInstr(value), constant_address_(0) { |
381 // Only doubles supported for now. | 381 // Only doubles supported for now. |
382 ASSERT(value.IsDouble()); | 382 ASSERT(value.IsDouble()); |
383 constant_address_ = | 383 constant_address_ = |
384 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); | 384 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); |
385 } | 385 } |
386 | 386 |
| 387 |
| 388 bool Value::BindsTo32BitMaskConstant() const { |
| 389 if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) { |
| 390 return false; |
| 391 } |
| 392 // Two cases to consider: UnboxInteger and UnboxUint32. |
| 393 if (definition()->IsUnboxInteger()) { |
| 394 UnboxIntegerInstr* instr = definition()->AsUnboxInteger(); |
| 395 if (!instr->value()->BindsToConstant()) { |
| 396 return false; |
| 397 } |
| 398 const Object& obj = instr->value()->BoundConstant(); |
| 399 if (!obj.IsMint()) { |
| 400 return false; |
| 401 } |
| 402 Mint& mint = Mint::Handle(); |
| 403 mint ^= obj.raw(); |
| 404 return mint.value() == kMaxUint32; |
| 405 } else if (definition()->IsUnboxUint32()) { |
| 406 UnboxUint32Instr* instr = definition()->AsUnboxUint32(); |
| 407 if (!instr->value()->BindsToConstant()) { |
| 408 return false; |
| 409 } |
| 410 const Object& obj = instr->value()->BoundConstant(); |
| 411 if (!obj.IsMint()) { |
| 412 return false; |
| 413 } |
| 414 Mint& mint = Mint::Handle(); |
| 415 mint ^= obj.raw(); |
| 416 return mint.value() == kMaxUint32; |
| 417 } |
| 418 return false; |
| 419 } |
| 420 |
| 421 |
387 // Returns true if the value represents a constant. | 422 // Returns true if the value represents a constant. |
388 bool Value::BindsToConstant() const { | 423 bool Value::BindsToConstant() const { |
389 return definition()->IsConstant(); | 424 return definition()->IsConstant(); |
390 } | 425 } |
391 | 426 |
392 | 427 |
393 // Returns true if the value represents constant null. | 428 // Returns true if the value represents constant null. |
394 bool Value::BindsToConstantNull() const { | 429 bool Value::BindsToConstantNull() const { |
395 ConstantInstr* constant = definition()->AsConstant(); | 430 ConstantInstr* constant = definition()->AsConstant(); |
396 return (constant != NULL) && constant->value().IsNull(); | 431 return (constant != NULL) && constant->value().IsNull(); |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1306 | 1341 |
1307 bool BinarySmiOpInstr::RightIsPowerOfTwoConstant() const { | 1342 bool BinarySmiOpInstr::RightIsPowerOfTwoConstant() const { |
1308 if (!right()->definition()->IsConstant()) return false; | 1343 if (!right()->definition()->IsConstant()) return false; |
1309 const Object& constant = right()->definition()->AsConstant()->value(); | 1344 const Object& constant = right()->definition()->AsConstant()->value(); |
1310 if (!constant.IsSmi()) return false; | 1345 if (!constant.IsSmi()) return false; |
1311 const intptr_t int_value = Smi::Cast(constant).Value(); | 1346 const intptr_t int_value = Smi::Cast(constant).Value(); |
1312 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); | 1347 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); |
1313 } | 1348 } |
1314 | 1349 |
1315 | 1350 |
1316 static bool ToIntegerConstant(Value* value, intptr_t* result) { | 1351 static bool ToIntegerConstant(Value* value, int64_t* result) { |
1317 if (!value->BindsToConstant()) { | 1352 if (!value->BindsToConstant()) { |
1318 if (value->definition()->IsUnboxDouble()) { | 1353 if (value->definition()->IsUnboxDouble()) { |
1319 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), | 1354 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), |
1320 result); | 1355 result); |
1321 } | 1356 } |
1322 return false; | 1357 return false; |
1323 } | 1358 } |
1324 | 1359 |
1325 const Object& constant = value->BoundConstant(); | 1360 const Object& constant = value->BoundConstant(); |
1326 if (constant.IsDouble()) { | 1361 if (constant.IsDouble()) { |
1327 const Double& double_constant = Double::Cast(constant); | 1362 const Double& double_constant = Double::Cast(constant); |
1328 *result = static_cast<intptr_t>(double_constant.value()); | 1363 *result = static_cast<int64_t>(double_constant.value()); |
1329 return (static_cast<double>(*result) == double_constant.value()); | 1364 return (static_cast<double>(*result) == double_constant.value()); |
1330 } else if (constant.IsSmi()) { | 1365 } else if (constant.IsSmi()) { |
1331 *result = Smi::Cast(constant).Value(); | 1366 *result = Smi::Cast(constant).Value(); |
1332 return true; | 1367 return true; |
| 1368 } else if (constant.IsMint()) { |
| 1369 *result = Mint::Cast(constant).value(); |
| 1370 return true; |
1333 } | 1371 } |
1334 | 1372 |
1335 return false; | 1373 return false; |
1336 } | 1374 } |
1337 | 1375 |
1338 | 1376 |
1339 static Definition* CanonicalizeCommutativeArithmetic(Token::Kind op, | 1377 static Definition* CanonicalizeCommutativeArithmetic( |
1340 intptr_t cid, | 1378 Token::Kind op, |
1341 Value* left, | 1379 intptr_t cid, |
1342 Value* right) { | 1380 Value* left, |
| 1381 Value* right, |
| 1382 int64_t mask = static_cast<int64_t>(0xFFFFFFFFFFFFFFFF)) { |
1343 ASSERT((cid == kSmiCid) || (cid == kDoubleCid) || (cid == kMintCid)); | 1383 ASSERT((cid == kSmiCid) || (cid == kDoubleCid) || (cid == kMintCid)); |
1344 | 1384 |
1345 intptr_t left_value; | 1385 int64_t left_value; |
1346 if (!ToIntegerConstant(left, &left_value)) { | 1386 if (!ToIntegerConstant(left, &left_value)) { |
1347 return NULL; | 1387 return NULL; |
1348 } | 1388 } |
1349 | 1389 |
| 1390 // Apply truncation mask to left_value. |
| 1391 left_value &= mask; |
| 1392 |
1350 switch (op) { | 1393 switch (op) { |
1351 case Token::kMUL: | 1394 case Token::kMUL: |
1352 if (left_value == 1) { | 1395 if (left_value == 1) { |
1353 if ((cid == kDoubleCid) && | 1396 if ((cid == kDoubleCid) && |
1354 (right->definition()->representation() != kUnboxedDouble)) { | 1397 (right->definition()->representation() != kUnboxedDouble)) { |
1355 // Can't yet apply the equivalence because representation selection | 1398 // Can't yet apply the equivalence because representation selection |
1356 // did not run yet. We need it to guarantee that right value is | 1399 // did not run yet. We need it to guarantee that right value is |
1357 // correctly coerced to double. The second canonicalization pass | 1400 // correctly coerced to double. The second canonicalization pass |
1358 // will apply this equivalence. | 1401 // will apply this equivalence. |
1359 return NULL; | 1402 return NULL; |
(...skipping 10 matching lines...) Expand all Loading... |
1370 if ((left_value == 0) && (cid != kDoubleCid)) { | 1413 if ((left_value == 0) && (cid != kDoubleCid)) { |
1371 // Can't apply this equivalence to double operations because | 1414 // Can't apply this equivalence to double operations because |
1372 // 0.0 + (-0.0) is 0.0 not -0.0. | 1415 // 0.0 + (-0.0) is 0.0 not -0.0. |
1373 return right->definition(); | 1416 return right->definition(); |
1374 } | 1417 } |
1375 break; | 1418 break; |
1376 case Token::kBIT_AND: | 1419 case Token::kBIT_AND: |
1377 ASSERT(cid != kDoubleCid); | 1420 ASSERT(cid != kDoubleCid); |
1378 if (left_value == 0) { | 1421 if (left_value == 0) { |
1379 return left->definition(); | 1422 return left->definition(); |
1380 } else if (left_value == -1) { | 1423 } else if (left_value == mask) { |
1381 return right->definition(); | 1424 return right->definition(); |
1382 } | 1425 } |
1383 break; | 1426 break; |
1384 case Token::kBIT_OR: | 1427 case Token::kBIT_OR: |
1385 ASSERT(cid != kDoubleCid); | 1428 ASSERT(cid != kDoubleCid); |
1386 if (left_value == 0) { | 1429 if (left_value == 0) { |
1387 return right->definition(); | 1430 return right->definition(); |
1388 } else if (left_value == -1) { | 1431 } else if (left_value == mask) { |
1389 return left->definition(); | 1432 return left->definition(); |
1390 } | 1433 } |
1391 break; | 1434 break; |
1392 case Token::kBIT_XOR: | 1435 case Token::kBIT_XOR: |
1393 ASSERT(cid != kDoubleCid); | 1436 ASSERT(cid != kDoubleCid); |
1394 if (left_value == 0) { | 1437 if (left_value == 0) { |
1395 return right->definition(); | 1438 return right->definition(); |
1396 } | 1439 } |
1397 break; | 1440 break; |
1398 default: | 1441 default: |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 right(), | 1547 right(), |
1505 left()); | 1548 left()); |
1506 if (result != NULL) { | 1549 if (result != NULL) { |
1507 return result; | 1550 return result; |
1508 } | 1551 } |
1509 | 1552 |
1510 return this; | 1553 return this; |
1511 } | 1554 } |
1512 | 1555 |
1513 | 1556 |
| 1557 Definition* BinaryUint32OpInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1558 Definition* result = NULL; |
| 1559 |
| 1560 const int64_t truncation_mask = static_cast<int64_t>(0xFFFFFFFF); |
| 1561 |
| 1562 result = CanonicalizeCommutativeArithmetic(op_kind(), |
| 1563 kMintCid, |
| 1564 left(), |
| 1565 right(), |
| 1566 truncation_mask); |
| 1567 if (result != NULL) { |
| 1568 return result; |
| 1569 } |
| 1570 |
| 1571 result = CanonicalizeCommutativeArithmetic(op_kind(), |
| 1572 kMintCid, |
| 1573 right(), |
| 1574 left(), |
| 1575 truncation_mask); |
| 1576 if (result != NULL) { |
| 1577 return result; |
| 1578 } |
| 1579 |
| 1580 return this; |
| 1581 } |
| 1582 |
| 1583 |
1514 // Optimizations that eliminate or simplify individual instructions. | 1584 // Optimizations that eliminate or simplify individual instructions. |
1515 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { | 1585 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { |
1516 return this; | 1586 return this; |
1517 } | 1587 } |
1518 | 1588 |
1519 | 1589 |
1520 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { | 1590 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { |
1521 return this; | 1591 return this; |
1522 } | 1592 } |
1523 | 1593 |
(...skipping 2511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4035 case Token::kTRUNCDIV: return 0; | 4105 case Token::kTRUNCDIV: return 0; |
4036 case Token::kMOD: return 1; | 4106 case Token::kMOD: return 1; |
4037 default: UNIMPLEMENTED(); return -1; | 4107 default: UNIMPLEMENTED(); return -1; |
4038 } | 4108 } |
4039 } | 4109 } |
4040 | 4110 |
4041 | 4111 |
4042 #undef __ | 4112 #undef __ |
4043 | 4113 |
4044 } // namespace dart | 4114 } // namespace dart |
OLD | NEW |