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