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

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

Issue 10084002: Add the first phi's input as possible generate-at-use-site. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments. Created 8 years, 8 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
« no previous file with comments | « frog/tests/leg/src/TypeInferenceTest.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) { 25 bool usedOnlyByPhis(instruction) {
26 for (HInstruction user in instruction.usedBy) { 26 for (HInstruction user in instruction.usedBy) {
27 if (user is !HPhi) return false; 27 if (user is! HPhi) return false;
28 } 28 }
29 return true; 29 return true;
30 } 30 }
31 31
32 void visitInstruction(HInstruction instruction) { 32 void visitInstruction(HInstruction instruction) {
33 // A code motion invariant instruction is dealt before visiting it. 33 // A code motion invariant instruction is dealt before visiting it.
34 assert(!instruction.isCodeMotionInvariant()); 34 assert(!instruction.isCodeMotionInvariant());
35 for (HInstruction input in instruction.inputs) { 35 for (HInstruction input in instruction.inputs) {
36 if (!generateAtUseSite.contains(input) 36 if (!generateAtUseSite.contains(input)
37 && !input.isCodeMotionInvariant() 37 && !input.isCodeMotionInvariant()
38 && input.usedBy.length == 1) { 38 && input.usedBy.length == 1
39 && input is! HPhi) {
39 expectedInputs.add(input); 40 expectedInputs.add(input);
40 } 41 }
41 } 42 }
42 } 43 }
43 44
44 // The codegen might use the input multiple times, so it must not be 45 // The codegen might use the input multiple times, so it must not be
45 // set generate at use site. 46 // set generate at use site.
46 void visitIs(HIs instruction) {} 47 void visitIs(HIs instruction) {}
47 48
48 // A check method must not have its input generate at use site, 49 // A check method must not have its input generate at use site,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 // be generated at their use site, if they occur in the correct order. 90 // be generated at their use site, if they occur in the correct order.
90 if (expectedInputs === null) expectedInputs = new List<HInstruction>(); 91 if (expectedInputs === null) expectedInputs = new List<HInstruction>();
91 92
92 // Pop instructions from expectedInputs until instruction is found. 93 // Pop instructions from expectedInputs until instruction is found.
93 // Return true if it is found, or false if not. 94 // Return true if it is found, or false if not.
94 bool findInInputs(HInstruction instruction) { 95 bool findInInputs(HInstruction instruction) {
95 while (!expectedInputs.isEmpty()) { 96 while (!expectedInputs.isEmpty()) {
96 HInstruction nextInput = expectedInputs.removeLast(); 97 HInstruction nextInput = expectedInputs.removeLast();
97 assert(!generateAtUseSite.contains(nextInput)); 98 assert(!generateAtUseSite.contains(nextInput));
98 assert(nextInput.usedBy.length == 1); 99 assert(nextInput.usedBy.length == 1);
99 if (nextInput == instruction) { 100 if (nextInput === instruction) {
100 return true; 101 return true;
101 } 102 }
102 } 103 }
103 return false; 104 return false;
104 } 105 }
105 106
107 for (HBasicBlock successor in block.successors) {
108 // Only add the input of the first phi. Making inputs of
109 // later phis generate-at-use-site would make them move
110 // accross the assignment of the first phi, and we need
111 // more analysis before we can do that.
112 HPhi phi = successor.phis.first;
113 if (phi != null) {
114 int index = successor.predecessors.indexOf(block);
115 HInstruction input = phi.inputs[index];
116 if (!generateAtUseSite.contains(input)
117 && !input.isCodeMotionInvariant()
118 && input.usedBy.length == 1
119 && input is! HPhi) {
120 expectedInputs.add(input);
121 }
122 break;
123 }
124 }
125
106 block.last.accept(this); 126 block.last.accept(this);
107 for (HInstruction instruction = block.last.previous; 127 for (HInstruction instruction = block.last.previous;
108 instruction !== null; 128 instruction !== null;
109 instruction = instruction.previous) { 129 instruction = instruction.previous) {
110 if (generateAtUseSite.contains(instruction)) { 130 if (generateAtUseSite.contains(instruction)) {
111 continue; 131 continue;
112 } 132 }
113 if (instruction.isCodeMotionInvariant()) { 133 if (instruction.isCodeMotionInvariant()) {
114 generateAtUseSite.add(instruction); 134 generateAtUseSite.add(instruction);
115 continue; 135 continue;
116 } 136 }
117 bool foundInInputs = false; 137 bool foundInInputs = false;
118 // See if the current instruction is the next non-trivial 138 // See if the current instruction is the next non-trivial
119 // expected input. If not, drop the expectedInputs and 139 // expected input. If not, drop the expectedInputs and
120 // start over. 140 // start over.
121 if (findInInputs(instruction)) { 141 if (findInInputs(instruction)) {
122 foundInInputs = true; 142 foundInInputs = true;
123 tryGenerateAtUseSite(instruction); 143 tryGenerateAtUseSite(instruction);
124 } else { 144 } else {
125 assert(expectedInputs.isEmpty()); 145 assert(expectedInputs.isEmpty());
126 } 146 }
127 if (foundInInputs || usedOnlyByPhis(instruction)) { 147 if (foundInInputs || usedOnlyByPhis(instruction)) {
128 // Try merging all non-trivial inputs. 148 // Try merging all non-trivial inputs.
129 instruction.accept(this); 149 instruction.accept(this);
130 } 150 }
131 } 151 }
132 152
133 if (block.predecessors.length === 1 153 if (block.predecessors.length === 1
134 && isBlockSinglePredecessor(block.predecessors[0])) { 154 && isBlockSinglePredecessor(block.predecessors[0])) {
155 assert(block.phis.isEmpty());
135 tryMergingExpressions(block.predecessors[0]); 156 tryMergingExpressions(block.predecessors[0]);
136 } else { 157 } else {
137 expectedInputs = null; 158 expectedInputs = null;
138 } 159 }
139 } 160 }
140 } 161 }
141 162
142 /** 163 /**
143 * Detect control flow arising from short-circuit logical operators, and 164 * Detect control flow arising from short-circuit logical operators, and
144 * prepare the program to be generated using these operators instead of 165 * prepare the program to be generated using these operators instead of
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 // improving the performance of future lookups. 431 // improving the performance of future lookups.
411 T root = getRepresentative(parent); 432 T root = getRepresentative(parent);
412 if (root !== parent) representative[element] = root; 433 if (root !== parent) representative[element] = root;
413 return root; 434 return root;
414 } 435 }
415 436
416 bool areEquivalent(T a, T b) { 437 bool areEquivalent(T a, T b) {
417 return getRepresentative(a) === getRepresentative(b); 438 return getRepresentative(a) === getRepresentative(b);
418 } 439 }
419 } 440 }
OLDNEW
« no previous file with comments | « frog/tests/leg/src/TypeInferenceTest.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698