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 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 return instruction is HGoto | 1236 return instruction is HGoto |
1237 || instruction.inputs[0].isConstantTrue(); | 1237 || instruction.inputs[0].isConstantTrue(); |
1238 } | 1238 } |
1239 bool firstInstructionInLoop = block == loopHeader | 1239 bool firstInstructionInLoop = block == loopHeader |
1240 // Compensate for lack of code motion. | 1240 // Compensate for lack of code motion. |
1241 || (blockChangesFlags[loopHeader.id] == 0 | 1241 || (blockChangesFlags[loopHeader.id] == 0 |
1242 && isLoopAlwaysTaken() | 1242 && isLoopAlwaysTaken() |
1243 && loopHeader.successors[0] == block); | 1243 && loopHeader.successors[0] == block); |
1244 while (instruction != null) { | 1244 while (instruction != null) { |
1245 HInstruction next = instruction.next; | 1245 HInstruction next = instruction.next; |
1246 if (instruction.useGvn() | 1246 if (instruction.useGvn() && instruction.isMovable |
1247 && (!instruction.canThrow() || firstInstructionInLoop) | 1247 && (!instruction.canThrow() || firstInstructionInLoop) |
1248 && !instruction.sideEffects.dependsOn(dependsFlags)) { | 1248 && !instruction.sideEffects.dependsOn(dependsFlags)) { |
1249 bool loopInvariantInputs = true; | 1249 bool loopInvariantInputs = true; |
1250 List<HInstruction> inputs = instruction.inputs; | 1250 List<HInstruction> inputs = instruction.inputs; |
1251 for (int i = 0, length = inputs.length; i < length; i++) { | 1251 for (int i = 0, length = inputs.length; i < length; i++) { |
1252 if (isInputDefinedAfterDominator(inputs[i], preheader)) { | 1252 if (isInputDefinedAfterDominator(inputs[i], preheader)) { |
1253 loopInvariantInputs = false; | 1253 loopInvariantInputs = false; |
1254 break; | 1254 break; |
1255 } | 1255 } |
1256 } | 1256 } |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 // which instructions can be moved to a dominator block. | 1458 // which instructions can be moved to a dominator block. |
1459 ValueSet set_ = values[block.id]; | 1459 ValueSet set_ = values[block.id]; |
1460 HInstruction instruction = block.first; | 1460 HInstruction instruction = block.first; |
1461 int flags = 0; | 1461 int flags = 0; |
1462 while (instruction != null) { | 1462 while (instruction != null) { |
1463 int dependsFlags = SideEffects.computeDependsOnFlags(flags); | 1463 int dependsFlags = SideEffects.computeDependsOnFlags(flags); |
1464 flags |= instruction.sideEffects.getChangesFlags(); | 1464 flags |= instruction.sideEffects.getChangesFlags(); |
1465 | 1465 |
1466 HInstruction current = instruction; | 1466 HInstruction current = instruction; |
1467 instruction = instruction.next; | 1467 instruction = instruction.next; |
1468 | 1468 if (!current.useGvn() || !current.isMovable) continue; |
1469 // TODO(ngeoffray): this check is needed because we currently do | |
1470 // not have flags to express 'Gvn'able', but not movable. | |
1471 if (current is HCheck) continue; | |
1472 if (!current.useGvn()) continue; | |
1473 if (current.sideEffects.dependsOn(dependsFlags)) continue; | 1469 if (current.sideEffects.dependsOn(dependsFlags)) continue; |
1474 | 1470 |
1475 bool canBeMoved = true; | 1471 bool canBeMoved = true; |
1476 for (final HInstruction input in current.inputs) { | 1472 for (final HInstruction input in current.inputs) { |
1477 if (input.block == block) { | 1473 if (input.block == block) { |
1478 canBeMoved = false; | 1474 canBeMoved = false; |
1479 break; | 1475 break; |
1480 } | 1476 } |
1481 } | 1477 } |
1482 if (!canBeMoved) continue; | 1478 if (!canBeMoved) continue; |
(...skipping 14 matching lines...) Expand all Loading... |
1497 final String name = "SsaTypeconversionInserter"; | 1493 final String name = "SsaTypeconversionInserter"; |
1498 final Compiler compiler; | 1494 final Compiler compiler; |
1499 | 1495 |
1500 SsaTypeConversionInserter(this.compiler); | 1496 SsaTypeConversionInserter(this.compiler); |
1501 | 1497 |
1502 void visitGraph(HGraph graph) { | 1498 void visitGraph(HGraph graph) { |
1503 visitDominatorTree(graph); | 1499 visitDominatorTree(graph); |
1504 } | 1500 } |
1505 | 1501 |
1506 // Update users of [input] that are dominated by [:dominator.first:] | 1502 // Update users of [input] that are dominated by [:dominator.first:] |
1507 // to use [newInput] instead. | 1503 // to use [TypeKnown] of [input] instead. As the type information depends |
1508 void changeUsesDominatedBy(HBasicBlock dominator, | 1504 // on the control flow, we mark the inserted [HTypeKnown] nodes as |
1509 HInstruction input, | 1505 // non-movable. |
1510 TypeMask convertedType) { | 1506 void insertTypePropagationForDominatedUsers(HBasicBlock dominator, |
| 1507 HInstruction input, |
| 1508 TypeMask convertedType) { |
1511 Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first); | 1509 Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first); |
1512 if (dominatedUsers.isEmpty) return; | 1510 if (dominatedUsers.isEmpty) return; |
1513 | 1511 |
1514 HTypeKnown newInput = new HTypeKnown(convertedType, input); | 1512 HTypeKnown newInput = new HTypeKnown.pinned(convertedType, input); |
1515 dominator.addBefore(dominator.first, newInput); | 1513 dominator.addBefore(dominator.first, newInput); |
1516 dominatedUsers.forEach((HInstruction user) { | 1514 dominatedUsers.forEach((HInstruction user) { |
1517 user.changeUse(input, newInput); | 1515 user.changeUse(input, newInput); |
1518 }); | 1516 }); |
1519 } | 1517 } |
1520 | 1518 |
1521 void visitIs(HIs instruction) { | 1519 void visitIs(HIs instruction) { |
1522 DartType type = instruction.typeExpression; | 1520 DartType type = instruction.typeExpression; |
1523 Element element = type.element; | 1521 Element element = type.element; |
1524 if (!instruction.isRawCheck) { | 1522 if (!instruction.isRawCheck) { |
1525 return; | 1523 return; |
1526 } else if (element.isTypedef()) { | 1524 } else if (element.isTypedef()) { |
1527 return; | 1525 return; |
1528 } | 1526 } |
1529 | 1527 |
1530 List<HInstruction> ifUsers = <HInstruction>[]; | 1528 List<HInstruction> ifUsers = <HInstruction>[]; |
1531 List<HInstruction> notIfUsers = <HInstruction>[]; | 1529 List<HInstruction> notIfUsers = <HInstruction>[]; |
1532 | 1530 |
1533 collectIfUsers(instruction, ifUsers, notIfUsers); | 1531 collectIfUsers(instruction, ifUsers, notIfUsers); |
1534 | 1532 |
1535 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; | 1533 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; |
1536 | 1534 |
1537 TypeMask convertedType = new TypeMask.nonNullSubtype(element); | 1535 TypeMask convertedType = new TypeMask.nonNullSubtype(element); |
1538 HInstruction input = instruction.expression; | 1536 HInstruction input = instruction.expression; |
1539 | 1537 |
1540 for (HIf ifUser in ifUsers) { | 1538 for (HIf ifUser in ifUsers) { |
1541 changeUsesDominatedBy(ifUser.thenBlock, input, convertedType); | 1539 insertTypePropagationForDominatedUsers(ifUser.thenBlock, input, |
| 1540 convertedType); |
1542 // TODO(ngeoffray): Also change uses for the else block on a type | 1541 // TODO(ngeoffray): Also change uses for the else block on a type |
1543 // that knows it is not of a specific type. | 1542 // that knows it is not of a specific type. |
1544 } | 1543 } |
1545 for (HIf ifUser in notIfUsers) { | 1544 for (HIf ifUser in notIfUsers) { |
1546 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); | 1545 insertTypePropagationForDominatedUsers(ifUser.elseBlock, input, |
| 1546 convertedType); |
1547 // TODO(ngeoffray): Also change uses for the then block on a type | 1547 // TODO(ngeoffray): Also change uses for the then block on a type |
1548 // that knows it is not of a specific type. | 1548 // that knows it is not of a specific type. |
1549 } | 1549 } |
1550 } | 1550 } |
1551 | 1551 |
1552 void visitIdentity(HIdentity instruction) { | 1552 void visitIdentity(HIdentity instruction) { |
1553 // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch. | 1553 // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch. |
1554 HInstruction left = instruction.left; | 1554 HInstruction left = instruction.left; |
1555 HInstruction right = instruction.right; | 1555 HInstruction right = instruction.right; |
1556 HInstruction input; | 1556 HInstruction input; |
(...skipping 11 matching lines...) Expand all Loading... |
1568 List<HInstruction> ifUsers = <HInstruction>[]; | 1568 List<HInstruction> ifUsers = <HInstruction>[]; |
1569 List<HInstruction> notIfUsers = <HInstruction>[]; | 1569 List<HInstruction> notIfUsers = <HInstruction>[]; |
1570 | 1570 |
1571 collectIfUsers(instruction, ifUsers, notIfUsers); | 1571 collectIfUsers(instruction, ifUsers, notIfUsers); |
1572 | 1572 |
1573 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; | 1573 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; |
1574 | 1574 |
1575 TypeMask nonNullType = input.instructionType.nonNullable(); | 1575 TypeMask nonNullType = input.instructionType.nonNullable(); |
1576 | 1576 |
1577 for (HIf ifUser in ifUsers) { | 1577 for (HIf ifUser in ifUsers) { |
1578 changeUsesDominatedBy(ifUser.elseBlock, input, nonNullType); | 1578 insertTypePropagationForDominatedUsers(ifUser.elseBlock, input, |
| 1579 nonNullType); |
1579 // Uses in thenBlock are `null`, but probably not common. | 1580 // Uses in thenBlock are `null`, but probably not common. |
1580 } | 1581 } |
1581 for (HIf ifUser in notIfUsers) { | 1582 for (HIf ifUser in notIfUsers) { |
1582 changeUsesDominatedBy(ifUser.thenBlock, input, nonNullType); | 1583 insertTypePropagationForDominatedUsers(ifUser.thenBlock, input, |
| 1584 nonNullType); |
1583 // Uses in elseBlock are `null`, but probably not common. | 1585 // Uses in elseBlock are `null`, but probably not common. |
1584 } | 1586 } |
1585 } | 1587 } |
1586 | 1588 |
1587 collectIfUsers(HInstruction instruction, | 1589 collectIfUsers(HInstruction instruction, |
1588 List<HInstruction> ifUsers, | 1590 List<HInstruction> ifUsers, |
1589 List<HInstruction> notIfUsers) { | 1591 List<HInstruction> notIfUsers) { |
1590 for (HInstruction user in instruction.usedBy) { | 1592 for (HInstruction user in instruction.usedBy) { |
1591 if (user is HIf) { | 1593 if (user is HIf) { |
1592 ifUsers.add(user); | 1594 ifUsers.add(user); |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2031 | 2033 |
2032 keyedValues.forEach((receiver, values) { | 2034 keyedValues.forEach((receiver, values) { |
2033 result.keyedValues[receiver] = | 2035 result.keyedValues[receiver] = |
2034 new Map<HInstruction, HInstruction>.from(values); | 2036 new Map<HInstruction, HInstruction>.from(values); |
2035 }); | 2037 }); |
2036 | 2038 |
2037 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2039 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
2038 return result; | 2040 return result; |
2039 } | 2041 } |
2040 } | 2042 } |
OLD | NEW |