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

Side by Side Diff: pkg/compiler/lib/src/tree_ir/optimization/variable_merger.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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 tree_ir.optimization.variable_merger; 5 library tree_ir.optimization.variable_merger;
6 6
7 import 'optimization.dart' show Pass; 7 import 'optimization.dart' show Pass;
8 import '../tree_ir_nodes.dart'; 8 import '../tree_ir_nodes.dart';
9 9
10 /// Merges variables based on liveness and source variable information. 10 /// Merges variables based on liveness and source variable information.
11 /// 11 ///
12 /// This phase cleans up artifacts introduced by the translation through CPS, 12 /// This phase cleans up artifacts introduced by the translation through CPS,
13 /// where each source variable is translated into several copies. The copies 13 /// where each source variable is translated into several copies. The copies
14 /// are merged again when they are not live simultaneously. 14 /// are merged again when they are not live simultaneously.
15 class VariableMerger implements Pass { 15 class VariableMerger implements Pass {
16 String get passName => 'Variable merger'; 16 String get passName => 'Variable merger';
17 17
18 final bool minifying; 18 final bool minifying;
19 19
20 VariableMerger({this.minifying: false}); 20 VariableMerger({this.minifying: false});
21 21
22 void rewrite(FunctionDefinition node) { 22 void rewrite(FunctionDefinition node) {
23 BlockGraphBuilder builder = new BlockGraphBuilder()..build(node); 23 BlockGraphBuilder builder = new BlockGraphBuilder()..build(node);
24 _computeLiveness(builder.blocks); 24 _computeLiveness(builder.blocks);
25 PriorityPairs priority = new PriorityPairs()..build(node); 25 PriorityPairs priority = new PriorityPairs()..build(node);
26 Map<Variable, Variable> subst = _computeRegisterAllocation( 26 Map<Variable, Variable> subst = _computeRegisterAllocation(
27 builder.blocks, node.parameters, priority, minifying: minifying); 27 builder.blocks, node.parameters, priority,
28 minifying: minifying);
28 new SubstituteVariables(subst).apply(node); 29 new SubstituteVariables(subst).apply(node);
29 } 30 }
30 } 31 }
31 32
32 /// A read or write access to a variable. 33 /// A read or write access to a variable.
33 class VariableAccess { 34 class VariableAccess {
34 Variable variable; 35 Variable variable;
35 bool isRead; 36 bool isRead;
36 bool get isWrite => !isRead; 37 bool get isWrite => !isRead;
37 38
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 _priority.putIfAbsent(x, () => new List<Variable>()).add(y); 270 _priority.putIfAbsent(x, () => new List<Variable>()).add(y);
270 _priority.putIfAbsent(y, () => new List<Variable>()).add(x); 271 _priority.putIfAbsent(y, () => new List<Variable>()).add(x);
271 } 272 }
272 273
273 visitAssign(Assign node) { 274 visitAssign(Assign node) {
274 super.visitAssign(node); 275 super.visitAssign(node);
275 Expression value = node.value; 276 Expression value = node.value;
276 if (value is VariableUse) { 277 if (value is VariableUse) {
277 _prioritize(node.variable, value.variable); 278 _prioritize(node.variable, value.variable);
278 } else if (value is ApplyBuiltinOperator && 279 } else if (value is ApplyBuiltinOperator &&
279 isCompoundableOperator(value.operator) && 280 isCompoundableOperator(value.operator) &&
280 value.arguments[0] is VariableUse) { 281 value.arguments[0] is VariableUse) {
281 VariableUse use = value.arguments[0]; 282 VariableUse use = value.arguments[0];
282 _prioritize(node.variable, use.variable); 283 _prioritize(node.variable, use.variable);
283 } 284 }
284 } 285 }
285 286
286 /// Returns the other half of every priority pair containing [variable]. 287 /// Returns the other half of every priority pair containing [variable].
287 List<Variable> getPriorityPairsWith(Variable variable) { 288 List<Variable> getPriorityPairsWith(Variable variable) {
288 return _priority[variable] ?? const <Variable>[]; 289 return _priority[variable] ?? const <Variable>[];
289 } 290 }
290 291
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 379
379 /// Based on liveness information, computes a map of variable substitutions to 380 /// Based on liveness information, computes a map of variable substitutions to
380 /// merge variables. 381 /// merge variables.
381 /// 382 ///
382 /// Constructs a register interference graph. This is an undirected graph of 383 /// Constructs a register interference graph. This is an undirected graph of
383 /// variables, with an edge between two variables if they cannot be merged 384 /// variables, with an edge between two variables if they cannot be merged
384 /// (because they are live simultaneously). 385 /// (because they are live simultaneously).
385 /// 386 ///
386 /// We then compute a graph coloring, where the color of a node denotes which 387 /// We then compute a graph coloring, where the color of a node denotes which
387 /// variable it will be substituted by. 388 /// variable it will be substituted by.
388 Map<Variable, Variable> _computeRegisterAllocation(List<Block> blocks, 389 Map<Variable, Variable> _computeRegisterAllocation(
389 List<Variable> parameters, 390 List<Block> blocks, List<Variable> parameters, PriorityPairs priority,
390 PriorityPairs priority, 391 {bool minifying}) {
391 {bool minifying}) {
392 Map<Variable, Set<Variable>> interference = <Variable, Set<Variable>>{}; 392 Map<Variable, Set<Variable>> interference = <Variable, Set<Variable>>{};
393 393
394 bool allowUnmotivatedMerge(Variable x, Variable y) { 394 bool allowUnmotivatedMerge(Variable x, Variable y) {
395 if (minifying) return true; 395 if (minifying) return true;
396 // Do not allow merging temporaries with named variables if they are 396 // Do not allow merging temporaries with named variables if they are
397 // not connected by a phi. That would leads to confusing mergings like: 397 // not connected by a phi. That would leads to confusing mergings like:
398 // var v0 = receiver.length; 398 // var v0 = receiver.length;
399 // ==> 399 // ==>
400 // receiver = receiver.length; 400 // receiver = receiver.length;
401 return x.element?.name == y.element?.name; 401 return x.element?.name == y.element?.name;
402 } 402 }
403 403
404 bool allowPhiMerge(Variable x, Variable y) { 404 bool allowPhiMerge(Variable x, Variable y) {
405 if (minifying) return true; 405 if (minifying) return true;
406 // Temporaries may be merged with a named variable if this eliminates a phi. 406 // Temporaries may be merged with a named variable if this eliminates a phi.
407 // The presence of the phi implies that the two variables can contain the 407 // The presence of the phi implies that the two variables can contain the
408 // same value, so it is not that confusing that they get the same name. 408 // same value, so it is not that confusing that they get the same name.
409 return x.element == null || 409 return x.element == null ||
410 y.element == null || 410 y.element == null ||
411 x.element.name == y.element.name; 411 x.element.name == y.element.name;
412 } 412 }
413 413
414 Set<Variable> empty = new Set<Variable>(); 414 Set<Variable> empty = new Set<Variable>();
415 415
416 // At the assignment to a variable x, add an edge to every variable that is 416 // At the assignment to a variable x, add an edge to every variable that is
417 // live after the assignment (if it came from the same source variable). 417 // live after the assignment (if it came from the same source variable).
418 for (Block block in blocks) { 418 for (Block block in blocks) {
419 // Track the live set while traversing the block. 419 // Track the live set while traversing the block.
420 Set<Variable> live = new Set<Variable>(); 420 Set<Variable> live = new Set<Variable>();
421 for (Variable variable in block.liveOut) { 421 for (Variable variable in block.liveOut) {
422 live.add(variable); 422 live.add(variable);
423 interference.putIfAbsent(variable, () => new Set<Variable>()); 423 interference.putIfAbsent(variable, () => new Set<Variable>());
424 } 424 }
425 // Get variables that are live at the catch block. 425 // Get variables that are live at the catch block.
426 Set<Variable> liveCatch = block.catchBlock != null 426 Set<Variable> liveCatch =
427 ? block.catchBlock.liveIn 427 block.catchBlock != null ? block.catchBlock.liveIn : empty;
428 : empty;
429 // Add edges for each variable being assigned here. 428 // Add edges for each variable being assigned here.
430 for (VariableAccess access in block.accesses.reversed) { 429 for (VariableAccess access in block.accesses.reversed) {
431 Variable variable = access.variable; 430 Variable variable = access.variable;
432 interference.putIfAbsent(variable, () => new Set<Variable>()); 431 interference.putIfAbsent(variable, () => new Set<Variable>());
433 if (access.isRead) { 432 if (access.isRead) {
434 live.add(variable); 433 live.add(variable);
435 } else { 434 } else {
436 if (!liveCatch.contains(variable)) { 435 if (!liveCatch.contains(variable)) {
437 // Assignment to a variable that is not live in the catch block. 436 // Assignment to a variable that is not live in the catch block.
438 live.remove(variable); 437 live.remove(variable);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 if (parameter.isCaptured) continue; 501 if (parameter.isCaptured) continue;
503 registers.add(parameter); 502 registers.add(parameter);
504 subst[parameter] = parameter; 503 subst[parameter] = parameter;
505 } 504 }
506 505
507 // Try to merge parameters with locals to eliminate phis. 506 // Try to merge parameters with locals to eliminate phis.
508 for (Variable parameter in parameters) { 507 for (Variable parameter in parameters) {
509 searchPriorityPairs(parameter, parameter); 508 searchPriorityPairs(parameter, parameter);
510 } 509 }
511 510
512 v1loop: 511 v1loop: for (Variable v1 in variables) {
513 for (Variable v1 in variables) {
514 // Ignore if the variable has already been assigned a register. 512 // Ignore if the variable has already been assigned a register.
515 if (subst.containsKey(v1)) continue; 513 if (subst.containsKey(v1)) continue;
516 514
517 // Optimization: If there are no interference edges for this variable, 515 // Optimization: If there are no interference edges for this variable,
518 // find a color for it without copying the register list. 516 // find a color for it without copying the register list.
519 Set<Variable> interferenceSet = interference[v1]; 517 Set<Variable> interferenceSet = interference[v1];
520 if (interferenceSet.isEmpty) { 518 if (interferenceSet.isEmpty) {
521 // Use the first register where naming constraints allow the merge. 519 // Use the first register where naming constraints allow the merge.
522 for (Variable v2 in registers) { 520 for (Variable v2 in registers) {
523 if (allowUnmotivatedMerge(v1, v2)) { 521 if (allowUnmotivatedMerge(v1, v2)) {
524 assignRegister(v1, v2); 522 assignRegister(v1, v2);
525 continue v1loop; 523 continue v1loop;
526 } 524 }
527 } 525 }
528 // No register allows merging with this one, create a new register. 526 // No register allows merging with this one, create a new register.
529 assignNewRegister(v1); 527 assignNewRegister(v1);
530 continue; 528 continue;
531 } 529 }
532 530
533 // Find an unused color. 531 // Find an unused color.
534 Set<Variable> potential = new Set<Variable>.from( 532 Set<Variable> potential = new Set<Variable>.from(
535 registers.where((v2) => allowUnmotivatedMerge(v1, v2))); 533 registers.where((v2) => allowUnmotivatedMerge(v1, v2)));
536 for (Variable v2 in interferenceSet) { 534 for (Variable v2 in interferenceSet) {
537 Variable v2subst = subst[v2]; 535 Variable v2subst = subst[v2];
538 if (v2subst != null) { 536 if (v2subst != null) {
539 potential.remove(v2subst); 537 potential.remove(v2subst);
540 if (potential.isEmpty) break; 538 if (potential.isEmpty) break;
541 } 539 }
542 } 540 }
543 541
544 if (potential.isEmpty) { 542 if (potential.isEmpty) {
545 // If no free color was found, add this variable as a new color. 543 // If no free color was found, add this variable as a new color.
546 assignNewRegister(v1); 544 assignNewRegister(v1);
547 } else { 545 } else {
548 assignRegister(v1, potential.first); 546 assignRegister(v1, potential.first);
549 } 547 }
550 } 548 }
551 549
552 return subst; 550 return subst;
553 } 551 }
554 552
555 /// Performs variable substitution and removes redundant assignments. 553 /// Performs variable substitution and removes redundant assignments.
556 class SubstituteVariables extends RecursiveTransformer { 554 class SubstituteVariables extends RecursiveTransformer {
557
558 Map<Variable, Variable> mapping; 555 Map<Variable, Variable> mapping;
559 556
560 SubstituteVariables(this.mapping); 557 SubstituteVariables(this.mapping);
561 558
562 Variable replaceRead(Variable variable) { 559 Variable replaceRead(Variable variable) {
563 Variable w = mapping[variable]; 560 Variable w = mapping[variable];
564 if (w == null) return variable; // Skip ignored variables. 561 if (w == null) return variable; // Skip ignored variables.
565 w.readCount++; 562 w.readCount++;
566 variable.readCount--; 563 variable.readCount--;
567 return w; 564 return w;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 node.expression = visitExpression(node.expression); 604 node.expression = visitExpression(node.expression);
608 node.next = visitStatement(node.next); 605 node.next = visitStatement(node.next);
609 if (node.expression is VariableUse) { 606 if (node.expression is VariableUse) {
610 VariableUse use = node.expression; 607 VariableUse use = node.expression;
611 --use.variable.readCount; 608 --use.variable.readCount;
612 return node.next; 609 return node.next;
613 } 610 }
614 return node; 611 return node;
615 } 612 }
616 } 613 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698