Index: sdk/lib/_internal/compiler/implementation/ssa/optimize.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart |
index bea5bd525b5e9c4625196a35da3213a13cdeb562..89a6db057cca006e0e5bdd93a7768fdcec661b01 100644 |
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart |
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart |
@@ -16,6 +16,7 @@ class SsaOptimizerTask extends CompilerTask { |
super(backend.compiler); |
String get name => 'SSA optimizer'; |
Compiler get compiler => backend.compiler; |
+ Map<HInstruction, Range> ranges = <HInstruction, Range>{}; |
void runPhases(HGraph graph, List<OptimizationPhase> phases) { |
for (OptimizationPhase phase in phases) { |
@@ -66,17 +67,24 @@ class SsaOptimizerTask extends CompilerTask { |
new SsaInstructionSimplifier(constantSystem, backend, work), |
new SsaCheckInserter(backend, work, context.boundsChecked), |
new SsaSimplifyInterceptors(compiler, constantSystem, work), |
- dce = new SsaDeadCodeEliminator(compiler)]; |
+ dce = new SsaDeadCodeEliminator(compiler), |
+ new SsaTypePropagator(compiler)]; |
runPhases(graph, phases); |
- if (!dce.eliminatedSideEffects) return; |
- phases = <OptimizationPhase>[ |
- new SsaGlobalValueNumberer(compiler), |
- new SsaCodeMotion(), |
- new SsaValueRangeAnalyzer(compiler, constantSystem, work), |
- new SsaInstructionSimplifier(constantSystem, backend, work), |
- new SsaCheckInserter(backend, work, context.boundsChecked), |
- new SsaSimplifyInterceptors(compiler, constantSystem, work), |
- new SsaDeadCodeEliminator(compiler)]; |
+ if (dce.eliminatedSideEffects) { |
+ phases = <OptimizationPhase>[ |
+ new SsaGlobalValueNumberer(compiler), |
+ new SsaCodeMotion(), |
+ new SsaValueRangeAnalyzer(compiler, constantSystem, work), |
+ new SsaInstructionSimplifier(constantSystem, backend, work), |
+ new SsaCheckInserter(backend, work, context.boundsChecked), |
+ new SsaSimplifyInterceptors(compiler, constantSystem, work), |
+ new SsaDeadCodeEliminator(compiler)]; |
+ } else { |
+ phases = <OptimizationPhase>[ |
+ // Run the simplifier to remove unneeded type checks inserted |
+ // by type propagation. |
+ new SsaInstructionSimplifier(constantSystem, backend, work)]; |
+ } |
runPhases(graph, phases); |
}); |
} |
@@ -941,7 +949,7 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
} |
void visitGraph(HGraph graph) { |
- analyzer = new SsaLiveBlockAnalyzer(graph); |
+ analyzer = new SsaLiveBlockAnalyzer(graph, compiler); |
analyzer.analyze(); |
visitPostDominatorTree(graph); |
cleanPhis(graph); |
@@ -969,6 +977,14 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
void cleanPhis(HGraph graph) { |
L: for (HBasicBlock block in graph.blocks) { |
List<HBasicBlock> predecessors = block.predecessors; |
+ // Zap all inputs to phis that correspond to dead blocks. |
+ block.forEachPhi((HPhi phi) { |
+ for (int i = 0; i < phi.inputs.length; ++i) { |
+ if (!predecessors[i].isLive && phi.inputs[i] != zapInstruction) { |
+ replaceInput(i, phi, zapInstruction); |
+ } |
+ } |
+ }); |
if (predecessors.length < 2) continue L; |
// Find the index of the single live predecessor if it exists. |
int indexOfLive = -1; |
@@ -991,6 +1007,12 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
} |
} |
+ void replaceInput(int i, HInstruction from, HInstruction by) { |
+ from.inputs[i].usedBy.remove(from); |
+ from.inputs[i] = by; |
+ by.usedBy.add(from); |
+ } |
+ |
void removeUsers(HInstruction instruction) { |
instruction.usedBy.forEach((user) { |
removeInput(user, instruction); |
@@ -1002,9 +1024,8 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
List<HInstruction> inputs = user.inputs; |
for (int i = 0, length = inputs.length; i < length; i++) { |
if (input == inputs[i]) { |
- HInstruction zap = zapInstruction; |
- inputs[i] = zap; |
- zap.usedBy.add(user); |
+ user.inputs[i] = zapInstruction; |
+ zapInstruction.usedBy.add(user); |
} |
} |
} |
@@ -1012,9 +1033,14 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
class SsaLiveBlockAnalyzer extends HBaseVisitor { |
final HGraph graph; |
+ final Compiler compiler; |
final Set<HBasicBlock> live = new Set<HBasicBlock>(); |
final List<HBasicBlock> worklist = <HBasicBlock>[]; |
- SsaLiveBlockAnalyzer(this.graph); |
+ |
+ SsaLiveBlockAnalyzer(this.graph, this.compiler); |
+ |
+ JavaScriptBackend get backend => compiler.backend; |
+ Map<HInstruction, Range> get ranges => backend.optimizer.ranges; |
bool isDeadBlock(HBasicBlock block) => !live.contains(block); |
@@ -1049,6 +1075,40 @@ class SsaLiveBlockAnalyzer extends HBaseVisitor { |
visitControlFlow(instruction); |
} |
} |
+ |
+ void visitSwitch(HSwitch node) { |
+ if (!node.isTotal && node.expression.isInteger(compiler)) { |
+ Range switchRange = ranges[node.expression]; |
+ if (switchRange != null && |
+ switchRange.lower is IntValue && |
+ switchRange.upper is IntValue) { |
+ IntValue lowerValue = switchRange.lower; |
+ IntValue upperValue = switchRange.upper; |
+ int lower = lowerValue.value; |
+ int upper = upperValue.value; |
+ Set<int> liveLabels = new Set<int>(); |
+ for (int pos = 1; pos < node.inputs.length; pos++) { |
+ HConstant input = node.inputs[pos]; |
+ if (!input.isConstantInteger()) continue; |
+ IntConstant constant = input.constant; |
+ int label = constant.value; |
+ if (!liveLabels.contains(label) && |
+ label <= upper && |
+ label >= lower) { |
+ markBlockLive(node.block.successors[pos - 1]); |
+ liveLabels.add(label); |
+ } |
+ } |
+ if (liveLabels.length != upper - lower + 1) { |
+ markBlockLive(node.defaultTarget); |
+ } else { |
+ node.isTotal = true; |
+ } |
+ return; |
+ } |
+ } |
+ visitControlFlow(node); |
+ } |
} |
class SsaDeadPhiEliminator implements OptimizationPhase { |