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

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

Issue 61123003: Inline integer modulo operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language_arm.cc » ('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/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after
1489 case Token::kDIV: 1489 case Token::kDIV:
1490 if (ShouldSpecializeForDouble(ic_data) || 1490 if (ShouldSpecializeForDouble(ic_data) ||
1491 HasOnlyTwoOf(ic_data, kSmiCid)) { 1491 HasOnlyTwoOf(ic_data, kSmiCid)) {
1492 operands_type = kDoubleCid; 1492 operands_type = kDoubleCid;
1493 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { 1493 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
1494 operands_type = kFloat32x4Cid; 1494 operands_type = kFloat32x4Cid;
1495 } else { 1495 } else {
1496 return false; 1496 return false;
1497 } 1497 }
1498 break; 1498 break;
1499 case Token::kMOD:
1500 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1501 operands_type = kSmiCid;
1502 } else {
1503 return false;
1504 }
1505 break;
1506 case Token::kBIT_AND: 1499 case Token::kBIT_AND:
1507 case Token::kBIT_OR: 1500 case Token::kBIT_OR:
1508 case Token::kBIT_XOR: 1501 case Token::kBIT_XOR:
1509 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1502 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1510 operands_type = kSmiCid; 1503 operands_type = kSmiCid;
1511 } else if (HasTwoMintOrSmi(ic_data)) { 1504 } else if (HasTwoMintOrSmi(ic_data)) {
1512 operands_type = kMintCid; 1505 operands_type = kMintCid;
1513 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { 1506 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) {
1514 operands_type = kInt32x4Cid; 1507 operands_type = kInt32x4Cid;
1515 } else { 1508 } else {
1516 return false; 1509 return false;
1517 } 1510 }
1518 break; 1511 break;
1519 case Token::kSHR: 1512 case Token::kSHR:
1520 case Token::kSHL: 1513 case Token::kSHL:
1521 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1514 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1522 // Left shift may overflow from smi into mint or big ints. 1515 // Left shift may overflow from smi into mint or big ints.
1523 // Don't generate smi code if the IC data is marked because 1516 // Don't generate smi code if the IC data is marked because
1524 // of an overflow. 1517 // of an overflow.
1525 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; 1518 if (ic_data.deopt_reason() == kDeoptShiftMintOp) {
1519 return false;
1520 }
1526 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp) 1521 operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp)
1527 ? kMintCid 1522 ? kMintCid
1528 : kSmiCid; 1523 : kSmiCid;
1529 } else if (HasTwoMintOrSmi(ic_data) && 1524 } else if (HasTwoMintOrSmi(ic_data) &&
1530 HasOnlyOneSmi(ICData::Handle( 1525 HasOnlyOneSmi(ICData::Handle(
1531 ic_data.AsUnaryClassChecksForArgNr(1)))) { 1526 ic_data.AsUnaryClassChecksForArgNr(1)))) {
1532 // Don't generate mint code if the IC data is marked because of an 1527 // Don't generate mint code if the IC data is marked because of an
1533 // overflow. 1528 // overflow.
1534 if (ic_data.deopt_reason() == kDeoptShiftMintOp) return false; 1529 if (ic_data.deopt_reason() == kDeoptShiftMintOp) {
1530 return false;
1531 }
1535 // Check for smi/mint << smi or smi/mint >> smi. 1532 // Check for smi/mint << smi or smi/mint >> smi.
1536 operands_type = kMintCid; 1533 operands_type = kMintCid;
1537 } else { 1534 } else {
1538 return false; 1535 return false;
1539 } 1536 }
1540 break; 1537 break;
1538 case Token::kMOD:
1541 case Token::kTRUNCDIV: 1539 case Token::kTRUNCDIV:
1542 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1540 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1543 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; 1541 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) {
1542 return false;
1543 }
1544 operands_type = kSmiCid; 1544 operands_type = kSmiCid;
1545 } else { 1545 } else {
1546 return false; 1546 return false;
1547 } 1547 }
1548 break; 1548 break;
1549 default: 1549 default:
1550 UNREACHABLE(); 1550 UNREACHABLE();
1551 } 1551 }
1552 1552
1553 ASSERT(call->ArgumentCount() == 2); 1553 ASSERT(call->ArgumentCount() == 2);
(...skipping 27 matching lines...) Expand all
1581 BinaryMintOpInstr* bin_op = 1581 BinaryMintOpInstr* bin_op =
1582 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), 1582 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right),
1583 call->deopt_id()); 1583 call->deopt_id());
1584 ReplaceCall(call, bin_op); 1584 ReplaceCall(call, bin_op);
1585 } 1585 }
1586 } else if (operands_type == kFloat32x4Cid) { 1586 } else if (operands_type == kFloat32x4Cid) {
1587 return InlineFloat32x4BinaryOp(call, op_kind); 1587 return InlineFloat32x4BinaryOp(call, op_kind);
1588 } else if (operands_type == kInt32x4Cid) { 1588 } else if (operands_type == kInt32x4Cid) {
1589 return InlineInt32x4BinaryOp(call, op_kind); 1589 return InlineInt32x4BinaryOp(call, op_kind);
1590 } else if (op_kind == Token::kMOD) { 1590 } else if (op_kind == Token::kMOD) {
1591 // TODO(vegorov): implement fast path code for modulo.
1592 ASSERT(operands_type == kSmiCid); 1591 ASSERT(operands_type == kSmiCid);
1593 if (!right->IsConstant()) return false; 1592 if (right->IsConstant()) {
1594 const Object& obj = right->AsConstant()->value(); 1593 const Object& obj = right->AsConstant()->value();
1595 if (!obj.IsSmi()) return false; 1594 if (obj.IsSmi() && Utils::IsPowerOfTwo(Smi::Cast(obj).Value())) {
1596 const intptr_t value = Smi::Cast(obj).Value(); 1595 // Insert smi check and attach a copy of the original environment
1597 if (!Utils::IsPowerOfTwo(value)) return false; 1596 // because the smi operation can still deoptimize.
1598 1597 InsertBefore(call,
1599 // Insert smi check and attach a copy of the original environment 1598 new CheckSmiInstr(new Value(left), call->deopt_id()),
1600 // because the smi operation can still deoptimize. 1599 call->env(),
1601 InsertBefore(call, 1600 Definition::kEffect);
1602 new CheckSmiInstr(new Value(left), call->deopt_id()), 1601 ConstantInstr* constant =
1603 call->env(), 1602 flow_graph()->GetConstant(Smi::Handle(
1604 Definition::kEffect); 1603 Smi::New(Smi::Cast(obj).Value() - 1)));
1605 ConstantInstr* constant = 1604 BinarySmiOpInstr* bin_op =
1606 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1))); 1605 new BinarySmiOpInstr(Token::kBIT_AND,
1606 new Value(left),
1607 new Value(constant),
1608 call->deopt_id());
1609 ReplaceCall(call, bin_op);
1610 return true;
1611 }
1612 }
1613 // Insert two smi checks and attach a copy of the original
1614 // environment because the smi operation can still deoptimize.
1615 AddCheckSmi(left, call->deopt_id(), call->env(), call);
1616 AddCheckSmi(right, call->deopt_id(), call->env(), call);
1607 BinarySmiOpInstr* bin_op = 1617 BinarySmiOpInstr* bin_op =
1608 new BinarySmiOpInstr(Token::kBIT_AND, 1618 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right),
1609 new Value(left),
1610 new Value(constant),
1611 call->deopt_id()); 1619 call->deopt_id());
1612 ReplaceCall(call, bin_op); 1620 ReplaceCall(call, bin_op);
1613 } else { 1621 } else {
1614 ASSERT(operands_type == kSmiCid); 1622 ASSERT(operands_type == kSmiCid);
1615 // Insert two smi checks and attach a copy of the original 1623 // Insert two smi checks and attach a copy of the original
1616 // environment because the smi operation can still deoptimize. 1624 // environment because the smi operation can still deoptimize.
1617 AddCheckSmi(left, call->deopt_id(), call->env(), call); 1625 AddCheckSmi(left, call->deopt_id(), call->env(), call);
1618 AddCheckSmi(right, call->deopt_id(), call->env(), call); 1626 AddCheckSmi(right, call->deopt_id(), call->env(), call);
1619 if (left->IsConstant() && 1627 if (left->IsConstant() &&
1620 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { 1628 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
(...skipping 6263 matching lines...) Expand 10 before | Expand all | Expand 10 after
7884 } 7892 }
7885 7893
7886 // Insert materializations at environment uses. 7894 // Insert materializations at environment uses.
7887 for (intptr_t i = 0; i < exits.length(); i++) { 7895 for (intptr_t i = 0; i < exits.length(); i++) {
7888 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7896 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7889 } 7897 }
7890 } 7898 }
7891 7899
7892 7900
7893 } // namespace dart 7901 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698