| Index: pkg/compiler/lib/src/ssa/optimize.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
|
| index 4b5679b33c1a4fe9666c5feaa8d8b5992a7500c2..b15ef7b0c1cc32754d03aa7f9b53ecb988affe54 100644
|
| --- a/pkg/compiler/lib/src/ssa/optimize.dart
|
| +++ b/pkg/compiler/lib/src/ssa/optimize.dart
|
| @@ -1623,6 +1623,7 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
|
| instruction = previous;
|
| }
|
| block.forEachPhi(simplifyPhi);
|
| + evacuateTakenBranch(block);
|
| }
|
|
|
| void simplifyPhi(HPhi phi) {
|
| @@ -1702,6 +1703,30 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
|
| return null;
|
| }
|
|
|
| + /// If [block] is an always-taken branch, move the code from the taken branch
|
| + /// into [block]. This has the effect of making the instructions available for
|
| + /// further optimizations by moving them to a position that dominates the join
|
| + /// point of the if-then-else.
|
| + // TODO(29475): Delete dead blocks instead.
|
| + void evacuateTakenBranch(HBasicBlock block) {
|
| + if (!block.isLive) return;
|
| + HControlFlow branch = block.last;
|
| + if (branch is HIf) {
|
| + if (branch.thenBlock.isLive == branch.elseBlock.isLive) return;
|
| + assert(branch.condition.isConstant());
|
| + HBasicBlock target =
|
| + branch.thenBlock.isLive ? branch.thenBlock : branch.elseBlock;
|
| + HInstruction instruction = target.first;
|
| + while (!instruction.isControlFlow()) {
|
| + HInstruction next = instruction.next;
|
| + if (instruction is HTypeKnown && instruction.isPinned) break;
|
| + instruction.block.detach(instruction);
|
| + block.moveAtExit(instruction);
|
| + instruction = next;
|
| + }
|
| + }
|
| + }
|
| +
|
| void cleanPhis() {
|
| L:
|
| for (HBasicBlock block in _graph.blocks) {
|
|
|