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

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

Issue 218993003: Emit read-modify-write of fields as assignment op. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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
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 part of ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * Replaces some instructions with specialized versions to make codegen easier. 8 * Replaces some instructions with specialized versions to make codegen easier.
9 * Caches codegen information on nodes. 9 * Caches codegen information on nodes.
10 */ 10 */
11 class SsaInstructionSelection extends HBaseVisitor { 11 class SsaInstructionSelection extends HBaseVisitor {
12 final Compiler compiler; 12 final Compiler compiler;
13 HGraph graph; 13 HGraph graph;
14 14
15 SsaInstructionSelection(this.compiler); 15 SsaInstructionSelection(this.compiler);
16 16
17 JavaScriptBackend get backend => compiler.backend; 17 JavaScriptBackend get backend => compiler.backend;
18 18
19 void visitGraph(HGraph graph) { 19 void visitGraph(HGraph graph) {
20 this.graph = graph; 20 this.graph = graph;
21 visitDominatorTree(graph); 21 visitDominatorTree(graph);
22 } 22 }
23 23
24 visitBasicBlock(HBasicBlock block) { 24 visitBasicBlock(HBasicBlock block) {
25 HInstruction instruction = block.first; 25 HInstruction instruction = block.first;
26 while (instruction != null) { 26 while (instruction != null) {
27 HInstruction next = instruction.next; 27 HInstruction next = instruction.next;
28 HInstruction replacement = instruction.accept(this); 28 HInstruction replacement = instruction.accept(this);
29 if (replacement != instruction) { 29 if (replacement != instruction && replacement != null) {
30 block.rewrite(instruction, replacement); 30 block.rewrite(instruction, replacement);
31 31
32 // If the replacement instruction does not know its source element, use 32 // If the replacement instruction does not know its source element, use
33 // the source element of the instruction. 33 // the source element of the instruction.
34 if (replacement.sourceElement == null) { 34 if (replacement.sourceElement == null) {
35 replacement.sourceElement = instruction.sourceElement; 35 replacement.sourceElement = instruction.sourceElement;
36 } 36 }
37 if (replacement.sourcePosition == null) { 37 if (replacement.sourcePosition == null) {
38 replacement.sourcePosition = instruction.sourcePosition; 38 replacement.sourcePosition = instruction.sourcePosition;
39 } 39 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 receiverArgument.usedBy.remove(node); 130 receiverArgument.usedBy.remove(node);
131 node.inputs[1] = dummy; 131 node.inputs[1] = dummy;
132 dummy.usedBy.add(node); 132 dummy.usedBy.add(node);
133 } 133 }
134 } 134 }
135 } 135 }
136 } 136 }
137 137
138 return node; 138 return node;
139 } 139 }
140
141 HInstruction visitFieldSet(HFieldSet setter) {
142 // Pattern match
143 // t1 = x.f; t2 = t1 op y; x.f = t2; use(t2) --> x.f op= y
144 // t1 = x.f; t2 = t1 + 1; x.f = t2; use(t2) --> ++x.f
floitsch 2014/04/01 17:28:58 Move that line first. Otherwise the x.f op= y alwa
sra1 2014/04/01 19:51:59 Done.
145 // t1 = x.f; t2 = t1 + 1; x.f = t2; use(t1) --> x.f++
146 HBasicBlock block = setter.block;
147 HInstruction op = setter.value;
148 HInstruction receiver = setter.receiver;
149
150 bool isMatchingRead(HInstruction candidate) {
151 if (candidate is! HFieldGet) return false;
152 if (candidate.element != setter.element) return false;
153 if (candidate.receiver != setter.receiver) return false;
154 // Recognize only three instructions in sequence in the same block. This
155 // could be broadened to allow non-interfereing interleaved instructions.
floitsch 2014/04/01 17:28:58 interfering
sra1 2014/04/01 19:51:59 Done.
156 if (op.block != block) return false;
157 if (candidate.block != block) return false;
158 if (setter.previous != op) return false;
159 if (op.previous != candidate) return false;
160 return true;
161 }
162
163 HInstruction noMatchingRead() {
164 // If we have other HFieldSet optimizations, they go here.
165 return null;
166 }
167
168 HInstruction replaceOp(HInstruction replacement, HInstruction getter) {
169 block.addBefore(setter, replacement);
170 block.remove(setter);
171 block.rewrite(op, replacement);
172 block.remove(op);
173 block.remove(getter);
174 return null;
175 }
176
177 HInstruction plusOrMinus(String assignOp, String incrementOp) {
178 if (isMatchingRead(op.left)) {
179 HFieldGet getter = op.left;
180 HInstruction right = op.right;
181 if (getter.usedBy.length == 1) {
182 if (right is HConstant && right.constant.isOne) {
183 HInstruction rmw = new HReadModifyWrite.preOp(
184 setter.element, incrementOp, receiver, op.instructionType);
185 return replaceOp(rmw, getter);
186 } else {
187 HInstruction rmw = new HReadModifyWrite.assignOp(
188 setter.element,
189 assignOp,
190 receiver, right, op.instructionType);
191 return replaceOp(rmw, getter);
192 }
193 } else if (op.usedBy.length == 1 &&
194 right is HConstant &&
195 right.constant.isOne) {
196 HInstruction rmw = new HReadModifyWrite.postOp(
197 setter.element, incrementOp, receiver, op.instructionType);
198 block.addAfter(getter, rmw);
199 block.remove(setter);
200 block.remove(op);
201 block.rewrite(getter, rmw);
202 block.remove(getter);
203 return null;
204 }
205 }
206 return noMatchingRead();
207 }
208
209 HInstruction simple(String assignOp) {
210 if (isMatchingRead(op.left)) {
211 HFieldGet getter = op.left;
212 if (getter.usedBy.length == 1) {
213 HInstruction rmw = new HReadModifyWrite.assignOp(
214 setter.element,
215 assignOp,
216 receiver, op.right, op.instructionType);
217 return replaceOp(rmw, getter);
218 }
219 }
220 return noMatchingRead();
221 }
222
223 HInstruction bitop(String assignOp) {
224 // HBitAnd, HBitOr etc. are more difficult because HBitAnd(a.x, y)
225 // sometimes needs to be forced to unsigned: a.x = (a.x & y) >>> 0.
226 if (op.isUInt31(compiler)) return simple(assignOp);
227 return noMatchingRead();
228 }
229
230 if (op is HAdd) return plusOrMinus('+', '++');
231 if (op is HSubtract) return plusOrMinus('-', '--');
232
233 if (op is HStringConcat) return simple('+');
234 if (op is HMultiply) return simple('*');
235 if (op is HDivide) return simple('/');
236
237 if (op is HBitAnd) return bitop('&');
238 if (op is HBitOr) return bitop('|');
239 if (op is HBitXor) return bitop('^');
240
241 return noMatchingRead();
242 }
140 } 243 }
141 244
142 /** 245 /**
143 * Remove [HTypeKnown] instructions from the graph, to make codegen 246 * Remove [HTypeKnown] instructions from the graph, to make codegen
144 * analysis easier. 247 * analysis easier.
145 */ 248 */
146 class SsaTypeKnownRemover extends HBaseVisitor { 249 class SsaTypeKnownRemover extends HBaseVisitor {
147 250
148 void visitGraph(HGraph graph) { 251 void visitGraph(HGraph graph) {
149 visitDominatorTree(graph); 252 visitDominatorTree(graph);
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 } 689 }
587 690
588 // If [thenInput] is defined in the first predecessor, then it is only used 691 // If [thenInput] is defined in the first predecessor, then it is only used
589 // by [phi] and can be generated at use site. 692 // by [phi] and can be generated at use site.
590 if (identical(thenInput.block, end.predecessors[0])) { 693 if (identical(thenInput.block, end.predecessors[0])) {
591 assert(thenInput.usedBy.length == 1); 694 assert(thenInput.usedBy.length == 1);
592 markAsGenerateAtUseSite(thenInput); 695 markAsGenerateAtUseSite(thenInput);
593 } 696 }
594 } 697 }
595 } 698 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/codegen.dart ('k') | sdk/lib/_internal/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698