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

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

Issue 345563007: Add Uint32 representation (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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/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
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
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 10 matching lines...) Expand all
1323 if ((left_value == 0) && (cid != kDoubleCid)) { 1366 if ((left_value == 0) && (cid != kDoubleCid)) {
1324 // Can't apply this equivalence to double operations because 1367 // Can't apply this equivalence to double operations because
1325 // 0.0 + (-0.0) is 0.0 not -0.0. 1368 // 0.0 + (-0.0) is 0.0 not -0.0.
1326 return right->definition(); 1369 return right->definition();
1327 } 1370 }
1328 break; 1371 break;
1329 case Token::kBIT_AND: 1372 case Token::kBIT_AND:
1330 ASSERT(cid != kDoubleCid); 1373 ASSERT(cid != kDoubleCid);
1331 if (left_value == 0) { 1374 if (left_value == 0) {
1332 return left->definition(); 1375 return left->definition();
1333 } else if (left_value == -1) { 1376 } else if (left_value == -1) {
Vyacheslav Egorov (Google) 2014/07/11 16:00:08 I think you should s/-1/mask/ in this function.
Cutch 2014/07/11 22:04:13 Done.
1334 return right->definition(); 1377 return right->definition();
1335 } 1378 }
1336 break; 1379 break;
1337 case Token::kBIT_OR: 1380 case Token::kBIT_OR:
1338 ASSERT(cid != kDoubleCid); 1381 ASSERT(cid != kDoubleCid);
1339 if (left_value == 0) { 1382 if (left_value == 0) {
1340 return right->definition(); 1383 return right->definition();
1341 } else if (left_value == -1) { 1384 } else if (left_value == -1) {
Vyacheslav Egorov (Google) 2014/07/11 16:00:08 ditto
Cutch 2014/07/11 22:04:14 Done.
1342 return left->definition(); 1385 return left->definition();
1343 } 1386 }
1344 break; 1387 break;
1345 case Token::kBIT_XOR: 1388 case Token::kBIT_XOR:
1346 ASSERT(cid != kDoubleCid); 1389 ASSERT(cid != kDoubleCid);
1347 if (left_value == 0) { 1390 if (left_value == 0) {
1348 return right->definition(); 1391 return right->definition();
1349 } 1392 }
1350 break; 1393 break;
1351 default: 1394 default:
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
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)) {
Vyacheslav Egorov (Google) 2014/07/11 16:00:08 I think this is not needed anymore once you replac
Cutch 2014/07/11 22:04:13 Done.
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698