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

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

Issue 10968060: Add a value range analysis phase to remove bounds checks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 abstract class OptimizationPhase { 5 abstract class OptimizationPhase {
6 String get name; 6 String get name;
7 void visitGraph(HGraph graph); 7 void visitGraph(HGraph graph);
8 } 8 }
9 9
10 class SsaOptimizerTask extends CompilerTask { 10 class SsaOptimizerTask extends CompilerTask {
(...skipping 23 matching lines...) Expand all
34 List<OptimizationPhase> phases = <OptimizationPhase>[ 34 List<OptimizationPhase> phases = <OptimizationPhase>[
35 // Run trivial constant folding first to optimize 35 // Run trivial constant folding first to optimize
36 // some patterns useful for type conversion. 36 // some patterns useful for type conversion.
37 new SsaConstantFolder(constantSystem, backend, work, types), 37 new SsaConstantFolder(constantSystem, backend, work, types),
38 new SsaTypeConversionInserter(compiler), 38 new SsaTypeConversionInserter(compiler),
39 new SsaTypePropagator(compiler, types), 39 new SsaTypePropagator(compiler, types),
40 new SsaCheckInserter(backend, types, context.boundsChecked), 40 new SsaCheckInserter(backend, types, context.boundsChecked),
41 new SsaConstantFolder(constantSystem, backend, work, types), 41 new SsaConstantFolder(constantSystem, backend, work, types),
42 new SsaRedundantPhiEliminator(), 42 new SsaRedundantPhiEliminator(),
43 new SsaDeadPhiEliminator(), 43 new SsaDeadPhiEliminator(),
44 new SsaConstantFolder(constantSystem, backend, work, types),
44 new SsaGlobalValueNumberer(compiler, types), 45 new SsaGlobalValueNumberer(compiler, types),
45 new SsaCodeMotion(), 46 new SsaCodeMotion(),
47 new SsaValueRangeAnalyzer(constantSystem, types, work),
46 // Previous optimizations may have generated new 48 // Previous optimizations may have generated new
47 // opportunities for constant folding. 49 // opportunities for constant folding.
48 new SsaConstantFolder(constantSystem, backend, work, types), 50 new SsaConstantFolder(constantSystem, backend, work, types),
49 new SsaDeadCodeEliminator(types), 51 new SsaDeadCodeEliminator(types),
50 new SsaRegisterRecompilationCandidates(backend, work, types)]; 52 new SsaRegisterRecompilationCandidates(backend, work, types)];
51 runPhases(graph, phases); 53 runPhases(graph, phases);
52 }); 54 });
53 } 55 }
54 56
55 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { 57 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 HInstruction operand = node.operand; 191 HInstruction operand = node.operand;
190 if (operand is HConstant) { 192 if (operand is HConstant) {
191 UnaryOperation operation = node.operation(constantSystem); 193 UnaryOperation operation = node.operation(constantSystem);
192 HConstant receiver = operand; 194 HConstant receiver = operand;
193 Constant folded = operation.fold(receiver.constant); 195 Constant folded = operation.fold(receiver.constant);
194 if (folded !== null) return graph.addConstant(folded); 196 if (folded !== null) return graph.addConstant(folded);
195 } 197 }
196 return node; 198 return node;
197 } 199 }
198 200
199 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) { 201 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) {
Søren Gjesse 2012/09/26 09:08:24 Add a comment on the pattern recognized here.
ngeoffray 2012/09/26 09:33:26 Done.
202 if (node.isLengthGetter() && node.inputs[1] is HInvokeStatic) {
203 HInvokeStatic call = node.inputs[1];
204 Element element = call.inputs[0].element;
205 if (element.isConstructor() &&
206 element.enclosingElement == compiler.listClass.defaultClass.element) {
207 if (call.inputs.length == 2 && call.inputs[1].isInteger(types)) {
208 return call.inputs[1];
209 }
210 }
211 }
200 HInstruction input = node.inputs[1]; 212 HInstruction input = node.inputs[1];
201 if (node.isLengthGetter()) { 213 if (node.isLengthGetter()) {
202 if (input.isConstantString()) { 214 if (input.isConstantString()) {
203 HConstant constantInput = input; 215 HConstant constantInput = input;
204 StringConstant constant = constantInput.constant; 216 StringConstant constant = constantInput.constant;
205 return graph.addConstantInt(constant.length, constantSystem); 217 return graph.addConstantInt(constant.length, constantSystem);
206 } else if (input.isConstantList()) { 218 } else if (input.isConstantList()) {
207 HConstant constantInput = input; 219 HConstant constantInput = input;
208 ListConstant constant = constantInput.constant; 220 ListConstant constant = constantInput.constant;
209 return graph.addConstantInt(constant.length, constantSystem); 221 return graph.addConstantInt(constant.length, constantSystem);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 275 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
264 selector, 276 selector,
265 node.inputs.getRange(1, node.inputs.length - 1)); 277 node.inputs.getRange(1, node.inputs.length - 1));
266 if (type.isExact()) { 278 if (type.isExact()) {
267 HBoundedType concrete = type; 279 HBoundedType concrete = type;
268 result.element = concrete.lookupMember(selector.name); 280 result.element = concrete.lookupMember(selector.name);
269 } 281 }
270 return result; 282 return result;
271 } 283 }
272 284
273 HInstruction visitBoundsCheck(HBoundsCheck node) {
274 int tryGetIntConstantValue(HInstruction instruction, String errorMessage) {
275 // Tests whether an [HInstruction] is a constant.
276 // If it is a constant, and not an int constant, it fails.
277 // If it's an int constant it returns the value.
278 // Otherwise it's not a constant, and this function returns null.
279 if (!instruction.isConstant()) return null;
280 HConstant constantInstruction = instruction;
281 Constant constant = constantInstruction.constant;
282 if (!constant.isInt()) {
283 compiler.internalError(errorMessage, instruction: instruction);
284 }
285 IntConstant intConstant = constant;
286 return intConstant.value;
287 }
288 int index = tryGetIntConstantValue(node.index,
289 'String or List index not a number');
290 if (index !== null) {
291 if (index < 0) {
292 node.staticChecks = HBoundsCheck.ALWAYS_FALSE;
293 return node;
294 }
295 int length = tryGetIntConstantValue(node.length,
296 'String or List length not a number');
297 if (length !== null) {
298 if (index >= length) {
299 node.staticChecks = HBoundsCheck.ALWAYS_FALSE;
300 } else {
301 // Could have set the staticChecks to ALWAYS_TRUE instead.
302 return node.index;
303 }
304 return node;
305 }
306 node.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
307 }
308 return node;
309 }
310
311 HInstruction visitIntegerCheck(HIntegerCheck node) { 285 HInstruction visitIntegerCheck(HIntegerCheck node) {
312 HInstruction value = node.value; 286 HInstruction value = node.value;
313 if (value.isInteger(types)) return value; 287 if (value.isInteger(types)) return value;
314 if (value.isConstant()) { 288 if (value.isConstant()) {
315 HConstant constantInstruction = value; 289 HConstant constantInstruction = value;
316 assert(!constantInstruction.constant.isInt()); 290 assert(!constantInstruction.constant.isInt());
317 if (!constantSystem.isInt(constantInstruction.constant)) { 291 if (!constantSystem.isInt(constantInstruction.constant)) {
318 // -0.0 is a double but will pass the runtime integer check. 292 // -0.0 is a double but will pass the runtime integer check.
319 node.alwaysFalse = true; 293 node.alwaysFalse = true;
320 } 294 }
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 695
722 void visitIndex(HIndex node) { 696 void visitIndex(HIndex node) {
723 if (!node.receiver.isIndexablePrimitive(types)) return; 697 if (!node.receiver.isIndexablePrimitive(types)) return;
724 if (boundsChecked.contains(node)) return; 698 if (boundsChecked.contains(node)) return;
725 HInstruction index = node.index; 699 HInstruction index = node.index;
726 if (!node.index.isInteger(types)) { 700 if (!node.index.isInteger(types)) {
727 index = insertIntegerCheck(node, index); 701 index = insertIntegerCheck(node, index);
728 } 702 }
729 index = insertBoundsCheck(node, node.receiver, index); 703 index = insertBoundsCheck(node, node.receiver, index);
730 node.changeUse(node.index, index); 704 node.changeUse(node.index, index);
705 assert(node.isBuiltin(types));
731 } 706 }
732 707
733 void visitIndexAssign(HIndexAssign node) { 708 void visitIndexAssign(HIndexAssign node) {
734 if (!node.receiver.isMutableArray(types)) return; 709 if (!node.receiver.isMutableArray(types)) return;
735 if (boundsChecked.contains(node)) return; 710 if (boundsChecked.contains(node)) return;
736 HInstruction index = node.index; 711 HInstruction index = node.index;
737 if (!node.index.isInteger(types)) { 712 if (!node.index.isInteger(types)) {
738 index = insertIntegerCheck(node, index); 713 index = insertIntegerCheck(node, index);
739 } 714 }
740 index = insertBoundsCheck(node, node.receiver, index); 715 index = insertBoundsCheck(node, node.receiver, index);
741 node.changeUse(node.index, index); 716 node.changeUse(node.index, index);
717 assert(node.isBuiltin(types));
742 } 718 }
743 719
744 void visitInvokeInterceptor(HInvokeInterceptor node) { 720 void visitInvokeInterceptor(HInvokeInterceptor node) {
745 if (!node.isPopCall(types)) return; 721 if (!node.isPopCall(types)) return;
746 if (boundsChecked.contains(node)) return; 722 if (boundsChecked.contains(node)) return;
747 HInstruction receiver = node.inputs[1]; 723 HInstruction receiver = node.inputs[1];
748 insertBoundsCheck(node, receiver, graph.addConstantInt(0, constantSystem)); 724 insertBoundsCheck(node, receiver, graph.addConstantInt(0, constantSystem));
749 } 725 }
750 } 726 }
751 727
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 // this type for the field is still a strong signal 1345 // this type for the field is still a strong signal
1370 // indicating the expected type of the field. 1346 // indicating the expected type of the field.
1371 types[field] = type; 1347 types[field] = type;
1372 } else { 1348 } else {
1373 // If there are no invoked setters we know the type of 1349 // If there are no invoked setters we know the type of
1374 // this field for sure. 1350 // this field for sure.
1375 field.guaranteedType = type; 1351 field.guaranteedType = type;
1376 } 1352 }
1377 } 1353 }
1378 } 1354 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698