Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| 11 | 11 |
| 12 class SsaOptimizerTask extends CompilerTask { | 12 class SsaOptimizerTask extends CompilerTask { |
| 13 final JavaScriptBackend backend; | 13 final JavaScriptBackend backend; |
| 14 SsaOptimizerTask(JavaScriptBackend backend) | 14 SsaOptimizerTask(JavaScriptBackend backend) |
| 15 : this.backend = backend, | 15 : this.backend = backend, |
| 16 super(backend.compiler); | 16 super(backend.compiler); |
| 17 String get name => 'SSA optimizer'; | 17 String get name => 'SSA optimizer'; |
| 18 Compiler get compiler => backend.compiler; | 18 Compiler get compiler => backend.compiler; |
| 19 Map<HInstruction, Range> ranges = <HInstruction, Range>{}; | |
| 19 | 20 |
| 20 void runPhases(HGraph graph, List<OptimizationPhase> phases) { | 21 void runPhases(HGraph graph, List<OptimizationPhase> phases) { |
| 21 for (OptimizationPhase phase in phases) { | 22 for (OptimizationPhase phase in phases) { |
| 22 runPhase(graph, phase); | 23 runPhase(graph, phase); |
| 23 } | 24 } |
| 24 } | 25 } |
| 25 | 26 |
| 26 void runPhase(HGraph graph, OptimizationPhase phase) { | 27 void runPhase(HGraph graph, OptimizationPhase phase) { |
| 27 phase.visitGraph(graph); | 28 phase.visitGraph(graph); |
| 28 compiler.tracer.traceGraph(phase.name, graph); | 29 compiler.tracer.traceGraph(phase.name, graph); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 59 new SsaCodeMotion(), | 60 new SsaCodeMotion(), |
| 60 new SsaLoadElimination(compiler), | 61 new SsaLoadElimination(compiler), |
| 61 new SsaDeadPhiEliminator(), | 62 new SsaDeadPhiEliminator(), |
| 62 new SsaTypePropagator(compiler), | 63 new SsaTypePropagator(compiler), |
| 63 new SsaValueRangeAnalyzer(compiler, constantSystem, work), | 64 new SsaValueRangeAnalyzer(compiler, constantSystem, work), |
| 64 // Previous optimizations may have generated new | 65 // Previous optimizations may have generated new |
| 65 // opportunities for instruction simplification. | 66 // opportunities for instruction simplification. |
| 66 new SsaInstructionSimplifier(constantSystem, backend, work), | 67 new SsaInstructionSimplifier(constantSystem, backend, work), |
| 67 new SsaCheckInserter(backend, work, context.boundsChecked), | 68 new SsaCheckInserter(backend, work, context.boundsChecked), |
| 68 new SsaSimplifyInterceptors(compiler, constantSystem, work), | 69 new SsaSimplifyInterceptors(compiler, constantSystem, work), |
| 69 dce = new SsaDeadCodeEliminator(compiler)]; | 70 dce = new SsaDeadCodeEliminator(compiler), |
| 71 new SsaTypePropagator(compiler)]; | |
| 70 runPhases(graph, phases); | 72 runPhases(graph, phases); |
| 71 if (!dce.eliminatedSideEffects) return; | 73 if (dce.eliminatedSideEffects) { |
| 72 phases = <OptimizationPhase>[ | 74 phases = <OptimizationPhase>[ |
| 73 new SsaGlobalValueNumberer(compiler), | 75 new SsaGlobalValueNumberer(compiler), |
| 74 new SsaCodeMotion(), | 76 new SsaCodeMotion(), |
| 75 new SsaValueRangeAnalyzer(compiler, constantSystem, work), | 77 new SsaValueRangeAnalyzer(compiler, constantSystem, work), |
| 76 new SsaInstructionSimplifier(constantSystem, backend, work), | 78 new SsaInstructionSimplifier(constantSystem, backend, work), |
| 77 new SsaCheckInserter(backend, work, context.boundsChecked), | 79 new SsaCheckInserter(backend, work, context.boundsChecked), |
| 78 new SsaSimplifyInterceptors(compiler, constantSystem, work), | 80 new SsaSimplifyInterceptors(compiler, constantSystem, work), |
| 79 new SsaDeadCodeEliminator(compiler)]; | 81 new SsaDeadCodeEliminator(compiler)]; |
| 82 } else { | |
| 83 phases = <OptimizationPhase>[ | |
| 84 // Run the simplifier to remove unneeded type checks inserted | |
| 85 // by type propagation. | |
| 86 new SsaInstructionSimplifier(constantSystem, backend, work)]; | |
| 87 } | |
| 80 runPhases(graph, phases); | 88 runPhases(graph, phases); |
| 81 }); | 89 }); |
| 82 } | 90 } |
| 83 } | 91 } |
| 84 | 92 |
| 85 bool isFixedLength(mask, Compiler compiler) { | 93 bool isFixedLength(mask, Compiler compiler) { |
| 86 JavaScriptBackend backend = compiler.backend; | 94 JavaScriptBackend backend = compiler.backend; |
| 87 if (mask.isContainer && mask.length != null) { | 95 if (mask.isContainer && mask.length != null) { |
| 88 // A container on which we have inferred the length. | 96 // A container on which we have inferred the length. |
| 89 return true; | 97 return true; |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 934 && instruction.onlyThrowsNSM() | 942 && instruction.onlyThrowsNSM() |
| 935 && hasFollowingThrowingNSM(instruction)) { | 943 && hasFollowingThrowingNSM(instruction)) { |
| 936 return true; | 944 return true; |
| 937 } | 945 } |
| 938 return !instruction.canThrow() | 946 return !instruction.canThrow() |
| 939 && instruction is !HParameterValue | 947 && instruction is !HParameterValue |
| 940 && instruction is !HLocalSet; | 948 && instruction is !HLocalSet; |
| 941 } | 949 } |
| 942 | 950 |
| 943 void visitGraph(HGraph graph) { | 951 void visitGraph(HGraph graph) { |
| 944 analyzer = new SsaLiveBlockAnalyzer(graph); | 952 analyzer = new SsaLiveBlockAnalyzer(graph, compiler); |
| 945 analyzer.analyze(); | 953 analyzer.analyze(); |
| 946 visitPostDominatorTree(graph); | 954 visitPostDominatorTree(graph); |
| 947 cleanPhis(graph); | 955 cleanPhis(graph); |
| 948 } | 956 } |
| 949 | 957 |
| 950 void visitBasicBlock(HBasicBlock block) { | 958 void visitBasicBlock(HBasicBlock block) { |
| 951 bool isDeadBlock = analyzer.isDeadBlock(block); | 959 bool isDeadBlock = analyzer.isDeadBlock(block); |
| 952 block.isLive = !isDeadBlock; | 960 block.isLive = !isDeadBlock; |
| 953 // Start from the last non-control flow instruction in the block. | 961 // Start from the last non-control flow instruction in the block. |
| 954 HInstruction instruction = block.last.previous; | 962 HInstruction instruction = block.last.previous; |
| 955 while (instruction != null) { | 963 while (instruction != null) { |
| 956 var previous = instruction.previous; | 964 var previous = instruction.previous; |
| 957 if (isDeadBlock) { | 965 if (isDeadBlock) { |
| 958 eliminatedSideEffects = eliminatedSideEffects || | 966 eliminatedSideEffects = eliminatedSideEffects || |
| 959 instruction.sideEffects.hasSideEffects(); | 967 instruction.sideEffects.hasSideEffects(); |
| 960 removeUsers(instruction); | 968 removeUsers(instruction); |
| 961 block.remove(instruction); | 969 block.remove(instruction); |
| 962 } else if (isDeadCode(instruction)) { | 970 } else if (isDeadCode(instruction)) { |
| 963 block.remove(instruction); | 971 block.remove(instruction); |
| 964 } | 972 } |
| 965 instruction = previous; | 973 instruction = previous; |
| 966 } | 974 } |
| 967 } | 975 } |
| 968 | 976 |
| 969 void cleanPhis(HGraph graph) { | 977 void cleanPhis(HGraph graph) { |
| 970 L: for (HBasicBlock block in graph.blocks) { | 978 L: for (HBasicBlock block in graph.blocks) { |
| 971 List<HBasicBlock> predecessors = block.predecessors; | 979 List<HBasicBlock> predecessors = block.predecessors; |
| 980 // Zap all inputs to phis that correspond to dead blocks, | |
| 981 // unless they have been zapped before. | |
| 982 block.forEachPhi((HPhi phi) { | |
| 983 for (int i = 0; i < phi.inputs.length; ++i) { | |
| 984 if (!predecessors[i].isLive && | |
| 985 phi.inputs[i] != zapInstruction) { | |
| 986 phi.inputs[i].usedBy.remove(phi); | |
| 987 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.
| |
| 988 phi.inputs[i] = zap; | |
| 989 zap.usedBy.add(phi); | |
| 990 } | |
| 991 } | |
| 992 }); | |
| 972 if (predecessors.length < 2) continue L; | 993 if (predecessors.length < 2) continue L; |
| 973 // Find the index of the single live predecessor if it exists. | 994 // Find the index of the single live predecessor if it exists. |
| 974 int indexOfLive = -1; | 995 int indexOfLive = -1; |
| 975 for (int i = 0; i < predecessors.length; i++) { | 996 for (int i = 0; i < predecessors.length; i++) { |
| 976 if (predecessors[i].isLive) { | 997 if (predecessors[i].isLive) { |
| 977 if (indexOfLive >= 0) continue L; | 998 if (indexOfLive >= 0) continue L; |
| 978 indexOfLive = i; | 999 indexOfLive = i; |
| 979 } | 1000 } |
| 980 } | 1001 } |
| 981 // Run through the phis of the block and replace them with their input | 1002 // Run through the phis of the block and replace them with their input |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1005 HInstruction zap = zapInstruction; | 1026 HInstruction zap = zapInstruction; |
| 1006 inputs[i] = zap; | 1027 inputs[i] = zap; |
| 1007 zap.usedBy.add(user); | 1028 zap.usedBy.add(user); |
| 1008 } | 1029 } |
| 1009 } | 1030 } |
| 1010 } | 1031 } |
| 1011 } | 1032 } |
| 1012 | 1033 |
| 1013 class SsaLiveBlockAnalyzer extends HBaseVisitor { | 1034 class SsaLiveBlockAnalyzer extends HBaseVisitor { |
| 1014 final HGraph graph; | 1035 final HGraph graph; |
| 1036 final Compiler compiler; | |
| 1015 final Set<HBasicBlock> live = new Set<HBasicBlock>(); | 1037 final Set<HBasicBlock> live = new Set<HBasicBlock>(); |
| 1016 final List<HBasicBlock> worklist = <HBasicBlock>[]; | 1038 final List<HBasicBlock> worklist = <HBasicBlock>[]; |
| 1017 SsaLiveBlockAnalyzer(this.graph); | 1039 |
| 1040 SsaLiveBlockAnalyzer(this.graph, this.compiler); | |
| 1041 | |
| 1042 Map<HInstruction, Range> get ranges => | |
| 1043 (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
| |
| 1018 | 1044 |
| 1019 bool isDeadBlock(HBasicBlock block) => !live.contains(block); | 1045 bool isDeadBlock(HBasicBlock block) => !live.contains(block); |
| 1020 | 1046 |
| 1021 void analyze() { | 1047 void analyze() { |
| 1022 markBlockLive(graph.entry); | 1048 markBlockLive(graph.entry); |
| 1023 while (!worklist.isEmpty) { | 1049 while (!worklist.isEmpty) { |
| 1024 HBasicBlock live = worklist.removeLast(); | 1050 HBasicBlock live = worklist.removeLast(); |
| 1025 live.last.accept(this); | 1051 live.last.accept(this); |
| 1026 } | 1052 } |
| 1027 } | 1053 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1042 if (condition.isConstant()) { | 1068 if (condition.isConstant()) { |
| 1043 if (condition.isConstantTrue()) { | 1069 if (condition.isConstantTrue()) { |
| 1044 markBlockLive(instruction.thenBlock); | 1070 markBlockLive(instruction.thenBlock); |
| 1045 } else { | 1071 } else { |
| 1046 markBlockLive(instruction.elseBlock); | 1072 markBlockLive(instruction.elseBlock); |
| 1047 } | 1073 } |
| 1048 } else { | 1074 } else { |
| 1049 visitControlFlow(instruction); | 1075 visitControlFlow(instruction); |
| 1050 } | 1076 } |
| 1051 } | 1077 } |
| 1078 | |
| 1079 void visitSwitch(HSwitch node) { | |
| 1080 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.
| |
| 1081 Range switchRange = ranges[node.inputs[0]]; | |
|
karlklose
2014/03/12 14:43:45
Ditto.
herhut
2014/03/13 13:27:45
Done.
| |
| 1082 if (switchRange != null && | |
| 1083 switchRange.lower is IntValue && | |
| 1084 switchRange.upper is IntValue) { | |
| 1085 IntValue lowerValue = switchRange.lower; | |
| 1086 IntValue upperValue = switchRange.upper; | |
| 1087 int lower = lowerValue.value; | |
| 1088 int upper = upperValue.value; | |
| 1089 Set<int> liveLabels = new Set<int>(); | |
| 1090 for (int pos = 1; pos < node.inputs.length; pos++) { | |
| 1091 HConstant input = node.inputs[pos]; | |
| 1092 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
| |
| 1093 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
| |
| 1094 int label = constant.value; | |
| 1095 if (!liveLabels.contains(label) && | |
| 1096 (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
| |
| 1097 (label >= lower)) { | |
|
karlklose
2014/03/12 14:43:45
Ditto.
herhut
2014/03/13 13:27:45
Done.
| |
| 1098 markBlockLive(node.block.successors[pos - 1]); | |
| 1099 liveLabels.add(label); | |
| 1100 } | |
| 1101 } | |
| 1102 if (liveLabels.length != upper - lower + 1) { | |
| 1103 markBlockLive(node.defaultTarget); | |
| 1104 } else { | |
| 1105 node.isTotal = true; | |
| 1106 } | |
| 1107 return; | |
| 1108 } | |
| 1109 } | |
| 1110 visitControlFlow(node); | |
| 1111 } | |
| 1052 } | 1112 } |
| 1053 | 1113 |
| 1054 class SsaDeadPhiEliminator implements OptimizationPhase { | 1114 class SsaDeadPhiEliminator implements OptimizationPhase { |
| 1055 final String name = "SsaDeadPhiEliminator"; | 1115 final String name = "SsaDeadPhiEliminator"; |
| 1056 | 1116 |
| 1057 void visitGraph(HGraph graph) { | 1117 void visitGraph(HGraph graph) { |
| 1058 final List<HPhi> worklist = <HPhi>[]; | 1118 final List<HPhi> worklist = <HPhi>[]; |
| 1059 // A set to keep track of the live phis that we found. | 1119 // A set to keep track of the live phis that we found. |
| 1060 final Set<HPhi> livePhis = new Set<HPhi>(); | 1120 final Set<HPhi> livePhis = new Set<HPhi>(); |
| 1061 | 1121 |
| (...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1968 | 2028 |
| 1969 keyedValues.forEach((receiver, values) { | 2029 keyedValues.forEach((receiver, values) { |
| 1970 result.keyedValues[receiver] = | 2030 result.keyedValues[receiver] = |
| 1971 new Map<HInstruction, HInstruction>.from(values); | 2031 new Map<HInstruction, HInstruction>.from(values); |
| 1972 }); | 2032 }); |
| 1973 | 2033 |
| 1974 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2034 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 1975 return result; | 2035 return result; |
| 1976 } | 2036 } |
| 1977 } | 2037 } |
| OLD | NEW |