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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library dart2js.cps_ir.shrinking_reductions; 5 library dart2js.cps_ir.shrinking_reductions;
6 6
7 import 'cps_ir_nodes.dart'; 7 import 'cps_ir_nodes.dart';
8 import 'optimizers.dart'; 8 import 'optimizers.dart';
9 9
10 /** 10 /**
(...skipping 21 matching lines...) Expand all
32 _ReductionTask task = _worklist.removeLast(); 32 _ReductionTask task = _worklist.removeLast();
33 _processTask(task); 33 _processTask(task);
34 } 34 }
35 } 35 }
36 36
37 /// Call instead of [_iterateWorklist] to check at every step that no 37 /// Call instead of [_iterateWorklist] to check at every step that no
38 /// redex was missed. 38 /// redex was missed.
39 void _debugWorklist(FunctionDefinition root) { 39 void _debugWorklist(FunctionDefinition root) {
40 while (_worklist.isNotEmpty) { 40 while (_worklist.isNotEmpty) {
41 _ReductionTask task = _worklist.removeLast(); 41 _ReductionTask task = _worklist.removeLast();
42 String irBefore = root.debugString({ 42 String irBefore =
43 task.node: '${task.kind} applied here' 43 root.debugString({task.node: '${task.kind} applied here'});
44 });
45 _processTask(task); 44 _processTask(task);
46 Set seenRedexes = _worklist.where(isValidTask).toSet(); 45 Set seenRedexes = _worklist.where(isValidTask).toSet();
47 Set actualRedexes = (new _RedexVisitor([])..visit(root)).worklist.toSet(); 46 Set actualRedexes = (new _RedexVisitor([])..visit(root)).worklist.toSet();
48 if (!seenRedexes.containsAll(actualRedexes)) { 47 if (!seenRedexes.containsAll(actualRedexes)) {
49 _ReductionTask missedTask = 48 _ReductionTask missedTask =
50 actualRedexes.firstWhere((x) => !seenRedexes.contains(x)); 49 actualRedexes.firstWhere((x) => !seenRedexes.contains(x));
51 print('\nBEFORE $task:\n'); 50 print('\nBEFORE $task:\n');
52 print(irBefore); 51 print(irBefore);
53 print('\nAFTER $task:\n'); 52 print('\nAFTER $task:\n');
54 root.debugPrint({ 53 root.debugPrint({missedTask.node: 'MISSED ${missedTask.kind}'});
55 missedTask.node: 'MISSED ${missedTask.kind}'
56 });
57 throw 'Missed $missedTask after processing $task'; 54 throw 'Missed $missedTask after processing $task';
58 } 55 }
59 } 56 }
60 } 57 }
61 58
62 bool isValidTask(_ReductionTask task) { 59 bool isValidTask(_ReductionTask task) {
63 switch (task.kind) { 60 switch (task.kind) {
64 case _ReductionKind.DEAD_VAL: 61 case _ReductionKind.DEAD_VAL:
65 return _isDeadVal(task.node); 62 return _isDeadVal(task.node);
66 case _ReductionKind.DEAD_CONT: 63 case _ReductionKind.DEAD_CONT:
67 return _isDeadCont(task.node); 64 return _isDeadCont(task.node);
68 case _ReductionKind.BETA_CONT_LIN: 65 case _ReductionKind.BETA_CONT_LIN:
69 return _isBetaContLin(task.node); 66 return _isBetaContLin(task.node);
70 case _ReductionKind.ETA_CONT: 67 case _ReductionKind.ETA_CONT:
71 return _isEtaCont(task.node); 68 return _isEtaCont(task.node);
72 case _ReductionKind.DEAD_PARAMETER: 69 case _ReductionKind.DEAD_PARAMETER:
73 return _isDeadParameter(task.node); 70 return _isDeadParameter(task.node);
74 case _ReductionKind.BRANCH: 71 case _ReductionKind.BRANCH:
75 return _isBranchRedex(task.node); 72 return _isBranchRedex(task.node);
76 } 73 }
77 } 74 }
78 75
79 /// Removes the given node from the CPS graph, replacing it with its body 76 /// Removes the given node from the CPS graph, replacing it with its body
80 /// and marking it as deleted. The node's parent must be a [[InteriorNode]]. 77 /// and marking it as deleted. The node's parent must be a [[InteriorNode]].
81 void _removeNode(InteriorNode node) { 78 void _removeNode(InteriorNode node) {
82 Node body = node.body; 79 Node body = node.body;
83 InteriorNode parent = node.parent; 80 InteriorNode parent = node.parent;
84 assert(parent.body == node); 81 assert(parent.body == node);
85 82
86 body.parent = parent; 83 body.parent = parent;
87 parent.body = body; 84 parent.body = body;
88 node.parent = null; 85 node.parent = null;
89 86
90 // The removed node could be the last node between a continuation and 87 // The removed node could be the last node between a continuation and
91 // an InvokeContinuation in the body. 88 // an InvokeContinuation in the body.
92 if (parent is Continuation) { 89 if (parent is Continuation) {
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 if (condition is Constant) { 281 if (condition is Constant) {
285 target = isTruthyConstant(condition.value, strict: branch.isStrictCheck) 282 target = isTruthyConstant(condition.value, strict: branch.isStrictCheck)
286 ? branch.trueContinuation 283 ? branch.trueContinuation
287 : branch.falseContinuation; 284 : branch.falseContinuation;
288 } else if (_isBranchTargetOfUselessIf(branch.trueContinuation)) { 285 } else if (_isBranchTargetOfUselessIf(branch.trueContinuation)) {
289 target = branch.trueContinuation; 286 target = branch.trueContinuation;
290 } else { 287 } else {
291 return; 288 return;
292 } 289 }
293 290
294 InvokeContinuation invoke = new InvokeContinuation( 291 InvokeContinuation invoke = new InvokeContinuation(target, <Primitive>[]
295 target, <Primitive>[]
296 // TODO(sra): Add sourceInformation. 292 // TODO(sra): Add sourceInformation.
297 /*, sourceInformation: branch.sourceInformation*/); 293 /*, sourceInformation: branch.sourceInformation*/);
298 branch.parent.body = invoke; 294 branch.parent.body = invoke;
299 invoke.parent = branch.parent; 295 invoke.parent = branch.parent;
300 branch.parent = null; 296 branch.parent = null;
301 297
302 new _RemovalVisitor(_worklist).visit(branch); 298 new _RemovalVisitor(_worklist).visit(branch);
303 } 299 }
304 300
305 void _reduceDeadParameter(_ReductionTask task) { 301 void _reduceDeadParameter(_ReductionTask task) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 } 345 }
350 346
351 void _checkEtaCont(Continuation continuation) { 347 void _checkEtaCont(Continuation continuation) {
352 if (_isEtaCont(continuation)) { 348 if (_isEtaCont(continuation)) {
353 _worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, continuation)); 349 _worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, continuation));
354 } 350 }
355 } 351 }
356 352
357 void _checkUselessBranchTarget(Continuation continuation) { 353 void _checkUselessBranchTarget(Continuation continuation) {
358 if (_isBranchTargetOfUselessIf(continuation)) { 354 if (_isBranchTargetOfUselessIf(continuation)) {
359 _worklist.add(new _ReductionTask(_ReductionKind.BRANCH, 355 _worklist.add(new _ReductionTask(
360 continuation.firstRef.parent)); 356 _ReductionKind.BRANCH, continuation.firstRef.parent));
361 } 357 }
362 } 358 }
363 359
364 void _checkConstantBranchCondition(Primitive primitive) { 360 void _checkConstantBranchCondition(Primitive primitive) {
365 if (primitive is! Constant) return; 361 if (primitive is! Constant) return;
366 for (Reference ref = primitive.firstRef; ref != null; ref = ref.next) { 362 for (Reference ref = primitive.firstRef; ref != null; ref = ref.next) {
367 Node use = ref.parent; 363 Node use = ref.parent;
368 if (use is Branch) { 364 if (use is Branch) {
369 _worklist.add(new _ReductionTask(_ReductionKind.BRANCH, use)); 365 _worklist.add(new _ReductionTask(_ReductionKind.BRANCH, use));
370 } 366 }
371 } 367 }
372 } 368 }
373 369
374 void _checkDeadPrimitive(Primitive primitive) { 370 void _checkDeadPrimitive(Primitive primitive) {
375 primitive = primitive.unrefined; 371 primitive = primitive.unrefined;
376 if (primitive is Parameter) { 372 if (primitive is Parameter) {
377 if (_isDeadParameter(primitive)) { 373 if (_isDeadParameter(primitive)) {
378 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, 374 _worklist
379 primitive)); 375 .add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, primitive));
380 } 376 }
381 } else if (primitive.parent is LetPrim) { 377 } else if (primitive.parent is LetPrim) {
382 LetPrim letPrim = primitive.parent; 378 LetPrim letPrim = primitive.parent;
383 if (_isDeadVal(letPrim)) { 379 if (_isDeadVal(letPrim)) {
384 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, letPrim)); 380 _worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, letPrim));
385 } 381 }
386 } 382 }
387 } 383 }
388 } 384 }
389 385
390 bool _isRemoved(InteriorNode node) { 386 bool _isRemoved(InteriorNode node) {
391 return node.parent == null; 387 return node.parent == null;
392 } 388 }
393 389
394 bool _isParameterRemoved(Parameter parameter) { 390 bool _isParameterRemoved(Parameter parameter) {
395 // A parameter can be removed directly or because its continuation is removed. 391 // A parameter can be removed directly or because its continuation is removed.
396 return parameter.parent == null || _isRemoved(parameter.parent); 392 return parameter.parent == null || _isRemoved(parameter.parent);
397 } 393 }
398 394
399 /// Returns true iff the bound primitive is unused, and has no effects 395 /// Returns true iff the bound primitive is unused, and has no effects
400 /// preventing it from being eliminated. 396 /// preventing it from being eliminated.
401 bool _isDeadVal(LetPrim node) { 397 bool _isDeadVal(LetPrim node) {
402 return !_isRemoved(node) && 398 return !_isRemoved(node) &&
403 node.primitive.hasNoRefinedUses && 399 node.primitive.hasNoRefinedUses &&
404 node.primitive.isSafeForElimination; 400 node.primitive.isSafeForElimination;
405 } 401 }
406 402
407 /// Returns true iff the continuation is unused. 403 /// Returns true iff the continuation is unused.
408 bool _isDeadCont(Continuation cont) { 404 bool _isDeadCont(Continuation cont) {
409 return !_isRemoved(cont) && 405 return !_isRemoved(cont) &&
410 !cont.isReturnContinuation && 406 !cont.isReturnContinuation &&
411 !cont.hasAtLeastOneUse; 407 !cont.hasAtLeastOneUse;
412 } 408 }
413 409
414 /// Returns true iff the continuation has a body (i.e., it is not the return 410 /// Returns true iff the continuation has a body (i.e., it is not the return
415 /// continuation), it is used exactly once, and that use is as the continuation 411 /// continuation), it is used exactly once, and that use is as the continuation
416 /// of a continuation invocation. 412 /// of a continuation invocation.
417 bool _isBetaContLin(Continuation cont) { 413 bool _isBetaContLin(Continuation cont) {
418 if (_isRemoved(cont)) return false; 414 if (_isRemoved(cont)) return false;
419 415
420 // There is a restriction on continuation eta-redexes that the body is not an 416 // There is a restriction on continuation eta-redexes that the body is not an
421 // invocation of the return continuation, because that leads to worse code 417 // invocation of the return continuation, because that leads to worse code
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 530
535 bool _isUselessIf(Branch branch) { 531 bool _isUselessIf(Branch branch) {
536 Continuation trueCont = branch.trueContinuation; 532 Continuation trueCont = branch.trueContinuation;
537 Expression trueBody = _unfoldDeadRefinements(trueCont.body); 533 Expression trueBody = _unfoldDeadRefinements(trueCont.body);
538 if (trueBody is! InvokeContinuation) return false; 534 if (trueBody is! InvokeContinuation) return false;
539 Continuation falseCont = branch.falseContinuation; 535 Continuation falseCont = branch.falseContinuation;
540 Expression falseBody = _unfoldDeadRefinements(falseCont.body); 536 Expression falseBody = _unfoldDeadRefinements(falseCont.body);
541 if (falseBody is! InvokeContinuation) return false; 537 if (falseBody is! InvokeContinuation) return false;
542 InvokeContinuation trueInvoke = trueBody; 538 InvokeContinuation trueInvoke = trueBody;
543 InvokeContinuation falseInvoke = falseBody; 539 InvokeContinuation falseInvoke = falseBody;
544 if (trueInvoke.continuation != 540 if (trueInvoke.continuation != falseInvoke.continuation) {
545 falseInvoke.continuation) {
546 return false; 541 return false;
547 } 542 }
548 // Matching zero arguments should be adequate, since isomorphic true and false 543 // Matching zero arguments should be adequate, since isomorphic true and false
549 // invocations should result in redundant phis which are removed elsewhere. 544 // invocations should result in redundant phis which are removed elsewhere.
550 // 545 //
551 // Note that the argument lists are not necessarily the same length here, 546 // Note that the argument lists are not necessarily the same length here,
552 // because we could be looking for new redexes in the middle of performing a 547 // because we could be looking for new redexes in the middle of performing a
553 // dead parameter reduction, where some but not all of the invocations have 548 // dead parameter reduction, where some but not all of the invocations have
554 // been rewritten. In that case, we will find the redex (once) after both 549 // been rewritten. In that case, we will find the redex (once) after both
555 // of these invocations have been rewritten. 550 // of these invocations have been rewritten.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 595
601 // Continuation beta- and eta-redexes can overlap, namely when an eta-redex 596 // Continuation beta- and eta-redexes can overlap, namely when an eta-redex
602 // is invoked exactly once. We prioritize continuation beta-redexes over 597 // is invoked exactly once. We prioritize continuation beta-redexes over
603 // eta-redexes because some reductions (e.g., dead parameter elimination) 598 // eta-redexes because some reductions (e.g., dead parameter elimination)
604 // can destroy a continuation eta-redex. If we prioritized eta- over 599 // can destroy a continuation eta-redex. If we prioritized eta- over
605 // beta-redexes, this would implicitly "create" the corresponding beta-redex 600 // beta-redexes, this would implicitly "create" the corresponding beta-redex
606 // (in the sense that it would still apply) and the algorithm would not 601 // (in the sense that it would still apply) and the algorithm would not
607 // detect it. 602 // detect it.
608 if (_isDeadCont(node)) { 603 if (_isDeadCont(node)) {
609 worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, node)); 604 worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, node));
610 } else if (_isBetaContLin(node)){ 605 } else if (_isBetaContLin(node)) {
611 worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, node)); 606 worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, node));
612 } else if (_isEtaCont(node)) { 607 } else if (_isEtaCont(node)) {
613 worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, node)); 608 worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, node));
614 } 609 }
615 } 610 }
616 611
617 void processParameter(Parameter node) { 612 void processParameter(Parameter node) {
618 if (_isDeadParameter(node)) { 613 if (_isDeadParameter(node)) {
619 worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, node)); 614 worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, node));
620 } 615 }
(...skipping 27 matching lines...) Expand all
648 reference.unlink(); 643 reference.unlink();
649 644
650 if (reference.definition is Primitive) { 645 if (reference.definition is Primitive) {
651 Primitive primitive = reference.definition.unrefined; 646 Primitive primitive = reference.definition.unrefined;
652 Node parent = primitive.parent; 647 Node parent = primitive.parent;
653 // The parent might be the deleted sentinel, or it might be a 648 // The parent might be the deleted sentinel, or it might be a
654 // Continuation or FunctionDefinition if the primitive is an argument. 649 // Continuation or FunctionDefinition if the primitive is an argument.
655 if (parent is LetPrim && _isDeadVal(parent)) { 650 if (parent is LetPrim && _isDeadVal(parent)) {
656 worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent)); 651 worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent));
657 } else if (primitive is Parameter && _isDeadParameter(primitive)) { 652 } else if (primitive is Parameter && _isDeadParameter(primitive)) {
658 worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, 653 worklist
659 primitive)); 654 .add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER, primitive));
660 } 655 }
661 } else if (reference.definition is Continuation) { 656 } else if (reference.definition is Continuation) {
662 Continuation cont = reference.definition; 657 Continuation cont = reference.definition;
663 Node parent = cont.parent; 658 Node parent = cont.parent;
664 // The parent might be the deleted sentinel, or it might be a 659 // The parent might be the deleted sentinel, or it might be a
665 // Body if the continuation is the return continuation. 660 // Body if the continuation is the return continuation.
666 if (parent is LetCont) { 661 if (parent is LetCont) {
667 if (cont.isRecursive && cont.hasAtMostOneUse) { 662 if (cont.isRecursive && cont.hasAtMostOneUse) {
668 // Convert recursive to nonrecursive continuations. If the 663 // Convert recursive to nonrecursive continuations. If the
669 // continuation is still in use, it is either dead and will be 664 // continuation is still in use, it is either dead and will be
(...skipping 26 matching lines...) Expand all
696 /// operator== since instantiations are used as Set elements. 691 /// operator== since instantiations are used as Set elements.
697 class _ReductionTask { 692 class _ReductionTask {
698 final _ReductionKind kind; 693 final _ReductionKind kind;
699 final Node node; 694 final Node node;
700 695
701 int get hashCode { 696 int get hashCode {
702 return (node.hashCode << 3) | kind.index; 697 return (node.hashCode << 3) | kind.index;
703 } 698 }
704 699
705 _ReductionTask(this.kind, this.node) { 700 _ReductionTask(this.kind, this.node) {
706 assert(node is Continuation || node is LetPrim || node is Parameter || 701 assert(node is Continuation ||
707 node is Branch); 702 node is LetPrim ||
703 node is Parameter ||
704 node is Branch);
708 } 705 }
709 706
710 bool operator==(_ReductionTask that) { 707 bool operator ==(_ReductionTask that) {
711 return (that.kind == this.kind && that.node == this.node); 708 return (that.kind == this.kind && that.node == this.node);
712 } 709 }
713 710
714 String toString() => "$kind: $node"; 711 String toString() => "$kind: $node";
715 } 712 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/scalar_replacement.dart ('k') | pkg/compiler/lib/src/cps_ir/type_mask_system.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698