| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 return instruction is HGoto | 1294 return instruction is HGoto |
| 1295 || instruction.inputs[0].isConstantTrue(); | 1295 || instruction.inputs[0].isConstantTrue(); |
| 1296 } | 1296 } |
| 1297 bool firstInstructionInLoop = block == loopHeader | 1297 bool firstInstructionInLoop = block == loopHeader |
| 1298 // Compensate for lack of code motion. | 1298 // Compensate for lack of code motion. |
| 1299 || (blockChangesFlags[loopHeader.id] == 0 | 1299 || (blockChangesFlags[loopHeader.id] == 0 |
| 1300 && isLoopAlwaysTaken() | 1300 && isLoopAlwaysTaken() |
| 1301 && loopHeader.successors[0] == block); | 1301 && loopHeader.successors[0] == block); |
| 1302 while (instruction != null) { | 1302 while (instruction != null) { |
| 1303 HInstruction next = instruction.next; | 1303 HInstruction next = instruction.next; |
| 1304 if (instruction.useGvn() | 1304 if (instruction.useGvn() && instruction.isMovable |
| 1305 && (!instruction.canThrow() || firstInstructionInLoop) | 1305 && (!instruction.canThrow() || firstInstructionInLoop) |
| 1306 && !instruction.sideEffects.dependsOn(dependsFlags)) { | 1306 && !instruction.sideEffects.dependsOn(dependsFlags)) { |
| 1307 bool loopInvariantInputs = true; | 1307 bool loopInvariantInputs = true; |
| 1308 List<HInstruction> inputs = instruction.inputs; | 1308 List<HInstruction> inputs = instruction.inputs; |
| 1309 for (int i = 0, length = inputs.length; i < length; i++) { | 1309 for (int i = 0, length = inputs.length; i < length; i++) { |
| 1310 if (isInputDefinedAfterDominator(inputs[i], preheader)) { | 1310 if (isInputDefinedAfterDominator(inputs[i], preheader)) { |
| 1311 loopInvariantInputs = false; | 1311 loopInvariantInputs = false; |
| 1312 break; | 1312 break; |
| 1313 } | 1313 } |
| 1314 } | 1314 } |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 // which instructions can be moved to a dominator block. | 1516 // which instructions can be moved to a dominator block. |
| 1517 ValueSet set_ = values[block.id]; | 1517 ValueSet set_ = values[block.id]; |
| 1518 HInstruction instruction = block.first; | 1518 HInstruction instruction = block.first; |
| 1519 int flags = 0; | 1519 int flags = 0; |
| 1520 while (instruction != null) { | 1520 while (instruction != null) { |
| 1521 int dependsFlags = SideEffects.computeDependsOnFlags(flags); | 1521 int dependsFlags = SideEffects.computeDependsOnFlags(flags); |
| 1522 flags |= instruction.sideEffects.getChangesFlags(); | 1522 flags |= instruction.sideEffects.getChangesFlags(); |
| 1523 | 1523 |
| 1524 HInstruction current = instruction; | 1524 HInstruction current = instruction; |
| 1525 instruction = instruction.next; | 1525 instruction = instruction.next; |
| 1526 | 1526 if (!current.useGvn() || !current.isMovable) continue; |
| 1527 // TODO(ngeoffray): this check is needed because we currently do | 1527 // TODO(sra): We could move throwing instructions provided we keep the |
| 1528 // not have flags to express 'Gvn'able', but not movable. | 1528 // exceptions in the same order. This requires they are in the same order |
| 1529 if (current is HCheck) continue; | 1529 // in all successors, which is not tracked by the ValueSet. |
| 1530 if (!current.useGvn()) continue; | 1530 if (current.canThrow()) continue; |
| 1531 if (current.sideEffects.dependsOn(dependsFlags)) continue; | 1531 if (current.sideEffects.dependsOn(dependsFlags)) continue; |
| 1532 | 1532 |
| 1533 bool canBeMoved = true; | 1533 bool canBeMoved = true; |
| 1534 for (final HInstruction input in current.inputs) { | 1534 for (final HInstruction input in current.inputs) { |
| 1535 if (input.block == block) { | 1535 if (input.block == block) { |
| 1536 canBeMoved = false; | 1536 canBeMoved = false; |
| 1537 break; | 1537 break; |
| 1538 } | 1538 } |
| 1539 } | 1539 } |
| 1540 if (!canBeMoved) continue; | 1540 if (!canBeMoved) continue; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1555 final String name = "SsaTypeconversionInserter"; | 1555 final String name = "SsaTypeconversionInserter"; |
| 1556 final Compiler compiler; | 1556 final Compiler compiler; |
| 1557 | 1557 |
| 1558 SsaTypeConversionInserter(this.compiler); | 1558 SsaTypeConversionInserter(this.compiler); |
| 1559 | 1559 |
| 1560 void visitGraph(HGraph graph) { | 1560 void visitGraph(HGraph graph) { |
| 1561 visitDominatorTree(graph); | 1561 visitDominatorTree(graph); |
| 1562 } | 1562 } |
| 1563 | 1563 |
| 1564 // Update users of [input] that are dominated by [:dominator.first:] | 1564 // Update users of [input] that are dominated by [:dominator.first:] |
| 1565 // to use [newInput] instead. | 1565 // to use [TypeKnown] of [input] instead. As the type information depends |
| 1566 void changeUsesDominatedBy(HBasicBlock dominator, | 1566 // on the control flow, we mark the inserted [HTypeKnown] nodes as |
| 1567 HInstruction input, | 1567 // non-movable. |
| 1568 TypeMask convertedType) { | 1568 void insertTypePropagationForDominatedUsers(HBasicBlock dominator, |
| 1569 HInstruction input, |
| 1570 TypeMask convertedType) { |
| 1569 Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first); | 1571 Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first); |
| 1570 if (dominatedUsers.isEmpty) return; | 1572 if (dominatedUsers.isEmpty) return; |
| 1571 | 1573 |
| 1572 HTypeKnown newInput = new HTypeKnown(convertedType, input); | 1574 HTypeKnown newInput = new HTypeKnown.pinned(convertedType, input); |
| 1573 dominator.addBefore(dominator.first, newInput); | 1575 dominator.addBefore(dominator.first, newInput); |
| 1574 dominatedUsers.forEach((HInstruction user) { | 1576 dominatedUsers.forEach((HInstruction user) { |
| 1575 user.changeUse(input, newInput); | 1577 user.changeUse(input, newInput); |
| 1576 }); | 1578 }); |
| 1577 } | 1579 } |
| 1578 | 1580 |
| 1579 void visitIs(HIs instruction) { | 1581 void visitIs(HIs instruction) { |
| 1580 DartType type = instruction.typeExpression; | 1582 DartType type = instruction.typeExpression; |
| 1581 Element element = type.element; | 1583 Element element = type.element; |
| 1582 if (!instruction.isRawCheck) { | 1584 if (!instruction.isRawCheck) { |
| 1583 return; | 1585 return; |
| 1584 } else if (element.isTypedef()) { | 1586 } else if (element.isTypedef()) { |
| 1585 return; | 1587 return; |
| 1586 } | 1588 } |
| 1587 | 1589 |
| 1588 List<HInstruction> ifUsers = <HInstruction>[]; | 1590 List<HInstruction> ifUsers = <HInstruction>[]; |
| 1589 List<HInstruction> notIfUsers = <HInstruction>[]; | 1591 List<HInstruction> notIfUsers = <HInstruction>[]; |
| 1590 | 1592 |
| 1591 collectIfUsers(instruction, ifUsers, notIfUsers); | 1593 collectIfUsers(instruction, ifUsers, notIfUsers); |
| 1592 | 1594 |
| 1593 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; | 1595 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; |
| 1594 | 1596 |
| 1595 TypeMask convertedType = new TypeMask.nonNullSubtype(element); | 1597 TypeMask convertedType = new TypeMask.nonNullSubtype(element); |
| 1596 HInstruction input = instruction.expression; | 1598 HInstruction input = instruction.expression; |
| 1597 | 1599 |
| 1598 for (HIf ifUser in ifUsers) { | 1600 for (HIf ifUser in ifUsers) { |
| 1599 changeUsesDominatedBy(ifUser.thenBlock, input, convertedType); | 1601 insertTypePropagationForDominatedUsers(ifUser.thenBlock, input, |
| 1602 convertedType); |
| 1600 // TODO(ngeoffray): Also change uses for the else block on a type | 1603 // TODO(ngeoffray): Also change uses for the else block on a type |
| 1601 // that knows it is not of a specific type. | 1604 // that knows it is not of a specific type. |
| 1602 } | 1605 } |
| 1603 for (HIf ifUser in notIfUsers) { | 1606 for (HIf ifUser in notIfUsers) { |
| 1604 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); | 1607 insertTypePropagationForDominatedUsers(ifUser.elseBlock, input, |
| 1608 convertedType); |
| 1605 // TODO(ngeoffray): Also change uses for the then block on a type | 1609 // TODO(ngeoffray): Also change uses for the then block on a type |
| 1606 // that knows it is not of a specific type. | 1610 // that knows it is not of a specific type. |
| 1607 } | 1611 } |
| 1608 } | 1612 } |
| 1609 | 1613 |
| 1610 void visitIdentity(HIdentity instruction) { | 1614 void visitIdentity(HIdentity instruction) { |
| 1611 // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch. | 1615 // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch. |
| 1612 HInstruction left = instruction.left; | 1616 HInstruction left = instruction.left; |
| 1613 HInstruction right = instruction.right; | 1617 HInstruction right = instruction.right; |
| 1614 HInstruction input; | 1618 HInstruction input; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1626 List<HInstruction> ifUsers = <HInstruction>[]; | 1630 List<HInstruction> ifUsers = <HInstruction>[]; |
| 1627 List<HInstruction> notIfUsers = <HInstruction>[]; | 1631 List<HInstruction> notIfUsers = <HInstruction>[]; |
| 1628 | 1632 |
| 1629 collectIfUsers(instruction, ifUsers, notIfUsers); | 1633 collectIfUsers(instruction, ifUsers, notIfUsers); |
| 1630 | 1634 |
| 1631 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; | 1635 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; |
| 1632 | 1636 |
| 1633 TypeMask nonNullType = input.instructionType.nonNullable(); | 1637 TypeMask nonNullType = input.instructionType.nonNullable(); |
| 1634 | 1638 |
| 1635 for (HIf ifUser in ifUsers) { | 1639 for (HIf ifUser in ifUsers) { |
| 1636 changeUsesDominatedBy(ifUser.elseBlock, input, nonNullType); | 1640 insertTypePropagationForDominatedUsers(ifUser.elseBlock, input, |
| 1641 nonNullType); |
| 1637 // Uses in thenBlock are `null`, but probably not common. | 1642 // Uses in thenBlock are `null`, but probably not common. |
| 1638 } | 1643 } |
| 1639 for (HIf ifUser in notIfUsers) { | 1644 for (HIf ifUser in notIfUsers) { |
| 1640 changeUsesDominatedBy(ifUser.thenBlock, input, nonNullType); | 1645 insertTypePropagationForDominatedUsers(ifUser.thenBlock, input, |
| 1646 nonNullType); |
| 1641 // Uses in elseBlock are `null`, but probably not common. | 1647 // Uses in elseBlock are `null`, but probably not common. |
| 1642 } | 1648 } |
| 1643 } | 1649 } |
| 1644 | 1650 |
| 1645 collectIfUsers(HInstruction instruction, | 1651 collectIfUsers(HInstruction instruction, |
| 1646 List<HInstruction> ifUsers, | 1652 List<HInstruction> ifUsers, |
| 1647 List<HInstruction> notIfUsers) { | 1653 List<HInstruction> notIfUsers) { |
| 1648 for (HInstruction user in instruction.usedBy) { | 1654 for (HInstruction user in instruction.usedBy) { |
| 1649 if (user is HIf) { | 1655 if (user is HIf) { |
| 1650 ifUsers.add(user); | 1656 ifUsers.add(user); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2089 | 2095 |
| 2090 keyedValues.forEach((receiver, values) { | 2096 keyedValues.forEach((receiver, values) { |
| 2091 result.keyedValues[receiver] = | 2097 result.keyedValues[receiver] = |
| 2092 new Map<HInstruction, HInstruction>.from(values); | 2098 new Map<HInstruction, HInstruction>.from(values); |
| 2093 }); | 2099 }); |
| 2094 | 2100 |
| 2095 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2101 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2096 return result; | 2102 return result; |
| 2097 } | 2103 } |
| 2098 } | 2104 } |
| OLD | NEW |