| OLD | NEW |
| 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 /** | 5 /** |
| 6 * Instead of emitting each SSA instruction with a temporary variable | 6 * Instead of emitting each SSA instruction with a temporary variable |
| 7 * mark instructions that can be emitted at their use-site. | 7 * mark instructions that can be emitted at their use-site. |
| 8 * For example, in: | 8 * For example, in: |
| 9 * t0 = 4; | 9 * t0 = 4; |
| 10 * t1 = 3; | 10 * t1 = 3; |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 }; | 344 }; |
| 345 } | 345 } |
| 346 | 346 |
| 347 class JSBinaryOperatorPrecedence { | 347 class JSBinaryOperatorPrecedence { |
| 348 final int left; | 348 final int left; |
| 349 final int right; | 349 final int right; |
| 350 const JSBinaryOperatorPrecedence(this.left, this.right); | 350 const JSBinaryOperatorPrecedence(this.left, this.right); |
| 351 // All binary operators (excluding assignment) are left associative. | 351 // All binary operators (excluding assignment) are left associative. |
| 352 int get precedence() => left; | 352 int get precedence() => left; |
| 353 } | 353 } |
| 354 |
| 355 class PhiEquivalator { |
| 356 final Equivalence<HPhi> equivalence; |
| 357 final Map<HPhi, String> logicalOperations; |
| 358 PhiEquivalator(this.equivalence, this.logicalOperations); |
| 359 |
| 360 void analyzeGraph(HGraph graph) { |
| 361 graph.blocks.forEach((HBasicBlock block) => analyzeBlock(block)); |
| 362 } |
| 363 |
| 364 void analyzeBlock(HBasicBlock block) { |
| 365 for (HPhi phi = block.phis.first; phi !== null; phi = phi.next) { |
| 366 if (!logicalOperations.containsKey(phi) && |
| 367 phi.usedBy.length == 1 && |
| 368 phi.usedBy[0] is HPhi) { |
| 369 equivalence.makeEquivalent(phi, phi.usedBy[0]); |
| 370 } |
| 371 } |
| 372 } |
| 373 } |
| 374 |
| 375 |
| 376 /** |
| 377 * Try to figure out which phis can be represented by the same temporary |
| 378 * variable, to avoid creating a new variable for each phi. |
| 379 */ |
| 380 class Equivalence<T extends Hashable> { |
| 381 // Represent equivalence classes of HPhi nodes as a forest of trees, |
| 382 // where each tree is one equivalence class, and the root is the |
| 383 // canonical representative for the equivalence class. |
| 384 // Implement the forest by having each phi point to its parent in the tree, |
| 385 // transitively linking it to the root, which itself doesn't have a parent. |
| 386 final Map<T,T> representative; |
| 387 |
| 388 Equivalence() : representative = new Map<T,T>(); |
| 389 |
| 390 T makeEquivalent(T a, T b) { |
| 391 T root1 = getRepresentative(a); |
| 392 T root2 = getRepresentative(b); |
| 393 if (root1 !== root2) { |
| 394 // Merge the trees for the two classes into one. |
| 395 representative[root1] = root2; |
| 396 } |
| 397 } |
| 398 |
| 399 /** |
| 400 * Get the canonical representative for an equivalence class of phis. |
| 401 */ |
| 402 T getRepresentative(T element) { |
| 403 T parent = representative[element]; |
| 404 if (parent === null) { |
| 405 // This is the root of a tree (a previously unseen node is considered |
| 406 // the root of its own tree). |
| 407 return element; |
| 408 } |
| 409 // Shorten the path for all the elements on the way to the root, |
| 410 // improving the performance of future lookups. |
| 411 T root = getRepresentative(parent); |
| 412 if (root !== parent) representative[element] = root; |
| 413 return root; |
| 414 } |
| 415 |
| 416 bool areEquivalent(T a, T b) { |
| 417 return getRepresentative(a) === getRepresentative(b); |
| 418 } |
| 419 } |
| OLD | NEW |