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

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

Issue 26451006: VM: Fix bug in canonicalization of identical in the optimizing compiler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 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/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_allocator.h" 10 #include "vm/flow_graph_allocator.h"
(...skipping 1497 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 } 1508 }
1509 1509
1510 1510
1511 Definition* UnboxUint32x4Instr::Canonicalize(FlowGraph* flow_graph) { 1511 Definition* UnboxUint32x4Instr::Canonicalize(FlowGraph* flow_graph) {
1512 // Fold away UnboxUint32x4(BoxUint32x4(v)). 1512 // Fold away UnboxUint32x4(BoxUint32x4(v)).
1513 BoxUint32x4Instr* defn = value()->definition()->AsBoxUint32x4(); 1513 BoxUint32x4Instr* defn = value()->definition()->AsBoxUint32x4();
1514 return (defn != NULL) ? defn->value()->definition() : this; 1514 return (defn != NULL) ? defn->value()->definition() : this;
1515 } 1515 }
1516 1516
1517 1517
1518 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare,
1519 bool* negated) {
1520 ASSERT(!*negated);
srdjan 2013/10/15 15:10:16 It seems safer to set *negated to false here than
Florian Schneider 2013/10/15 15:15:03 Done.
1521 if (!compare->right()->BindsToConstant()) {
1522 return compare;
1523 }
1524 const Object& right_constant = compare->right()->BoundConstant();
1525 Definition* left_defn = compare->left()->definition();
1526
1527 // TODO(fschneider): Handle other cases: e === false and e !== true/false.
1528 // Handles e === true.
1529 if ((compare->kind() == Token::kEQ_STRICT) &&
1530 (right_constant.raw() == Bool::True().raw()) &&
1531 (compare->left()->Type()->ToCid() == kBoolCid)) {
1532 // Return left subexpression as the replacement for this instruction.
1533 return left_defn;
1534 }
1535 // x = (a === b); y = x !== true; -> y = a !== b.
1536 // In order to merge two strict compares, 'left_strict' must have only one
1537 // use. Do not check left's cid as it is required to be a strict compare.
1538 StrictCompareInstr* left_strict = left_defn->AsStrictCompare();
1539 if ((compare->kind() == Token::kNE_STRICT) &&
1540 (right_constant.raw() == Bool::True().raw()) &&
1541 (left_strict != NULL) &&
1542 (left_strict->HasOnlyUse(compare->left()))) {
1543 *negated = true;
1544 return left_strict;
1545 }
1546 return compare;
1547 }
1548
1549
1518 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { 1550 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) {
1519 // Only handle strict-compares. 1551 // Only handle strict-compares.
1520 if (comparison()->IsStrictCompare()) { 1552 if (comparison()->IsStrictCompare()) {
1521 Definition* replacement = comparison()->Canonicalize(flow_graph); 1553 bool negated = false;
1522 if ((replacement == comparison()) || (replacement == NULL)) { 1554 Definition* replacement =
1555 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated);
1556 if (replacement == comparison()) {
1523 return this; 1557 return this;
1524 } 1558 }
1525 ComparisonInstr* comp = replacement->AsComparison(); 1559 ComparisonInstr* comp = replacement->AsComparison();
1526 if ((comp == NULL) || comp->CanDeoptimize()) { 1560 if ((comp == NULL) || comp->CanDeoptimize()) {
1527 return this; 1561 return this;
1528 } 1562 }
1529 1563
1530 // Check that comparison is not serving as a pending deoptimization target 1564 // Assert that the comparison is not serving as a pending deoptimization
1531 // for conversions. 1565 // target for conversions.
1532 for (intptr_t i = 0; i < comp->InputCount(); i++) { 1566 for (intptr_t i = 0; i < comp->InputCount(); i++) {
1533 if (comp->RequiredInputRepresentation(i) != 1567 if (comp->RequiredInputRepresentation(i) !=
1534 comp->InputAt(i)->definition()->representation()) { 1568 comp->InputAt(i)->definition()->representation()) {
1535 return this; 1569 return this;
1536 } 1570 }
1537 } 1571 }
1538 1572
1539 // Replace the comparison if the replacement is used at this branch, 1573 // Replace the comparison if the replacement is used at this branch,
1540 // and has exactly one use. 1574 // and has exactly one use.
1541 Value* use = comp->input_use_list(); 1575 Value* use = comp->input_use_list();
1542 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { 1576 if ((use->instruction() == this) && comp->HasOnlyUse(use)) {
1577 if (negated) {
1578 comp->NegateComparison();
1579 }
1543 RemoveEnvironment(); 1580 RemoveEnvironment();
1544 flow_graph->CopyDeoptTarget(this, comp); 1581 flow_graph->CopyDeoptTarget(this, comp);
1545 1582
1546 comp->RemoveFromGraph(); 1583 comp->RemoveFromGraph();
1547 SetComparison(comp); 1584 SetComparison(comp);
1548 if (FLAG_trace_optimization) { 1585 if (FLAG_trace_optimization) {
1549 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); 1586 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index());
1550 } 1587 }
1551 // Clear the comparison's temp index and ssa temp index since the 1588 // Clear the comparison's temp index and ssa temp index since the
1552 // value of the comparison is not used outside the branch anymore. 1589 // value of the comparison is not used outside the branch anymore.
1553 ASSERT(comp->input_use_list() == NULL); 1590 ASSERT(comp->input_use_list() == NULL);
1554 comp->ClearSSATempIndex(); 1591 comp->ClearSSATempIndex();
1555 comp->ClearTempIndex(); 1592 comp->ClearTempIndex();
1556 } 1593 }
1557 } 1594 }
1558 return this; 1595 return this;
1559 } 1596 }
1560 1597
1561 1598
1562 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { 1599 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) {
1563 if (!right()->BindsToConstant()) { 1600 bool negated = false;
1564 return this; 1601 Definition* replacement = CanonicalizeStrictCompare(this, &negated);
1602 if (negated && replacement->IsComparison()) {
1603 ASSERT(replacement != this);
1604 replacement->AsComparison()->NegateComparison();
1565 } 1605 }
1566 const Object& right_constant = right()->BoundConstant(); 1606 return replacement;
1567 Definition* left_defn = left()->definition();
1568 // TODO(fschneider): Handle other cases: e === false and e !== true/false.
1569 // Handles e === true.
1570 if ((kind() == Token::kEQ_STRICT) &&
1571 (right_constant.raw() == Bool::True().raw()) &&
1572 (left()->Type()->ToCid() == kBoolCid)) {
1573 // Return left subexpression as the replacement for this instruction.
1574 return left_defn;
1575 }
1576 // x = (a === b); y = x !== true; -> y = a !== b.
1577 // In order to merge two strict comares, 'left_strict' must have only one use.
1578 // Do not check left's cid as it is required to be a strict compare.
1579 StrictCompareInstr* left_strict = left_defn->AsStrictCompare();
1580 if ((kind() == Token::kNE_STRICT) &&
1581 (right_constant.raw() == Bool::True().raw()) &&
1582 (left_strict != NULL) &&
1583 (left_strict->HasOnlyUse(left()))) {
1584 left_strict->set_kind(Token::NegateComparison(left_strict->kind()));
1585 return left_strict;
1586 }
1587
1588 return this;
1589 } 1607 }
1590 1608
1591 1609
1592 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { 1610 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) {
1593 // TODO(vegorov): Replace class checks with null checks when ToNullableCid 1611 // TODO(vegorov): Replace class checks with null checks when ToNullableCid
1594 // matches. 1612 // matches.
1595 1613
1596 const intptr_t value_cid = value()->Type()->ToCid(); 1614 const intptr_t value_cid = value()->Type()->ToCid();
1597 if (value_cid == kDynamicCid) { 1615 if (value_cid == kDynamicCid) {
1598 return this; 1616 return this;
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2700 return kCosRuntimeEntry; 2718 return kCosRuntimeEntry;
2701 default: 2719 default:
2702 UNREACHABLE(); 2720 UNREACHABLE();
2703 } 2721 }
2704 return kSinRuntimeEntry; 2722 return kSinRuntimeEntry;
2705 } 2723 }
2706 2724
2707 #undef __ 2725 #undef __
2708 2726
2709 } // namespace dart 2727 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698