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

Side by Side Diff: pkg/compiler/lib/src/ssa/optimize.dart

Issue 2814453005: Merge CommonElements and BackendHelpers! (Closed)
Patch Set: comments and re-merge, take two Created 3 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
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 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';
11 import '../common_elements.dart' show CommonElements; 11 import '../common_elements.dart' show CommonElements;
12 import '../elements/elements.dart' 12 import '../elements/elements.dart'
13 show ClassElement, FieldElement, MethodElement; 13 show ClassElement, FieldElement, MethodElement;
14 import '../elements/entities.dart'; 14 import '../elements/entities.dart';
15 import '../elements/resolution_types.dart'; 15 import '../elements/resolution_types.dart';
16 import '../js/js.dart' as js; 16 import '../js/js.dart' as js;
17 import '../js_backend/backend_helpers.dart' show BackendHelpers;
18 import '../js_backend/js_backend.dart'; 17 import '../js_backend/js_backend.dart';
19 import '../js_backend/interceptor_data.dart' show InterceptorData; 18 import '../js_backend/interceptor_data.dart' show InterceptorData;
20 import '../js_backend/native_data.dart' show NativeData; 19 import '../js_backend/native_data.dart' show NativeData;
21 import '../native/native.dart' as native; 20 import '../native/native.dart' as native;
22 import '../options.dart'; 21 import '../options.dart';
23 import '../tree/dartstring.dart' as ast; 22 import '../tree/dartstring.dart' as ast;
24 import '../types/types.dart'; 23 import '../types/types.dart';
25 import '../universe/selector.dart' show Selector; 24 import '../universe/selector.dart' show Selector;
26 import '../universe/side_effects.dart' show SideEffects; 25 import '../universe/side_effects.dart' show SideEffects;
27 import '../util/util.dart'; 26 import '../util/util.dart';
(...skipping 16 matching lines...) Expand all
44 Map<HInstruction, Range> ranges = <HInstruction, Range>{}; 43 Map<HInstruction, Range> ranges = <HInstruction, Range>{};
45 44
46 SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer); 45 SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer);
47 46
48 String get name => 'SSA optimizer'; 47 String get name => 'SSA optimizer';
49 48
50 Compiler get _compiler => _backend.compiler; 49 Compiler get _compiler => _backend.compiler;
51 50
52 GlobalTypeInferenceResults get _results => _compiler.globalInference.results; 51 GlobalTypeInferenceResults get _results => _compiler.globalInference.results;
53 52
54 BackendHelpers get _helpers => _backend.helpers;
55
56 CompilerOptions get _options => _compiler.options; 53 CompilerOptions get _options => _compiler.options;
57 54
58 RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions; 55 RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions;
59 56
60 InterceptorData get _interceptorData => _backend.interceptorData; 57 InterceptorData get _interceptorData => _backend.interceptorData;
61 58
62 void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { 59 void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
63 void runPhase(OptimizationPhase phase) { 60 void runPhase(OptimizationPhase phase) {
64 measureSubtask(phase.name, () => phase.visitGraph(graph)); 61 measureSubtask(phase.name, () => phase.visitGraph(graph));
65 _backend.tracer.traceGraph(phase.name, graph); 62 _backend.tracer.traceGraph(phase.name, graph);
66 assert(graph.isValid(), 'Graph not valid after ${phase.name}'); 63 assert(graph.isValid(), 'Graph not valid after ${phase.name}');
67 } 64 }
68 65
69 bool trustPrimitives = _options.trustPrimitives; 66 bool trustPrimitives = _options.trustPrimitives;
70 CodegenRegistry registry = work.registry; 67 CodegenRegistry registry = work.registry;
71 Set<HInstruction> boundsChecked = new Set<HInstruction>(); 68 Set<HInstruction> boundsChecked = new Set<HInstruction>();
72 SsaCodeMotion codeMotion; 69 SsaCodeMotion codeMotion;
73 SsaLoadElimination loadElimination; 70 SsaLoadElimination loadElimination;
74 measure(() { 71 measure(() {
75 List<OptimizationPhase> phases = <OptimizationPhase>[ 72 List<OptimizationPhase> phases = <OptimizationPhase>[
76 // Run trivial instruction simplification first to optimize 73 // Run trivial instruction simplification first to optimize
77 // some patterns useful for type conversion. 74 // some patterns useful for type conversion.
78 new SsaInstructionSimplifier(_results, _options, _helpers, 75 new SsaInstructionSimplifier(
79 _rtiSubstitutions, closedWorld, registry), 76 _results, _options, _rtiSubstitutions, closedWorld, registry),
80 new SsaTypeConversionInserter(closedWorld), 77 new SsaTypeConversionInserter(closedWorld),
81 new SsaRedundantPhiEliminator(), 78 new SsaRedundantPhiEliminator(),
82 new SsaDeadPhiEliminator(), 79 new SsaDeadPhiEliminator(),
83 new SsaTypePropagator(_results, _options, _helpers, closedWorld), 80 new SsaTypePropagator(
81 _results, _options, closedWorld.commonElements, closedWorld),
84 // After type propagation, more instructions can be 82 // After type propagation, more instructions can be
85 // simplified. 83 // simplified.
86 new SsaInstructionSimplifier(_results, _options, _helpers, 84 new SsaInstructionSimplifier(
87 _rtiSubstitutions, closedWorld, registry), 85 _results, _options, _rtiSubstitutions, closedWorld, registry),
88 new SsaCheckInserter( 86 new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
89 trustPrimitives, _helpers, closedWorld, boundsChecked), 87 new SsaInstructionSimplifier(
90 new SsaInstructionSimplifier(_results, _options, _helpers, 88 _results, _options, _rtiSubstitutions, closedWorld, registry),
91 _rtiSubstitutions, closedWorld, registry), 89 new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
92 new SsaCheckInserter( 90 new SsaTypePropagator(
93 trustPrimitives, _helpers, closedWorld, boundsChecked), 91 _results, _options, closedWorld.commonElements, closedWorld),
94 new SsaTypePropagator(_results, _options, _helpers, closedWorld),
95 // Run a dead code eliminator before LICM because dead 92 // Run a dead code eliminator before LICM because dead
96 // interceptors are often in the way of LICM'able instructions. 93 // interceptors are often in the way of LICM'able instructions.
97 new SsaDeadCodeEliminator(closedWorld, this), 94 new SsaDeadCodeEliminator(closedWorld, this),
98 new SsaGlobalValueNumberer(), 95 new SsaGlobalValueNumberer(),
99 // After GVN, some instructions might need their type to be 96 // After GVN, some instructions might need their type to be
100 // updated because they now have different inputs. 97 // updated because they now have different inputs.
101 new SsaTypePropagator(_results, _options, _helpers, closedWorld), 98 new SsaTypePropagator(
99 _results, _options, closedWorld.commonElements, closedWorld),
102 codeMotion = new SsaCodeMotion(), 100 codeMotion = new SsaCodeMotion(),
103 loadElimination = 101 loadElimination = new SsaLoadElimination(_compiler, closedWorld),
104 new SsaLoadElimination(_helpers, _compiler, closedWorld),
105 new SsaRedundantPhiEliminator(), 102 new SsaRedundantPhiEliminator(),
106 new SsaDeadPhiEliminator(), 103 new SsaDeadPhiEliminator(),
107 // After GVN and load elimination the same value may be used in code 104 // After GVN and load elimination the same value may be used in code
108 // controlled by a test on the value, so redo 'conversion insertion' to 105 // controlled by a test on the value, so redo 'conversion insertion' to
109 // learn from the refined type. 106 // learn from the refined type.
110 new SsaTypeConversionInserter(closedWorld), 107 new SsaTypeConversionInserter(closedWorld),
111 new SsaTypePropagator(_results, _options, _helpers, closedWorld), 108 new SsaTypePropagator(
112 new SsaValueRangeAnalyzer(_helpers, closedWorld, this), 109 _results, _options, closedWorld.commonElements, closedWorld),
110 new SsaValueRangeAnalyzer(closedWorld, this),
113 // Previous optimizations may have generated new 111 // Previous optimizations may have generated new
114 // opportunities for instruction simplification. 112 // opportunities for instruction simplification.
115 new SsaInstructionSimplifier(_results, _options, _helpers, 113 new SsaInstructionSimplifier(
116 _rtiSubstitutions, closedWorld, registry), 114 _results, _options, _rtiSubstitutions, closedWorld, registry),
117 new SsaCheckInserter( 115 new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
118 trustPrimitives, _helpers, closedWorld, boundsChecked),
119 ]; 116 ];
120 phases.forEach(runPhase); 117 phases.forEach(runPhase);
121 118
122 // Simplifying interceptors is not strictly just an optimization, it is 119 // Simplifying interceptors is not strictly just an optimization, it is
123 // required for implementation correctness because the code generator 120 // required for implementation correctness because the code generator
124 // assumes it is always performed. 121 // assumes it is always performed.
125 runPhase(new SsaSimplifyInterceptors(closedWorld, _helpers, 122 runPhase(new SsaSimplifyInterceptors(
126 _interceptorData, work.element.enclosingClass)); 123 closedWorld,
124 closedWorld.commonElements,
125 _interceptorData,
126 work.element.enclosingClass));
127 127
128 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this); 128 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this);
129 runPhase(dce); 129 runPhase(dce);
130 if (codeMotion.movedCode || 130 if (codeMotion.movedCode ||
131 dce.eliminatedSideEffects || 131 dce.eliminatedSideEffects ||
132 loadElimination.newGvnCandidates) { 132 loadElimination.newGvnCandidates) {
133 phases = <OptimizationPhase>[ 133 phases = <OptimizationPhase>[
134 new SsaTypePropagator(_results, _options, _helpers, closedWorld), 134 new SsaTypePropagator(
135 _results, _options, closedWorld.commonElements, closedWorld),
135 new SsaGlobalValueNumberer(), 136 new SsaGlobalValueNumberer(),
136 new SsaCodeMotion(), 137 new SsaCodeMotion(),
137 new SsaValueRangeAnalyzer(_helpers, closedWorld, this), 138 new SsaValueRangeAnalyzer(closedWorld, this),
138 new SsaInstructionSimplifier(_results, _options, _helpers, 139 new SsaInstructionSimplifier(
139 _rtiSubstitutions, closedWorld, registry), 140 _results, _options, _rtiSubstitutions, closedWorld, registry),
140 new SsaCheckInserter( 141 new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
141 trustPrimitives, _helpers, closedWorld, boundsChecked), 142 new SsaSimplifyInterceptors(closedWorld, closedWorld.commonElements,
142 new SsaSimplifyInterceptors(closedWorld, _helpers, _interceptorData, 143 _interceptorData, work.element.enclosingClass),
143 work.element.enclosingClass),
144 new SsaDeadCodeEliminator(closedWorld, this), 144 new SsaDeadCodeEliminator(closedWorld, this),
145 ]; 145 ];
146 } else { 146 } else {
147 phases = <OptimizationPhase>[ 147 phases = <OptimizationPhase>[
148 new SsaTypePropagator(_results, _options, _helpers, closedWorld), 148 new SsaTypePropagator(
149 _results, _options, closedWorld.commonElements, closedWorld),
149 // Run the simplifier to remove unneeded type checks inserted by 150 // Run the simplifier to remove unneeded type checks inserted by
150 // type propagation. 151 // type propagation.
151 new SsaInstructionSimplifier(_results, _options, _helpers, 152 new SsaInstructionSimplifier(
152 _rtiSubstitutions, closedWorld, registry), 153 _results, _options, _rtiSubstitutions, closedWorld, registry),
153 ]; 154 ];
154 } 155 }
155 phases.forEach(runPhase); 156 phases.forEach(runPhase);
156 }); 157 });
157 } 158 }
158 } 159 }
159 160
160 /// Returns `true` if [mask] represents only types that have a length that 161 /// Returns `true` if [mask] represents only types that have a length that
161 /// cannot change. The current implementation is conservative for the purpose 162 /// cannot change. The current implementation is conservative for the purpose
162 /// of identifying gvn-able lengths and mis-identifies some unions of fixed 163 /// of identifying gvn-able lengths and mis-identifies some unions of fixed
(...skipping 20 matching lines...) Expand all
183 class SsaInstructionSimplifier extends HBaseVisitor 184 class SsaInstructionSimplifier extends HBaseVisitor
184 implements OptimizationPhase { 185 implements OptimizationPhase {
185 // We don't produce constant-folded strings longer than this unless they have 186 // We don't produce constant-folded strings longer than this unless they have
186 // a single use. This protects against exponentially large constant folded 187 // a single use. This protects against exponentially large constant folded
187 // strings. 188 // strings.
188 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; 189 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512;
189 190
190 final String name = "SsaInstructionSimplifier"; 191 final String name = "SsaInstructionSimplifier";
191 final GlobalTypeInferenceResults _globalInferenceResults; 192 final GlobalTypeInferenceResults _globalInferenceResults;
192 final CompilerOptions _options; 193 final CompilerOptions _options;
193 final BackendHelpers _helpers;
194 final RuntimeTypesSubstitutions _rtiSubstitutions; 194 final RuntimeTypesSubstitutions _rtiSubstitutions;
195 final ClosedWorld _closedWorld; 195 final ClosedWorld _closedWorld;
196 final CodegenRegistry _registry; 196 final CodegenRegistry _registry;
197 HGraph _graph; 197 HGraph _graph;
198 198
199 SsaInstructionSimplifier(this._globalInferenceResults, this._options, 199 SsaInstructionSimplifier(this._globalInferenceResults, this._options,
200 this._helpers, this._rtiSubstitutions, this._closedWorld, this._registry); 200 this._rtiSubstitutions, this._closedWorld, this._registry);
201 201
202 CommonElements get commonElements => _closedWorld.commonElements; 202 CommonElements get commonElements => _closedWorld.commonElements;
203 203
204 ConstantSystem get constantSystem => _closedWorld.constantSystem; 204 ConstantSystem get constantSystem => _closedWorld.constantSystem;
205 205
206 NativeData get _nativeData => _closedWorld.nativeData; 206 NativeData get _nativeData => _closedWorld.nativeData;
207 207
208 void visitGraph(HGraph visitee) { 208 void visitGraph(HGraph visitee) {
209 _graph = visitee; 209 _graph = visitee;
210 visitDominatorTree(visitee); 210 visitDominatorTree(visitee);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 if (input.isBoolean(_closedWorld)) return input; 314 if (input.isBoolean(_closedWorld)) return input;
315 315
316 // If the code is unreachable, remove the HBoolify. This can happen when 316 // If the code is unreachable, remove the HBoolify. This can happen when
317 // there is a throw expression in a short-circuit conditional. Removing the 317 // there is a throw expression in a short-circuit conditional. Removing the
318 // unreachable HBoolify makes it easier to reconstruct the short-circuit 318 // unreachable HBoolify makes it easier to reconstruct the short-circuit
319 // operation. 319 // operation.
320 if (input.instructionType.isEmpty) return input; 320 if (input.instructionType.isEmpty) return input;
321 321
322 // All values that cannot be 'true' are boolified to false. 322 // All values that cannot be 'true' are boolified to false.
323 TypeMask mask = input.instructionType; 323 TypeMask mask = input.instructionType;
324 if (!mask.contains(_helpers.jsBoolClass, _closedWorld)) { 324 if (!mask.contains(commonElements.jsBoolClass, _closedWorld)) {
325 return _graph.addConstantBool(false, _closedWorld); 325 return _graph.addConstantBool(false, _closedWorld);
326 } 326 }
327 return node; 327 return node;
328 } 328 }
329 329
330 HInstruction visitNot(HNot node) { 330 HInstruction visitNot(HNot node) {
331 List<HInstruction> inputs = node.inputs; 331 List<HInstruction> inputs = node.inputs;
332 assert(inputs.length == 1); 332 assert(inputs.length == 1);
333 HInstruction input = inputs[0]; 333 HInstruction input = inputs[0];
334 if (input is HConstant) { 334 if (input is HConstant) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 HConstant constantInput = actualReceiver; 367 HConstant constantInput = actualReceiver;
368 ListConstantValue constant = constantInput.constant; 368 ListConstantValue constant = constantInput.constant;
369 return _graph.addConstantInt(constant.length, _closedWorld); 369 return _graph.addConstantInt(constant.length, _closedWorld);
370 } 370 }
371 bool isFixed = 371 bool isFixed =
372 isFixedLength(actualReceiver.instructionType, _closedWorld); 372 isFixedLength(actualReceiver.instructionType, _closedWorld);
373 TypeMask actualType = node.instructionType; 373 TypeMask actualType = node.instructionType;
374 TypeMask resultType = _closedWorld.commonMasks.positiveIntType; 374 TypeMask resultType = _closedWorld.commonMasks.positiveIntType;
375 // If we already have computed a more specific type, keep that type. 375 // If we already have computed a more specific type, keep that type.
376 if (HInstruction.isInstanceOf( 376 if (HInstruction.isInstanceOf(
377 actualType, _helpers.jsUInt31Class, _closedWorld)) { 377 actualType, commonElements.jsUInt31Class, _closedWorld)) {
378 resultType = _closedWorld.commonMasks.uint31Type; 378 resultType = _closedWorld.commonMasks.uint31Type;
379 } else if (HInstruction.isInstanceOf( 379 } else if (HInstruction.isInstanceOf(
380 actualType, _helpers.jsUInt32Class, _closedWorld)) { 380 actualType, commonElements.jsUInt32Class, _closedWorld)) {
381 resultType = _closedWorld.commonMasks.uint32Type; 381 resultType = _closedWorld.commonMasks.uint32Type;
382 } 382 }
383 HGetLength result = 383 HGetLength result =
384 new HGetLength(actualReceiver, resultType, isAssignable: !isFixed); 384 new HGetLength(actualReceiver, resultType, isAssignable: !isFixed);
385 return result; 385 return result;
386 } else if (actualReceiver.isConstantMap()) { 386 } else if (actualReceiver.isConstantMap()) {
387 HConstant constantInput = actualReceiver; 387 HConstant constantInput = actualReceiver;
388 MapConstantValue constant = constantInput.constant; 388 MapConstantValue constant = constantInput.constant;
389 return _graph.addConstantInt(constant.length, _closedWorld); 389 return _graph.addConstantInt(constant.length, _closedWorld);
390 } 390 }
391 return null; 391 return null;
392 } 392 }
393 393
394 HInstruction handleInterceptedCall(HInvokeDynamic node) { 394 HInstruction handleInterceptedCall(HInvokeDynamic node) {
395 // Try constant folding the instruction. 395 // Try constant folding the instruction.
396 Operation operation = node.specializer.operation(constantSystem); 396 Operation operation = node.specializer.operation(constantSystem);
397 if (operation != null) { 397 if (operation != null) {
398 HInstruction instruction = node.inputs.length == 2 398 HInstruction instruction = node.inputs.length == 2
399 ? foldUnary(operation, node.inputs[1]) 399 ? foldUnary(operation, node.inputs[1])
400 : foldBinary(operation, node.inputs[1], node.inputs[2]); 400 : foldBinary(operation, node.inputs[1], node.inputs[2]);
401 if (instruction != null) return instruction; 401 if (instruction != null) return instruction;
402 } 402 }
403 403
404 // Try converting the instruction to a builtin instruction. 404 // Try converting the instruction to a builtin instruction.
405 HInstruction instruction = node.specializer.tryConvertToBuiltin(node, 405 HInstruction instruction = node.specializer.tryConvertToBuiltin(
406 _graph, _globalInferenceResults, _options, _helpers, _closedWorld); 406 node,
407 _graph,
408 _globalInferenceResults,
409 _options,
410 commonElements,
411 _closedWorld);
407 if (instruction != null) return instruction; 412 if (instruction != null) return instruction;
408 413
409 Selector selector = node.selector; 414 Selector selector = node.selector;
410 TypeMask mask = node.mask; 415 TypeMask mask = node.mask;
411 HInstruction input = node.inputs[1]; 416 HInstruction input = node.inputs[1];
412 417
413 bool applies(MemberEntity element) { 418 bool applies(MemberEntity element) {
414 return selector.applies(element) && 419 return selector.applies(element) &&
415 (mask == null || mask.canHit(element, selector, _closedWorld)); 420 (mask == null || mask.canHit(element, selector, _closedWorld));
416 } 421 }
417 422
418 if (selector.isCall || selector.isOperator) { 423 if (selector.isCall || selector.isOperator) {
419 FunctionEntity target; 424 FunctionEntity target;
420 if (input.isExtendableArray(_closedWorld)) { 425 if (input.isExtendableArray(_closedWorld)) {
421 if (applies(_helpers.jsArrayRemoveLast)) { 426 if (applies(commonElements.jsArrayRemoveLast)) {
422 target = _helpers.jsArrayRemoveLast; 427 target = commonElements.jsArrayRemoveLast;
423 } else if (applies(_helpers.jsArrayAdd)) { 428 } else if (applies(commonElements.jsArrayAdd)) {
424 // The codegen special cases array calls, but does not 429 // The codegen special cases array calls, but does not
425 // inline argument type checks. 430 // inline argument type checks.
426 if (!_options.enableTypeAssertions) { 431 if (!_options.enableTypeAssertions) {
427 target = _helpers.jsArrayAdd; 432 target = commonElements.jsArrayAdd;
428 } 433 }
429 } 434 }
430 } else if (input.isStringOrNull(_closedWorld)) { 435 } else if (input.isStringOrNull(_closedWorld)) {
431 if (applies(_helpers.jsStringSplit)) { 436 if (applies(commonElements.jsStringSplit)) {
432 HInstruction argument = node.inputs[2]; 437 HInstruction argument = node.inputs[2];
433 if (argument.isString(_closedWorld)) { 438 if (argument.isString(_closedWorld)) {
434 target = _helpers.jsStringSplit; 439 target = commonElements.jsStringSplit;
435 } 440 }
436 } else if (applies(_helpers.jsStringOperatorAdd)) { 441 } else if (applies(commonElements.jsStringOperatorAdd)) {
437 // `operator+` is turned into a JavaScript '+' so we need to 442 // `operator+` is turned into a JavaScript '+' so we need to
438 // make sure the receiver and the argument are not null. 443 // make sure the receiver and the argument are not null.
439 // TODO(sra): Do this via [node.specializer]. 444 // TODO(sra): Do this via [node.specializer].
440 HInstruction argument = node.inputs[2]; 445 HInstruction argument = node.inputs[2];
441 if (argument.isString(_closedWorld) && !input.canBeNull()) { 446 if (argument.isString(_closedWorld) && !input.canBeNull()) {
442 return new HStringConcat(input, argument, node.instructionType); 447 return new HStringConcat(input, argument, node.instructionType);
443 } 448 }
444 } else if (applies(_helpers.jsStringToString) && !input.canBeNull()) { 449 } else if (applies(commonElements.jsStringToString) &&
450 !input.canBeNull()) {
445 return input; 451 return input;
446 } 452 }
447 } 453 }
448 if (target != null) { 454 if (target != null) {
449 // TODO(ngeoffray): There is a strong dependency between codegen 455 // TODO(ngeoffray): There is a strong dependency between codegen
450 // and this optimization that the dynamic invoke does not need an 456 // and this optimization that the dynamic invoke does not need an
451 // interceptor. We currently need to keep a 457 // interceptor. We currently need to keep a
452 // HInvokeDynamicMethod and not create a HForeign because 458 // HInvokeDynamicMethod and not create a HForeign because
453 // HForeign is too opaque for the SsaCheckInserter (that adds a 459 // HForeign is too opaque for the SsaCheckInserter (that adds a
454 // bounds check on removeLast). Once we start inlining, the 460 // bounds check on removeLast). Once we start inlining, the
455 // bounds check will become explicit, so we won't need this 461 // bounds check will become explicit, so we won't need this
456 // optimization. 462 // optimization.
457 HInvokeDynamicMethod result = new HInvokeDynamicMethod(node.selector, 463 HInvokeDynamicMethod result = new HInvokeDynamicMethod(node.selector,
458 node.mask, node.inputs.sublist(1), node.instructionType); 464 node.mask, node.inputs.sublist(1), node.instructionType);
459 result.element = target; 465 result.element = target;
460 return result; 466 return result;
461 } 467 }
462 } else if (selector.isGetter) { 468 } else if (selector.isGetter) {
463 if (selector.applies(_helpers.jsIndexableLength)) { 469 if (selector.applies(commonElements.jsIndexableLength)) {
464 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node); 470 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
465 if (optimized != null) return optimized; 471 if (optimized != null) return optimized;
466 } 472 }
467 } 473 }
468 474
469 return node; 475 return node;
470 } 476 }
471 477
472 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 478 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
473 propagateConstantValueToUses(node); 479 propagateConstantValueToUses(node);
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 HInstruction visitInvokeStatic(HInvokeStatic node) { 1067 HInstruction visitInvokeStatic(HInvokeStatic node) {
1062 propagateConstantValueToUses(node); 1068 propagateConstantValueToUses(node);
1063 MemberEntity element = node.element; 1069 MemberEntity element = node.element;
1064 1070
1065 if (element == commonElements.identicalFunction) { 1071 if (element == commonElements.identicalFunction) {
1066 if (node.inputs.length == 2) { 1072 if (node.inputs.length == 2) {
1067 return new HIdentity(node.inputs[0], node.inputs[1], null, 1073 return new HIdentity(node.inputs[0], node.inputs[1], null,
1068 _closedWorld.commonMasks.boolType) 1074 _closedWorld.commonMasks.boolType)
1069 ..sourceInformation = node.sourceInformation; 1075 ..sourceInformation = node.sourceInformation;
1070 } 1076 }
1071 } else if (element == _helpers.checkConcurrentModificationError) { 1077 } else if (element == commonElements.checkConcurrentModificationError) {
1072 if (node.inputs.length == 2) { 1078 if (node.inputs.length == 2) {
1073 HInstruction firstArgument = node.inputs[0]; 1079 HInstruction firstArgument = node.inputs[0];
1074 if (firstArgument is HConstant) { 1080 if (firstArgument is HConstant) {
1075 HConstant constant = firstArgument; 1081 HConstant constant = firstArgument;
1076 if (constant.constant.isTrue) return constant; 1082 if (constant.constant.isTrue) return constant;
1077 } 1083 }
1078 } 1084 }
1079 } else if (element == _helpers.checkInt) { 1085 } else if (element == commonElements.checkInt) {
1080 if (node.inputs.length == 1) { 1086 if (node.inputs.length == 1) {
1081 HInstruction argument = node.inputs[0]; 1087 HInstruction argument = node.inputs[0];
1082 if (argument.isInteger(_closedWorld)) return argument; 1088 if (argument.isInteger(_closedWorld)) return argument;
1083 } 1089 }
1084 } else if (element == _helpers.checkNum) { 1090 } else if (element == commonElements.checkNum) {
1085 if (node.inputs.length == 1) { 1091 if (node.inputs.length == 1) {
1086 HInstruction argument = node.inputs[0]; 1092 HInstruction argument = node.inputs[0];
1087 if (argument.isNumber(_closedWorld)) return argument; 1093 if (argument.isNumber(_closedWorld)) return argument;
1088 } 1094 }
1089 } else if (element == _helpers.checkString) { 1095 } else if (element == commonElements.checkString) {
1090 if (node.inputs.length == 1) { 1096 if (node.inputs.length == 1) {
1091 HInstruction argument = node.inputs[0]; 1097 HInstruction argument = node.inputs[0];
1092 if (argument.isString(_closedWorld)) return argument; 1098 if (argument.isString(_closedWorld)) return argument;
1093 } 1099 }
1094 } 1100 }
1095 return node; 1101 return node;
1096 } 1102 }
1097 1103
1098 HInstruction visitStringConcat(HStringConcat node) { 1104 HInstruction visitStringConcat(HStringConcat node) {
1099 // Simplify string concat: 1105 // Simplify string concat:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 // (since SsaInstructionSimplifier runs after SsaSimplifyInterceptors). 1177 // (since SsaInstructionSimplifier runs after SsaSimplifyInterceptors).
1172 if (input.canBePrimitive(_closedWorld)) return null; 1178 if (input.canBePrimitive(_closedWorld)) return null;
1173 if (input.canBeNull()) return null; 1179 if (input.canBeNull()) return null;
1174 Selector selector = Selectors.toString_; 1180 Selector selector = Selectors.toString_;
1175 TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector( 1181 TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector(
1176 selector, input.instructionType, _globalInferenceResults); 1182 selector, input.instructionType, _globalInferenceResults);
1177 if (!toStringType.containsOnlyString(_closedWorld)) return null; 1183 if (!toStringType.containsOnlyString(_closedWorld)) return null;
1178 // All intercepted classes extend `Interceptor`, so if the receiver can't 1184 // All intercepted classes extend `Interceptor`, so if the receiver can't
1179 // be a class extending `Interceptor` then it can be called directly. 1185 // be a class extending `Interceptor` then it can be called directly.
1180 if (new TypeMask.nonNullSubclass( 1186 if (new TypeMask.nonNullSubclass(
1181 _helpers.jsInterceptorClass, _closedWorld) 1187 commonElements.jsInterceptorClass, _closedWorld)
1182 .isDisjoint(input.instructionType, _closedWorld)) { 1188 .isDisjoint(input.instructionType, _closedWorld)) {
1183 var inputs = <HInstruction>[input, input]; // [interceptor, receiver]. 1189 var inputs = <HInstruction>[input, input]; // [interceptor, receiver].
1184 HInstruction result = new HInvokeDynamicMethod( 1190 HInstruction result = new HInvokeDynamicMethod(
1185 selector, 1191 selector,
1186 input.instructionType, // receiver mask. 1192 input.instructionType, // receiver mask.
1187 inputs, 1193 inputs,
1188 toStringType) 1194 toStringType)
1189 ..sourceInformation = node.sourceInformation; 1195 ..sourceInformation = node.sourceInformation;
1190 return result; 1196 return result;
1191 } 1197 }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 // arguments. The [selectTypeArgumentFromObjectCreation] argument of 1370 // arguments. The [selectTypeArgumentFromObjectCreation] argument of
1365 // [finishSubstituted] indexes into these type arguments. 1371 // [finishSubstituted] indexes into these type arguments.
1366 1372
1367 return node; 1373 return node;
1368 } 1374 }
1369 } 1375 }
1370 1376
1371 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { 1377 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
1372 final Set<HInstruction> boundsChecked; 1378 final Set<HInstruction> boundsChecked;
1373 final bool trustPrimitives; 1379 final bool trustPrimitives;
1374 final BackendHelpers _helpers;
1375 final ClosedWorld closedWorld; 1380 final ClosedWorld closedWorld;
1376 final String name = "SsaCheckInserter"; 1381 final String name = "SsaCheckInserter";
1377 HGraph graph; 1382 HGraph graph;
1378 1383
1379 SsaCheckInserter(this.trustPrimitives, this._helpers, this.closedWorld, 1384 SsaCheckInserter(this.trustPrimitives, this.closedWorld, this.boundsChecked);
1380 this.boundsChecked);
1381 1385
1382 void visitGraph(HGraph graph) { 1386 void visitGraph(HGraph graph) {
1383 this.graph = graph; 1387 this.graph = graph;
1384 1388
1385 // In --trust-primitives mode we don't add bounds checks. This is better 1389 // In --trust-primitives mode we don't add bounds checks. This is better
1386 // than trying to remove them later as the limit expression would become 1390 // than trying to remove them later as the limit expression would become
1387 // dead and require DCE. 1391 // dead and require DCE.
1388 if (trustPrimitives) return; 1392 if (trustPrimitives) return;
1389 1393
1390 visitDominatorTree(graph); 1394 visitDominatorTree(graph);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 1437
1434 void visitIndexAssign(HIndexAssign node) { 1438 void visitIndexAssign(HIndexAssign node) {
1435 if (boundsChecked.contains(node)) return; 1439 if (boundsChecked.contains(node)) return;
1436 HInstruction index = node.index; 1440 HInstruction index = node.index;
1437 index = insertBoundsCheck(node, node.receiver, index); 1441 index = insertBoundsCheck(node, node.receiver, index);
1438 } 1442 }
1439 1443
1440 void visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1444 void visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1441 MemberEntity element = node.element; 1445 MemberEntity element = node.element;
1442 if (node.isInterceptedCall) return; 1446 if (node.isInterceptedCall) return;
1443 if (element != _helpers.jsArrayRemoveLast) return; 1447 if (element != closedWorld.commonElements.jsArrayRemoveLast) return;
1444 if (boundsChecked.contains(node)) return; 1448 if (boundsChecked.contains(node)) return;
1445 // `0` is the index we want to check, but we want to report `-1`, as if we 1449 // `0` is the index we want to check, but we want to report `-1`, as if we
1446 // executed `a[a.length-1]` 1450 // executed `a[a.length-1]`
1447 HBoundsCheck check = insertBoundsCheck( 1451 HBoundsCheck check = insertBoundsCheck(
1448 node, node.receiver, graph.addConstantInt(0, closedWorld)); 1452 node, node.receiver, graph.addConstantInt(0, closedWorld));
1449 HInstruction minusOne = graph.addConstantInt(-1, closedWorld); 1453 HInstruction minusOne = graph.addConstantInt(-1, closedWorld);
1450 check.inputs.add(minusOne); 1454 check.inputs.add(minusOne);
1451 minusOne.usedBy.add(check); 1455 minusOne.usedBy.add(check);
1452 } 1456 }
1453 } 1457 }
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
2293 } 2297 }
2294 } 2298 }
2295 } 2299 }
2296 2300
2297 /** 2301 /**
2298 * Optimization phase that tries to eliminate memory loads (for 2302 * Optimization phase that tries to eliminate memory loads (for
2299 * example [HFieldGet]), when it knows the value stored in that memory 2303 * example [HFieldGet]), when it knows the value stored in that memory
2300 * location. 2304 * location.
2301 */ 2305 */
2302 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { 2306 class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
2303 final BackendHelpers _helpers;
2304 final Compiler compiler; 2307 final Compiler compiler;
2305 final ClosedWorld closedWorld; 2308 final ClosedWorld closedWorld;
2306 final String name = "SsaLoadElimination"; 2309 final String name = "SsaLoadElimination";
2307 MemorySet memorySet; 2310 MemorySet memorySet;
2308 List<MemorySet> memories; 2311 List<MemorySet> memories;
2309 bool newGvnCandidates = false; 2312 bool newGvnCandidates = false;
2310 2313
2311 SsaLoadElimination(this._helpers, this.compiler, this.closedWorld); 2314 SsaLoadElimination(this.compiler, this.closedWorld);
2312 2315
2313 void visitGraph(HGraph graph) { 2316 void visitGraph(HGraph graph) {
2314 memories = new List<MemorySet>(graph.blocks.length); 2317 memories = new List<MemorySet>(graph.blocks.length);
2315 List<HBasicBlock> blocks = graph.blocks; 2318 List<HBasicBlock> blocks = graph.blocks;
2316 for (int i = 0; i < blocks.length; i++) { 2319 for (int i = 0; i < blocks.length; i++) {
2317 HBasicBlock block = blocks[i]; 2320 HBasicBlock block = blocks[i];
2318 visitBasicBlock(block); 2321 visitBasicBlock(block);
2319 if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) { 2322 if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) {
2320 // We've reached the ending block of a loop. Iterate over the 2323 // We've reached the ending block of a loop. Iterate over the
2321 // blocks of the loop again to take values that flow from that 2324 // blocks of the loop again to take values that flow from that
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2370 } 2373 }
2371 2374
2372 void visitFieldGet(HFieldGet instruction) { 2375 void visitFieldGet(HFieldGet instruction) {
2373 if (instruction.isNullCheck) return; 2376 if (instruction.isNullCheck) return;
2374 FieldEntity element = instruction.element; 2377 FieldEntity element = instruction.element;
2375 HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); 2378 HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck();
2376 _visitFieldGet(element, receiver, instruction); 2379 _visitFieldGet(element, receiver, instruction);
2377 } 2380 }
2378 2381
2379 void visitGetLength(HGetLength instruction) { 2382 void visitGetLength(HGetLength instruction) {
2380 _visitFieldGet(_helpers.jsIndexableLength, instruction.receiver.nonCheck(), 2383 _visitFieldGet(closedWorld.commonElements.jsIndexableLength,
2381 instruction); 2384 instruction.receiver.nonCheck(), instruction);
2382 } 2385 }
2383 2386
2384 void _visitFieldGet( 2387 void _visitFieldGet(
2385 MemberEntity element, HInstruction receiver, HInstruction instruction) { 2388 MemberEntity element, HInstruction receiver, HInstruction instruction) {
2386 HInstruction existing = memorySet.lookupFieldValue(element, receiver); 2389 HInstruction existing = memorySet.lookupFieldValue(element, receiver);
2387 if (existing != null) { 2390 if (existing != null) {
2388 checkNewGvnCandidates(instruction, existing); 2391 checkNewGvnCandidates(instruction, existing);
2389 instruction.block.rewriteWithBetterUser(instruction, existing); 2392 instruction.block.rewriteWithBetterUser(instruction, existing);
2390 instruction.block.remove(instruction); 2393 instruction.block.remove(instruction);
2391 } else { 2394 } else {
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
2858 2861
2859 keyedValues.forEach((receiver, values) { 2862 keyedValues.forEach((receiver, values) {
2860 result.keyedValues[receiver] = 2863 result.keyedValues[receiver] =
2861 new Map<HInstruction, HInstruction>.from(values); 2864 new Map<HInstruction, HInstruction>.from(values);
2862 }); 2865 });
2863 2866
2864 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2867 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2865 return result; 2868 return result;
2866 } 2869 }
2867 } 2870 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart ('k') | pkg/compiler/lib/src/ssa/types_propagation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698