Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: lib/compiler/implementation/ssa/codegen_helpers.dart

Issue 10440087: Compute liveness of instructions to get better and fewer variable names. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 /** 5 /**
6 * Instead of emitting each SSA instruction with a temporary variable 6 * Instead of emitting each SSA instruction with a temporary variable
7 * mark instructions that can be emitted at their use-site. 7 * mark instructions that can be emitted at their use-site.
8 * For example, in: 8 * For example, in:
9 * t0 = 4; 9 * t0 = 4;
10 * t1 = 3; 10 * t1 = 3;
11 * t2 = add(t0, t1); 11 * t2 = add(t0, t1);
12 * t0 and t1 would be marked and the resulting code would then be: 12 * t0 and t1 would be marked and the resulting code would then be:
13 * t2 = add(4, 3); 13 * t2 = add(4, 3);
14 */ 14 */
15 class SsaInstructionMerger extends HBaseVisitor { 15 class SsaInstructionMerger extends HBaseVisitor {
16 List<HInstruction> expectedInputs; 16 List<HInstruction> expectedInputs;
17 Set<HInstruction> generateAtUseSite; 17 Set<HInstruction> generateAtUseSite;
18 18
19 SsaInstructionMerger(this.generateAtUseSite); 19 SsaInstructionMerger(this.generateAtUseSite);
20 20
21 void visitGraph(HGraph graph) { 21 void visitGraph(HGraph graph) {
22 visitDominatorTree(graph); 22 visitDominatorTree(graph);
23 } 23 }
24 24
25 bool usedOnlyByPhis(instruction) {
26 for (HInstruction user in instruction.usedBy) {
27 if (user is! HPhi) return false;
28 }
29 return true;
30 }
31
32 void visitInstruction(HInstruction instruction) { 25 void visitInstruction(HInstruction instruction) {
33 // A code motion invariant instruction is dealt before visiting it. 26 // A code motion invariant instruction is dealt before visiting it.
34 assert(!instruction.isCodeMotionInvariant()); 27 assert(!instruction.isCodeMotionInvariant());
35 for (HInstruction input in instruction.inputs) { 28 for (HInstruction input in instruction.inputs) {
36 if (!generateAtUseSite.contains(input) 29 if (!generateAtUseSite.contains(input)
37 && !input.isCodeMotionInvariant() 30 && !input.isCodeMotionInvariant()
38 && input.usedBy.length == 1 31 && input.usedBy.length == 1
39 && input is! HPhi) { 32 && input is! HPhi) {
40 expectedInputs.add(input); 33 expectedInputs.add(input);
41 } 34 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 HInstruction nextInput = expectedInputs.removeLast(); 88 HInstruction nextInput = expectedInputs.removeLast();
96 assert(!generateAtUseSite.contains(nextInput)); 89 assert(!generateAtUseSite.contains(nextInput));
97 assert(nextInput.usedBy.length == 1); 90 assert(nextInput.usedBy.length == 1);
98 if (nextInput === instruction) { 91 if (nextInput === instruction) {
99 return true; 92 return true;
100 } 93 }
101 } 94 }
102 return false; 95 return false;
103 } 96 }
104 97
105 for (HBasicBlock successor in block.successors) {
106 // Only add the input of the first phi. Making inputs of
107 // later phis generate-at-use-site would make them move
108 // accross the assignment of the first phi, and we need
109 // more analysis before we can do that.
110 HPhi phi = successor.phis.first;
111 if (phi != null) {
112 int index = successor.predecessors.indexOf(block);
113 HInstruction input = phi.inputs[index];
114 if (!generateAtUseSite.contains(input)
115 && !input.isCodeMotionInvariant()
116 && input.usedBy.length == 1
117 && input is! HPhi) {
118 expectedInputs.add(input);
119 }
120 break;
121 }
122 }
123
124 block.last.accept(this); 98 block.last.accept(this);
125 for (HInstruction instruction = block.last.previous; 99 for (HInstruction instruction = block.last.previous;
126 instruction !== null; 100 instruction !== null;
127 instruction = instruction.previous) { 101 instruction = instruction.previous) {
128 if (generateAtUseSite.contains(instruction)) { 102 if (generateAtUseSite.contains(instruction)) {
129 continue; 103 continue;
130 } 104 }
131 if (instruction.isCodeMotionInvariant()) { 105 if (instruction.isCodeMotionInvariant()) {
132 generateAtUseSite.add(instruction); 106 generateAtUseSite.add(instruction);
133 continue; 107 continue;
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 }; 394 };
421 } 395 }
422 396
423 class JSBinaryOperatorPrecedence { 397 class JSBinaryOperatorPrecedence {
424 final int left; 398 final int left;
425 final int right; 399 final int right;
426 const JSBinaryOperatorPrecedence(this.left, this.right); 400 const JSBinaryOperatorPrecedence(this.left, this.right);
427 // All binary operators (excluding assignment) are left associative. 401 // All binary operators (excluding assignment) are left associative.
428 int get precedence() => left; 402 int get precedence() => left;
429 } 403 }
430
431 class PhiEquivalator {
432 final Equivalence<HPhi> equivalence;
433 final Map<HPhi, String> logicalOperations;
434 PhiEquivalator(this.equivalence, this.logicalOperations);
435
436 void analyzeGraph(HGraph graph) {
437 graph.blocks.forEach(analyzeBlock);
438 }
439
440 void analyzeBlock(HBasicBlock block) {
441 for (HPhi phi = block.phis.first; phi !== null; phi = phi.next) {
442 if (!logicalOperations.containsKey(phi) &&
443 phi.usedBy.length == 1 &&
444 phi.usedBy[0] is HPhi &&
445 phi.block.id < phi.usedBy[0].block.id) {
446 equivalence.makeEquivalent(phi, phi.usedBy[0]);
447 }
448 }
449 }
450 }
451
452
453 /**
454 * Try to figure out which phis can be represented by the same temporary
455 * variable, to avoid creating a new variable for each phi.
456 */
457 class Equivalence<T extends Hashable> {
458 // Represent equivalence classes of HPhi nodes as a forest of trees,
459 // where each tree is one equivalence class, and the root is the
460 // canonical representative for the equivalence class.
461 // Implement the forest by having each phi point to its parent in the tree,
462 // transitively linking it to the root, which itself doesn't have a parent.
463 final Map<T,T> representative;
464
465 Equivalence() : representative = new Map<T,T>();
466
467 T makeEquivalent(T a, T b) {
468 T root1 = getRepresentative(a);
469 T root2 = getRepresentative(b);
470 if (root1 !== root2) {
471 // Merge the trees for the two classes into one.
472 representative[root1] = root2;
473 }
474 }
475
476 /**
477 * Get the canonical representative for an equivalence class of phis.
478 */
479 T getRepresentative(T element) {
480 T parent = representative[element];
481 if (parent === null) {
482 // This is the root of a tree (a previously unseen node is considered
483 // the root of its own tree).
484 return element;
485 }
486 // Shorten the path for all the elements on the way to the root,
487 // improving the performance of future lookups.
488 T root = getRepresentative(parent);
489 if (root !== parent) representative[element] = root;
490 return root;
491 }
492
493 bool areEquivalent(T a, T b) {
494 return getRepresentative(a) === getRepresentative(b);
495 }
496 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698