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 |