| 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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 6 import '../common/names.dart' show Selectors; | 6 import '../common/names.dart' show Selectors; |
| 7 import '../common/tasks.dart' show CompilerTask; | 7 import '../common/tasks.dart' show CompilerTask; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
| 9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 void runPhase(OptimizationPhase phase) { | 52 void runPhase(OptimizationPhase phase) { |
| 53 measureSubtask(phase.name, () => phase.visitGraph(graph)); | 53 measureSubtask(phase.name, () => phase.visitGraph(graph)); |
| 54 backend.tracer.traceGraph(phase.name, graph); | 54 backend.tracer.traceGraph(phase.name, graph); |
| 55 assert(graph.isValid()); | 55 assert(graph.isValid()); |
| 56 } | 56 } |
| 57 | 57 |
| 58 bool trustPrimitives = compiler.options.trustPrimitives; | 58 bool trustPrimitives = compiler.options.trustPrimitives; |
| 59 CodegenRegistry registry = work.registry; | 59 CodegenRegistry registry = work.registry; |
| 60 Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 60 Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| 61 SsaCodeMotion codeMotion; | 61 SsaCodeMotion codeMotion; |
| 62 SsaLoadElimination loadElimination; |
| 62 measure(() { | 63 measure(() { |
| 63 List<OptimizationPhase> phases = <OptimizationPhase>[ | 64 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 64 // Run trivial instruction simplification first to optimize | 65 // Run trivial instruction simplification first to optimize |
| 65 // some patterns useful for type conversion. | 66 // some patterns useful for type conversion. |
| 66 new SsaInstructionSimplifier(backend, closedWorld, this, registry), | 67 new SsaInstructionSimplifier(backend, closedWorld, this, registry), |
| 67 new SsaTypeConversionInserter(closedWorld), | 68 new SsaTypeConversionInserter(closedWorld), |
| 68 new SsaRedundantPhiEliminator(), | 69 new SsaRedundantPhiEliminator(), |
| 69 new SsaDeadPhiEliminator(), | 70 new SsaDeadPhiEliminator(), |
| 70 new SsaTypePropagator(compiler, closedWorld), | 71 new SsaTypePropagator(compiler, closedWorld), |
| 71 // After type propagation, more instructions can be | 72 // After type propagation, more instructions can be |
| 72 // simplified. | 73 // simplified. |
| 73 new SsaInstructionSimplifier(backend, closedWorld, this, registry), | 74 new SsaInstructionSimplifier(backend, closedWorld, this, registry), |
| 74 new SsaCheckInserter( | 75 new SsaCheckInserter( |
| 75 trustPrimitives, backend, closedWorld, boundsChecked), | 76 trustPrimitives, backend, closedWorld, boundsChecked), |
| 76 new SsaInstructionSimplifier(backend, closedWorld, this, registry), | 77 new SsaInstructionSimplifier(backend, closedWorld, this, registry), |
| 77 new SsaCheckInserter( | 78 new SsaCheckInserter( |
| 78 trustPrimitives, backend, closedWorld, boundsChecked), | 79 trustPrimitives, backend, closedWorld, boundsChecked), |
| 79 new SsaTypePropagator(compiler, closedWorld), | 80 new SsaTypePropagator(compiler, closedWorld), |
| 80 // Run a dead code eliminator before LICM because dead | 81 // Run a dead code eliminator before LICM because dead |
| 81 // interceptors are often in the way of LICM'able instructions. | 82 // interceptors are often in the way of LICM'able instructions. |
| 82 new SsaDeadCodeEliminator(closedWorld, this), | 83 new SsaDeadCodeEliminator(closedWorld, this), |
| 83 new SsaGlobalValueNumberer(), | 84 new SsaGlobalValueNumberer(), |
| 84 // After GVN, some instructions might need their type to be | 85 // After GVN, some instructions might need their type to be |
| 85 // updated because they now have different inputs. | 86 // updated because they now have different inputs. |
| 86 new SsaTypePropagator(compiler, closedWorld), | 87 new SsaTypePropagator(compiler, closedWorld), |
| 87 codeMotion = new SsaCodeMotion(), | 88 codeMotion = new SsaCodeMotion(), |
| 88 new SsaLoadElimination(backend, compiler, closedWorld), | 89 loadElimination = |
| 90 new SsaLoadElimination(backend, compiler, closedWorld), |
| 89 new SsaRedundantPhiEliminator(), | 91 new SsaRedundantPhiEliminator(), |
| 90 new SsaDeadPhiEliminator(), | 92 new SsaDeadPhiEliminator(), |
| 91 // After GVN and load elimination the same value may be used in code | 93 // After GVN and load elimination the same value may be used in code |
| 92 // controlled by a test on the value, so redo 'conversion insertion' to | 94 // controlled by a test on the value, so redo 'conversion insertion' to |
| 93 // learn from the refined type. | 95 // learn from the refined type. |
| 94 new SsaTypeConversionInserter(closedWorld), | 96 new SsaTypeConversionInserter(closedWorld), |
| 95 new SsaTypePropagator(compiler, closedWorld), | 97 new SsaTypePropagator(compiler, closedWorld), |
| 96 new SsaValueRangeAnalyzer(backend.helpers, closedWorld, this), | 98 new SsaValueRangeAnalyzer(backend.helpers, closedWorld, this), |
| 97 // Previous optimizations may have generated new | 99 // Previous optimizations may have generated new |
| 98 // opportunities for instruction simplification. | 100 // opportunities for instruction simplification. |
| 99 new SsaInstructionSimplifier(backend, closedWorld, this, registry), | 101 new SsaInstructionSimplifier(backend, closedWorld, this, registry), |
| 100 new SsaCheckInserter( | 102 new SsaCheckInserter( |
| 101 trustPrimitives, backend, closedWorld, boundsChecked), | 103 trustPrimitives, backend, closedWorld, boundsChecked), |
| 102 ]; | 104 ]; |
| 103 phases.forEach(runPhase); | 105 phases.forEach(runPhase); |
| 104 | 106 |
| 105 // Simplifying interceptors is not strictly just an optimization, it is | 107 // Simplifying interceptors is not strictly just an optimization, it is |
| 106 // required for implementation correctness because the code generator | 108 // required for implementation correctness because the code generator |
| 107 // assumes it is always performed. | 109 // assumes it is always performed. |
| 108 runPhase(new SsaSimplifyInterceptors( | 110 runPhase(new SsaSimplifyInterceptors( |
| 109 compiler, closedWorld, work.element.enclosingClass)); | 111 compiler, closedWorld, work.element.enclosingClass)); |
| 110 | 112 |
| 111 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this); | 113 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this); |
| 112 runPhase(dce); | 114 runPhase(dce); |
| 113 if (codeMotion.movedCode || dce.eliminatedSideEffects) { | 115 if (codeMotion.movedCode || |
| 116 dce.eliminatedSideEffects || |
| 117 loadElimination.newGvnCandidates) { |
| 114 phases = <OptimizationPhase>[ | 118 phases = <OptimizationPhase>[ |
| 115 new SsaTypePropagator(compiler, closedWorld), | 119 new SsaTypePropagator(compiler, closedWorld), |
| 116 new SsaGlobalValueNumberer(), | 120 new SsaGlobalValueNumberer(), |
| 117 new SsaCodeMotion(), | 121 new SsaCodeMotion(), |
| 118 new SsaValueRangeAnalyzer(backend.helpers, closedWorld, this), | 122 new SsaValueRangeAnalyzer(backend.helpers, closedWorld, this), |
| 119 new SsaInstructionSimplifier(backend, closedWorld, this, registry), | 123 new SsaInstructionSimplifier(backend, closedWorld, this, registry), |
| 120 new SsaCheckInserter( | 124 new SsaCheckInserter( |
| 121 trustPrimitives, backend, closedWorld, boundsChecked), | 125 trustPrimitives, backend, closedWorld, boundsChecked), |
| 122 new SsaSimplifyInterceptors( | 126 new SsaSimplifyInterceptors( |
| 123 compiler, closedWorld, work.element.enclosingClass), | 127 compiler, closedWorld, work.element.enclosingClass), |
| (...skipping 2129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2253 * example [HFieldGet]), when it knows the value stored in that memory | 2257 * example [HFieldGet]), when it knows the value stored in that memory |
| 2254 * location. | 2258 * location. |
| 2255 */ | 2259 */ |
| 2256 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { | 2260 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
| 2257 final JavaScriptBackend backend; | 2261 final JavaScriptBackend backend; |
| 2258 final Compiler compiler; | 2262 final Compiler compiler; |
| 2259 final ClosedWorld closedWorld; | 2263 final ClosedWorld closedWorld; |
| 2260 final String name = "SsaLoadElimination"; | 2264 final String name = "SsaLoadElimination"; |
| 2261 MemorySet memorySet; | 2265 MemorySet memorySet; |
| 2262 List<MemorySet> memories; | 2266 List<MemorySet> memories; |
| 2267 bool newGvnCandidates = false; |
| 2263 | 2268 |
| 2264 SsaLoadElimination(this.backend, this.compiler, this.closedWorld); | 2269 SsaLoadElimination(this.backend, this.compiler, this.closedWorld); |
| 2265 | 2270 |
| 2266 void visitGraph(HGraph graph) { | 2271 void visitGraph(HGraph graph) { |
| 2267 memories = new List<MemorySet>(graph.blocks.length); | 2272 memories = new List<MemorySet>(graph.blocks.length); |
| 2268 List<HBasicBlock> blocks = graph.blocks; | 2273 List<HBasicBlock> blocks = graph.blocks; |
| 2269 for (int i = 0; i < blocks.length; i++) { | 2274 for (int i = 0; i < blocks.length; i++) { |
| 2270 HBasicBlock block = blocks[i]; | 2275 HBasicBlock block = blocks[i]; |
| 2271 visitBasicBlock(block); | 2276 visitBasicBlock(block); |
| 2272 if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) { | 2277 if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2307 | 2312 |
| 2308 memories[block.id] = memorySet; | 2313 memories[block.id] = memorySet; |
| 2309 HInstruction instruction = block.first; | 2314 HInstruction instruction = block.first; |
| 2310 while (instruction != null) { | 2315 while (instruction != null) { |
| 2311 HInstruction next = instruction.next; | 2316 HInstruction next = instruction.next; |
| 2312 instruction.accept(this); | 2317 instruction.accept(this); |
| 2313 instruction = next; | 2318 instruction = next; |
| 2314 } | 2319 } |
| 2315 } | 2320 } |
| 2316 | 2321 |
| 2322 void checkNewGvnCandidates(HInstruction instruction, HInstruction existing) { |
| 2323 if (newGvnCandidates) return; |
| 2324 bool hasUseGvn(HInstruction insn) => insn.nonCheck().useGvn(); |
| 2325 if (instruction.usedBy.any(hasUseGvn) && existing.usedBy.any(hasUseGvn)) { |
| 2326 newGvnCandidates = true; |
| 2327 } |
| 2328 } |
| 2329 |
| 2317 void visitFieldGet(HFieldGet instruction) { | 2330 void visitFieldGet(HFieldGet instruction) { |
| 2318 if (instruction.isNullCheck) return; | 2331 if (instruction.isNullCheck) return; |
| 2319 FieldEntity element = instruction.element; | 2332 FieldEntity element = instruction.element; |
| 2320 HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); | 2333 HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); |
| 2321 _visitFieldGet(element, receiver, instruction); | 2334 _visitFieldGet(element, receiver, instruction); |
| 2322 } | 2335 } |
| 2323 | 2336 |
| 2324 void visitGetLength(HGetLength instruction) { | 2337 void visitGetLength(HGetLength instruction) { |
| 2325 _visitFieldGet(backend.helpers.jsIndexableLength, | 2338 _visitFieldGet(backend.helpers.jsIndexableLength, |
| 2326 instruction.receiver.nonCheck(), instruction); | 2339 instruction.receiver.nonCheck(), instruction); |
| 2327 } | 2340 } |
| 2328 | 2341 |
| 2329 void _visitFieldGet( | 2342 void _visitFieldGet( |
| 2330 MemberEntity element, HInstruction receiver, HInstruction instruction) { | 2343 MemberEntity element, HInstruction receiver, HInstruction instruction) { |
| 2331 HInstruction existing = memorySet.lookupFieldValue(element, receiver); | 2344 HInstruction existing = memorySet.lookupFieldValue(element, receiver); |
| 2332 if (existing != null) { | 2345 if (existing != null) { |
| 2346 checkNewGvnCandidates(instruction, existing); |
| 2333 instruction.block.rewriteWithBetterUser(instruction, existing); | 2347 instruction.block.rewriteWithBetterUser(instruction, existing); |
| 2334 instruction.block.remove(instruction); | 2348 instruction.block.remove(instruction); |
| 2335 } else { | 2349 } else { |
| 2336 memorySet.registerFieldValue(element, receiver, instruction); | 2350 memorySet.registerFieldValue(element, receiver, instruction); |
| 2337 } | 2351 } |
| 2338 } | 2352 } |
| 2339 | 2353 |
| 2340 void visitFieldSet(HFieldSet instruction) { | 2354 void visitFieldSet(HFieldSet instruction) { |
| 2341 HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); | 2355 HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); |
| 2342 memorySet.registerFieldValueUpdate( | 2356 memorySet.registerFieldValueUpdate( |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2405 } | 2419 } |
| 2406 | 2420 |
| 2407 void visitLazyStatic(HLazyStatic instruction) { | 2421 void visitLazyStatic(HLazyStatic instruction) { |
| 2408 FieldEntity field = instruction.element; | 2422 FieldEntity field = instruction.element; |
| 2409 handleStaticLoad(field, instruction); | 2423 handleStaticLoad(field, instruction); |
| 2410 } | 2424 } |
| 2411 | 2425 |
| 2412 void handleStaticLoad(MemberEntity element, HInstruction instruction) { | 2426 void handleStaticLoad(MemberEntity element, HInstruction instruction) { |
| 2413 HInstruction existing = memorySet.lookupFieldValue(element, null); | 2427 HInstruction existing = memorySet.lookupFieldValue(element, null); |
| 2414 if (existing != null) { | 2428 if (existing != null) { |
| 2429 checkNewGvnCandidates(instruction, existing); |
| 2415 instruction.block.rewriteWithBetterUser(instruction, existing); | 2430 instruction.block.rewriteWithBetterUser(instruction, existing); |
| 2416 instruction.block.remove(instruction); | 2431 instruction.block.remove(instruction); |
| 2417 } else { | 2432 } else { |
| 2418 memorySet.registerFieldValue(element, null, instruction); | 2433 memorySet.registerFieldValue(element, null, instruction); |
| 2419 } | 2434 } |
| 2420 } | 2435 } |
| 2421 | 2436 |
| 2422 void visitStatic(HStatic instruction) { | 2437 void visitStatic(HStatic instruction) { |
| 2423 handleStaticLoad(instruction.element, instruction); | 2438 handleStaticLoad(instruction.element, instruction); |
| 2424 } | 2439 } |
| 2425 | 2440 |
| 2426 void visitStaticStore(HStaticStore instruction) { | 2441 void visitStaticStore(HStaticStore instruction) { |
| 2427 memorySet.registerFieldValueUpdate( | 2442 memorySet.registerFieldValueUpdate( |
| 2428 instruction.element, null, instruction.inputs.last); | 2443 instruction.element, null, instruction.inputs.last); |
| 2429 } | 2444 } |
| 2430 | 2445 |
| 2431 void visitLiteralList(HLiteralList instruction) { | 2446 void visitLiteralList(HLiteralList instruction) { |
| 2432 memorySet.registerAllocation(instruction); | 2447 memorySet.registerAllocation(instruction); |
| 2433 memorySet.killAffectedBy(instruction); | 2448 memorySet.killAffectedBy(instruction); |
| 2434 // TODO(sra): Set initial keyed values. | 2449 // TODO(sra): Set initial keyed values. |
| 2435 // TODO(sra): Set initial length. | 2450 // TODO(sra): Set initial length. |
| 2436 } | 2451 } |
| 2437 | 2452 |
| 2438 void visitIndex(HIndex instruction) { | 2453 void visitIndex(HIndex instruction) { |
| 2439 HInstruction receiver = instruction.receiver.nonCheck(); | 2454 HInstruction receiver = instruction.receiver.nonCheck(); |
| 2440 HInstruction existing = | 2455 HInstruction existing = |
| 2441 memorySet.lookupKeyedValue(receiver, instruction.index); | 2456 memorySet.lookupKeyedValue(receiver, instruction.index); |
| 2442 if (existing != null) { | 2457 if (existing != null) { |
| 2458 checkNewGvnCandidates(instruction, existing); |
| 2443 instruction.block.rewriteWithBetterUser(instruction, existing); | 2459 instruction.block.rewriteWithBetterUser(instruction, existing); |
| 2444 instruction.block.remove(instruction); | 2460 instruction.block.remove(instruction); |
| 2445 } else { | 2461 } else { |
| 2446 memorySet.registerKeyedValue(receiver, instruction.index, instruction); | 2462 memorySet.registerKeyedValue(receiver, instruction.index, instruction); |
| 2447 } | 2463 } |
| 2448 } | 2464 } |
| 2449 | 2465 |
| 2450 void visitIndexAssign(HIndexAssign instruction) { | 2466 void visitIndexAssign(HIndexAssign instruction) { |
| 2451 HInstruction receiver = instruction.receiver.nonCheck(); | 2467 HInstruction receiver = instruction.receiver.nonCheck(); |
| 2452 memorySet.registerKeyedValueUpdate( | 2468 memorySet.registerKeyedValueUpdate( |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2788 | 2804 |
| 2789 keyedValues.forEach((receiver, values) { | 2805 keyedValues.forEach((receiver, values) { |
| 2790 result.keyedValues[receiver] = | 2806 result.keyedValues[receiver] = |
| 2791 new Map<HInstruction, HInstruction>.from(values); | 2807 new Map<HInstruction, HInstruction>.from(values); |
| 2792 }); | 2808 }); |
| 2793 | 2809 |
| 2794 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2810 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2795 return result; | 2811 return result; |
| 2796 } | 2812 } |
| 2797 } | 2813 } |
| OLD | NEW |