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