| 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 |