Chromium Code Reviews| 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..277cdbb46f94a34cef8e64a452368d9b692457f6 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,19 @@ 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, |
| + // unless they have been zapped before. |
| + block.forEachPhi((HPhi phi) { |
| + for (int i = 0; i < phi.inputs.length; ++i) { |
| + if (!predecessors[i].isLive && |
| + phi.inputs[i] != zapInstruction) { |
| + phi.inputs[i].usedBy.remove(phi); |
| + HInstruction zap = zapInstruction; |
|
karlklose
2014/03/12 14:43:45
Is this a performance optimization? I would prefer
herhut
2014/03/13 13:27:45
Done.
|
| + phi.inputs[i] = zap; |
| + zap.usedBy.add(phi); |
| + } |
| + } |
| + }); |
| if (predecessors.length < 2) continue L; |
| // Find the index of the single live predecessor if it exists. |
| int indexOfLive = -1; |
| @@ -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); |
| + |
| + Map<HInstruction, Range> get ranges => |
| + (this.compiler.backend as JavaScriptBackend).optimizer.ranges; |
|
karlklose
2014/03/12 14:43:45
If you added a 'backend' field of type JavaScriptB
herhut
2014/03/13 13:27:45
I need the compiler, too, so I have decided to jus
|
| 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.inputs[0].isInteger(compiler)) { |
|
karlklose
2014/03/12 14:43:45
'node.inputs[0]' -> 'node.expression'.
herhut
2014/03/13 13:27:45
Done.
|
| + Range switchRange = ranges[node.inputs[0]]; |
|
karlklose
2014/03/12 14:43:45
Ditto.
herhut
2014/03/13 13:27:45
Done.
|
| + 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]; |
| + assert(input.isConstantInteger()); |
|
karlklose
2014/03/12 14:43:45
I think this assertion is unnecessary, the code be
herhut
2014/03/13 13:27:45
You are probably right about the assert, it is a l
|
| + IntConstant constant = input.constant; |
|
floitsch
2014/03/12 16:20:25
Pay attention that "-0.0" is a double-constant but
herhut
2014/03/13 13:27:45
0.0 should be illegal in case statements (and hope
|
| + int label = constant.value; |
| + if (!liveLabels.contains(label) && |
| + (label <= upper) && |
|
karlklose
2014/03/12 14:43:45
No need for parentheses.
herhut
2014/03/13 13:27:45
I just like the visual grouping they provide. To k
|
| + (label >= lower)) { |
|
karlklose
2014/03/12 14:43:45
Ditto.
herhut
2014/03/13 13:27:45
Done.
|
| + 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 { |