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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 | 330 |
331 | 331 |
332 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value) | 332 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value) |
333 : ConstantInstr(value), constant_address_(0) { | 333 : ConstantInstr(value), constant_address_(0) { |
334 // Only doubles supported for now. | 334 // Only doubles supported for now. |
335 ASSERT(value.IsDouble()); | 335 ASSERT(value.IsDouble()); |
336 constant_address_ = | 336 constant_address_ = |
337 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); | 337 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); |
338 } | 338 } |
339 | 339 |
| 340 |
| 341 bool Value::BindsTo32BitMaskConstant() const { |
| 342 if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) { |
| 343 return false; |
| 344 } |
| 345 // Two cases to consider: UnboxInteger and UnboxUint32. |
| 346 if (definition()->IsUnboxInteger()) { |
| 347 UnboxIntegerInstr* instr = definition()->AsUnboxInteger(); |
| 348 if (!instr->value()->BindsToConstant()) { |
| 349 return false; |
| 350 } |
| 351 const Object& obj = instr->value()->BoundConstant(); |
| 352 if (!obj.IsMint()) { |
| 353 return false; |
| 354 } |
| 355 Mint& mint = Mint::Handle(); |
| 356 mint ^= obj.raw(); |
| 357 return mint.value() == kMaxUint32; |
| 358 } else if (definition()->IsUnboxUint32()) { |
| 359 UnboxUint32Instr* instr = definition()->AsUnboxUint32(); |
| 360 if (!instr->value()->BindsToConstant()) { |
| 361 return false; |
| 362 } |
| 363 const Object& obj = instr->value()->BoundConstant(); |
| 364 if (!obj.IsMint()) { |
| 365 return false; |
| 366 } |
| 367 Mint& mint = Mint::Handle(); |
| 368 mint ^= obj.raw(); |
| 369 return mint.value() == kMaxUint32; |
| 370 } |
| 371 return false; |
| 372 } |
| 373 |
| 374 |
340 // Returns true if the value represents a constant. | 375 // Returns true if the value represents a constant. |
341 bool Value::BindsToConstant() const { | 376 bool Value::BindsToConstant() const { |
342 return definition()->IsConstant(); | 377 return definition()->IsConstant(); |
343 } | 378 } |
344 | 379 |
345 | 380 |
346 // Returns true if the value represents constant null. | 381 // Returns true if the value represents constant null. |
347 bool Value::BindsToConstantNull() const { | 382 bool Value::BindsToConstantNull() const { |
348 ConstantInstr* constant = definition()->AsConstant(); | 383 ConstantInstr* constant = definition()->AsConstant(); |
349 return (constant != NULL) && constant->value().IsNull(); | 384 return (constant != NULL) && constant->value().IsNull(); |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1259 | 1294 |
1260 bool BinarySmiOpInstr::RightIsPowerOfTwoConstant() const { | 1295 bool BinarySmiOpInstr::RightIsPowerOfTwoConstant() const { |
1261 if (!right()->definition()->IsConstant()) return false; | 1296 if (!right()->definition()->IsConstant()) return false; |
1262 const Object& constant = right()->definition()->AsConstant()->value(); | 1297 const Object& constant = right()->definition()->AsConstant()->value(); |
1263 if (!constant.IsSmi()) return false; | 1298 if (!constant.IsSmi()) return false; |
1264 const intptr_t int_value = Smi::Cast(constant).Value(); | 1299 const intptr_t int_value = Smi::Cast(constant).Value(); |
1265 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); | 1300 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); |
1266 } | 1301 } |
1267 | 1302 |
1268 | 1303 |
1269 static bool ToIntegerConstant(Value* value, intptr_t* result) { | 1304 static bool ToIntegerConstant(Value* value, int64_t* result) { |
1270 if (!value->BindsToConstant()) { | 1305 if (!value->BindsToConstant()) { |
1271 if (value->definition()->IsUnboxDouble()) { | 1306 if (value->definition()->IsUnboxDouble()) { |
1272 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), | 1307 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), |
1273 result); | 1308 result); |
1274 } | 1309 } |
1275 return false; | 1310 return false; |
1276 } | 1311 } |
1277 | 1312 |
1278 const Object& constant = value->BoundConstant(); | 1313 const Object& constant = value->BoundConstant(); |
1279 if (constant.IsDouble()) { | 1314 if (constant.IsDouble()) { |
1280 const Double& double_constant = Double::Cast(constant); | 1315 const Double& double_constant = Double::Cast(constant); |
1281 *result = static_cast<intptr_t>(double_constant.value()); | 1316 *result = static_cast<int64_t>(double_constant.value()); |
1282 return (static_cast<double>(*result) == double_constant.value()); | 1317 return (static_cast<double>(*result) == double_constant.value()); |
1283 } else if (constant.IsSmi()) { | 1318 } else if (constant.IsSmi()) { |
1284 *result = Smi::Cast(constant).Value(); | 1319 *result = Smi::Cast(constant).Value(); |
1285 return true; | 1320 return true; |
| 1321 } else if (constant.IsMint()) { |
| 1322 *result = Mint::Cast(constant).value(); |
| 1323 return true; |
1286 } | 1324 } |
1287 | 1325 |
1288 return false; | 1326 return false; |
1289 } | 1327 } |
1290 | 1328 |
1291 | 1329 |
1292 static Definition* CanonicalizeCommutativeArithmetic(Token::Kind op, | 1330 static Definition* CanonicalizeCommutativeArithmetic( |
1293 intptr_t cid, | 1331 Token::Kind op, |
1294 Value* left, | 1332 intptr_t cid, |
1295 Value* right) { | 1333 Value* left, |
| 1334 Value* right, |
| 1335 int64_t mask = static_cast<int64_t>(0xFFFFFFFFFFFFFFFF)) { |
1296 ASSERT((cid == kSmiCid) || (cid == kDoubleCid) || (cid == kMintCid)); | 1336 ASSERT((cid == kSmiCid) || (cid == kDoubleCid) || (cid == kMintCid)); |
1297 | 1337 |
1298 intptr_t left_value; | 1338 int64_t left_value; |
1299 if (!ToIntegerConstant(left, &left_value)) { | 1339 if (!ToIntegerConstant(left, &left_value)) { |
1300 return NULL; | 1340 return NULL; |
1301 } | 1341 } |
1302 | 1342 |
| 1343 // Apply truncation mask to left_value. |
| 1344 left_value &= mask; |
| 1345 |
1303 switch (op) { | 1346 switch (op) { |
1304 case Token::kMUL: | 1347 case Token::kMUL: |
1305 if (left_value == 1) { | 1348 if (left_value == 1) { |
1306 if ((cid == kDoubleCid) && | 1349 if ((cid == kDoubleCid) && |
1307 (right->definition()->representation() != kUnboxedDouble)) { | 1350 (right->definition()->representation() != kUnboxedDouble)) { |
1308 // Can't yet apply the equivalence because representation selection | 1351 // Can't yet apply the equivalence because representation selection |
1309 // did not run yet. We need it to guarantee that right value is | 1352 // did not run yet. We need it to guarantee that right value is |
1310 // correctly coerced to double. The second canonicalization pass | 1353 // correctly coerced to double. The second canonicalization pass |
1311 // will apply this equivalence. | 1354 // will apply this equivalence. |
1312 return NULL; | 1355 return NULL; |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 right(), | 1500 right(), |
1458 left()); | 1501 left()); |
1459 if (result != NULL) { | 1502 if (result != NULL) { |
1460 return result; | 1503 return result; |
1461 } | 1504 } |
1462 | 1505 |
1463 return this; | 1506 return this; |
1464 } | 1507 } |
1465 | 1508 |
1466 | 1509 |
| 1510 static bool IsUint32Mask(BinaryUint32OpInstr* defn) { |
| 1511 ASSERT(defn != NULL); |
| 1512 if (defn->op_kind() != Token::kBIT_AND) { |
| 1513 // Not a mask. |
| 1514 return false; |
| 1515 } |
| 1516 Value* left = defn->left(); |
| 1517 Value* right = defn->right(); |
| 1518 return left->BindsTo32BitMaskConstant() != right->BindsTo32BitMaskConstant(); |
| 1519 } |
| 1520 |
| 1521 |
| 1522 Definition* BinaryUint32OpInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1523 // If this is (value & 0xFFFFFFFF) the mask operation can be dropped because |
| 1524 // all Uint32 operations are implicitly masked with 0xFFFFFFFF. |
| 1525 if (IsUint32Mask(this)) { |
| 1526 return NULL; |
| 1527 } |
| 1528 |
| 1529 Definition* result = NULL; |
| 1530 |
| 1531 const int64_t truncation_mask = static_cast<int64_t>(0xFFFFFFFF); |
| 1532 |
| 1533 result = CanonicalizeCommutativeArithmetic(op_kind(), |
| 1534 kMintCid, |
| 1535 left(), |
| 1536 right(), |
| 1537 truncation_mask); |
| 1538 if (result != NULL) { |
| 1539 return result; |
| 1540 } |
| 1541 |
| 1542 result = CanonicalizeCommutativeArithmetic(op_kind(), |
| 1543 kMintCid, |
| 1544 right(), |
| 1545 left(), |
| 1546 truncation_mask); |
| 1547 if (result != NULL) { |
| 1548 return result; |
| 1549 } |
| 1550 |
| 1551 return this; |
| 1552 } |
| 1553 |
| 1554 |
1467 // Optimizations that eliminate or simplify individual instructions. | 1555 // Optimizations that eliminate or simplify individual instructions. |
1468 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { | 1556 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { |
1469 return this; | 1557 return this; |
1470 } | 1558 } |
1471 | 1559 |
1472 | 1560 |
1473 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { | 1561 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { |
1474 return this; | 1562 return this; |
1475 } | 1563 } |
1476 | 1564 |
(...skipping 2498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3975 case Token::kTRUNCDIV: return 0; | 4063 case Token::kTRUNCDIV: return 0; |
3976 case Token::kMOD: return 1; | 4064 case Token::kMOD: return 1; |
3977 default: UNIMPLEMENTED(); return -1; | 4065 default: UNIMPLEMENTED(); return -1; |
3978 } | 4066 } |
3979 } | 4067 } |
3980 | 4068 |
3981 | 4069 |
3982 #undef __ | 4070 #undef __ |
3983 | 4071 |
3984 } // namespace dart | 4072 } // namespace dart |
OLD | NEW |