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

Side by Side Diff: pkg/compiler/lib/src/ssa/optimize.dart

Issue 2823543002: dart2js: eliminate useless conditionals (Closed)
Patch Set: Created 3 years, 8 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
6 import '../common/names.dart' show Selectors; 6 import '../common/names.dart' show Selectors;
7 import '../common/tasks.dart' show CompilerTask; 7 import '../common/tasks.dart' show CompilerTask;
8 import '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
9 import '../constants/constant_system.dart'; 9 import '../constants/constant_system.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
(...skipping 1441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 check.inputs.add(minusOne); 1452 check.inputs.add(minusOne);
1453 minusOne.usedBy.add(check); 1453 minusOne.usedBy.add(check);
1454 } 1454 }
1455 } 1455 }
1456 1456
1457 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { 1457 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
1458 final String name = "SsaDeadCodeEliminator"; 1458 final String name = "SsaDeadCodeEliminator";
1459 1459
1460 final ClosedWorld closedWorld; 1460 final ClosedWorld closedWorld;
1461 final SsaOptimizerTask optimizer; 1461 final SsaOptimizerTask optimizer;
1462 HGraph _graph;
1462 SsaLiveBlockAnalyzer analyzer; 1463 SsaLiveBlockAnalyzer analyzer;
1463 Map<HInstruction, bool> trivialDeadStoreReceivers = 1464 Map<HInstruction, bool> trivialDeadStoreReceivers =
1464 new Maplet<HInstruction, bool>(); 1465 new Maplet<HInstruction, bool>();
1465 bool eliminatedSideEffects = false; 1466 bool eliminatedSideEffects = false;
1466 1467
1467 SsaDeadCodeEliminator(this.closedWorld, this.optimizer); 1468 SsaDeadCodeEliminator(this.closedWorld, this.optimizer);
1468 1469
1469 HInstruction zapInstructionCache; 1470 HInstruction zapInstructionCache;
1470 HInstruction get zapInstruction { 1471 HInstruction get zapInstruction {
1471 if (zapInstructionCache == null) { 1472 if (zapInstructionCache == null) {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 instruction.onlyThrowsNSM() && 1590 instruction.onlyThrowsNSM() &&
1590 hasFollowingThrowingNSM(instruction)) { 1591 hasFollowingThrowingNSM(instruction)) {
1591 return true; 1592 return true;
1592 } 1593 }
1593 return !instruction.canThrow() && 1594 return !instruction.canThrow() &&
1594 instruction is! HParameterValue && 1595 instruction is! HParameterValue &&
1595 instruction is! HLocalSet; 1596 instruction is! HLocalSet;
1596 } 1597 }
1597 1598
1598 void visitGraph(HGraph graph) { 1599 void visitGraph(HGraph graph) {
1600 _graph = graph;
1599 analyzer = new SsaLiveBlockAnalyzer(graph, closedWorld, optimizer); 1601 analyzer = new SsaLiveBlockAnalyzer(graph, closedWorld, optimizer);
1600 analyzer.analyze(); 1602 analyzer.analyze();
1601 visitPostDominatorTree(graph); 1603 visitPostDominatorTree(graph);
1602 cleanPhis(graph); 1604 cleanPhis();
1603 } 1605 }
1604 1606
1605 void visitBasicBlock(HBasicBlock block) { 1607 void visitBasicBlock(HBasicBlock block) {
1606 bool isDeadBlock = analyzer.isDeadBlock(block); 1608 bool isDeadBlock = analyzer.isDeadBlock(block);
1607 block.isLive = !isDeadBlock; 1609 block.isLive = !isDeadBlock;
1610 simplifyControlFlow(block);
1608 // Start from the last non-control flow instruction in the block. 1611 // Start from the last non-control flow instruction in the block.
1609 HInstruction instruction = block.last.previous; 1612 HInstruction instruction = block.last.previous;
1610 while (instruction != null) { 1613 while (instruction != null) {
1611 var previous = instruction.previous; 1614 var previous = instruction.previous;
1612 if (isDeadBlock) { 1615 if (isDeadBlock) {
1613 eliminatedSideEffects = 1616 eliminatedSideEffects =
1614 eliminatedSideEffects || instruction.sideEffects.hasSideEffects(); 1617 eliminatedSideEffects || instruction.sideEffects.hasSideEffects();
1615 removeUsers(instruction); 1618 removeUsers(instruction);
1616 block.remove(instruction); 1619 block.remove(instruction);
1617 } else if (isDeadCode(instruction)) { 1620 } else if (isDeadCode(instruction)) {
1618 block.remove(instruction); 1621 block.remove(instruction);
1619 } 1622 }
1620 instruction = previous; 1623 instruction = previous;
1621 } 1624 }
1625 block.forEachPhi(simplifyPhi);
1622 } 1626 }
1623 1627
1624 void cleanPhis(HGraph graph) { 1628 void simplifyPhi(HPhi phi) {
1629 // If the phi is of the form `phi(x, HTypeKnown(x))`, it does not strengthen
1630 // `x`. We can replace the phi with `x` to potentially make the HTypeKnown
1631 // refinement node dead and potentially make a HIf control no HPhis.
1632
1633 // TODO(sra): Implement version of this test that works for a subgraph of
1634 // HPhi nodes.
1635 HInstruction base = null;
1636 bool seenUnrefinedBase = false;
1637 for (HInstruction input in phi.inputs) {
1638 HInstruction value = input;
1639 while (value is HTypeKnown) {
1640 HTypeKnown refinement = value;
1641 value = refinement.checkedInput;
1642 }
1643 if (value == input) seenUnrefinedBase = true;
1644 base ??= value;
1645 if (base != value) return;
1646 }
1647
1648 if (seenUnrefinedBase) {
1649 HBasicBlock block = phi.block;
1650 block.rewrite(phi, base);
1651 block.removePhi(phi);
1652 }
1653 }
1654
1655 void simplifyControlFlow(HBasicBlock block) {
1656 HControlFlow instruction = block.last;
1657 if (instruction is HIf) {
1658 HInstruction condition = instruction.condition;
1659 if (condition.isConstant()) return;
1660
1661 // We want to remove an if-then-else diamond when the then- and else-
1662 // branches are empty and the condition does not control a HPhi. We cannot
1663 // change the CFG structure so we replace the HIf condition with a
1664 // constant. This may leave the original condition unused. i.e. a
1665 // candidate for being dead code.
1666
1667 List<HBasicBlock> dominated = block.dominatedBlocks;
1668 // Diamond-like control flow dominates the then-, else- and join- blocks.
1669 if (dominated.length != 3) return;
1670 HBasicBlock join = dominated.last;
1671 if (!join.phis.isEmpty) return; // condition controls a phi.
1672 // Ignore exit block - usually the join in `if (...) return ...`
1673 if (join.isExitBlock()) return;
1674
1675 int thenSize = measureEmptyInterval(instruction.thenBlock, join);
1676 if (thenSize == null) return;
1677 int elseSize = measureEmptyInterval(instruction.elseBlock, join);
1678 if (elseSize == null) return;
1679
1680 // Pick the 'live' branch to be the smallest subgraph.
1681 bool value = thenSize <= elseSize;
1682 HInstruction newCondition = _graph.addConstantBool(value, closedWorld);
1683 instruction.inputs[0] = newCondition;
1684 condition.usedBy.remove(instruction);
1685 newCondition.usedBy.add(instruction);
1686 }
1687 }
1688
1689 /// Returns the number of blocks from [start] up to but not including [end].
1690 /// Returns `null` if any of the blocks is non-empty (other than control
1691 /// flow). Returns `null` if there is an exit from the region other than
1692 /// [end] or via control flow other than HGoto and HIf.
1693 int measureEmptyInterval(HBasicBlock start, HBasicBlock end) {
1694 if (start.first != start.last) return null; // start is not empty.
1695 // Do a simple single-block region test first.
1696 if (start.last is HGoto &&
1697 start.successors.length == 1 &&
1698 start.successors.single == end) {
1699 return 1;
1700 }
1701 // TODO(sra): Implement fuller test.
1702 return null;
1703 }
1704
1705 void cleanPhis() {
1625 L: 1706 L:
1626 for (HBasicBlock block in graph.blocks) { 1707 for (HBasicBlock block in _graph.blocks) {
1627 List<HBasicBlock> predecessors = block.predecessors; 1708 List<HBasicBlock> predecessors = block.predecessors;
1628 // Zap all inputs to phis that correspond to dead blocks. 1709 // Zap all inputs to phis that correspond to dead blocks.
1629 block.forEachPhi((HPhi phi) { 1710 block.forEachPhi((HPhi phi) {
1630 for (int i = 0; i < phi.inputs.length; ++i) { 1711 for (int i = 0; i < phi.inputs.length; ++i) {
1631 if (!predecessors[i].isLive && phi.inputs[i] != zapInstruction) { 1712 if (!predecessors[i].isLive && phi.inputs[i] != zapInstruction) {
1632 replaceInput(i, phi, zapInstruction); 1713 replaceInput(i, phi, zapInstruction);
1633 } 1714 }
1634 } 1715 }
1635 }); 1716 });
1636 if (predecessors.length < 2) continue L; 1717 if (predecessors.length < 2) continue L;
(...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after
2870 2951
2871 keyedValues.forEach((receiver, values) { 2952 keyedValues.forEach((receiver, values) {
2872 result.keyedValues[receiver] = 2953 result.keyedValues[receiver] =
2873 new Map<HInstruction, HInstruction>.from(values); 2954 new Map<HInstruction, HInstruction>.from(values);
2874 }); 2955 });
2875 2956
2876 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2957 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2877 return result; 2958 return result;
2878 } 2959 }
2879 } 2960 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698