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

Unified Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart

Issue 196223017: Fix bad generate-at-use-site. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/builder.dart ('k') | tests/language/pure_function2_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
index 1e83906f09e213186317df5c505165962b732c96..5dbea83b8ce334d68438bedf42aef21254d42772 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
@@ -285,16 +285,66 @@ class SsaInstructionMerger extends HBaseVisitor {
markAsGenerateAtUseSite(instruction);
continue;
}
- if (instruction.isJsStatement()) {
- expectedInputs.clear();
- }
if (instruction.isPure()) {
if (pureInputs.contains(instruction)) {
tryGenerateAtUseSite(instruction);
} else {
// If the input is not in the [pureInputs] set, it has not
- // been visited.
+ // been visited or should not be generated at use-site. The most
+ // likely reason for the latter, is that the instruction is used
+ // in more than one location.
+ // We must either clear the expectedInputs, or move the pure
+ // instruction's inputs in front of the existing ones.
+ // Example:
+ // t1 = foo(); // side-effect.
+ // t2 = bar(); // side-effect.
+ // t3 = pure(t2); // used more than once.
+ // f(t1, t3); // expected inputs of 'f': t1.
+ // use(t3);
+ //
+ // If we don't clear the expected inputs we end up in a situation
+ // where pure pushes "t2" on top of "t1" leading to:
+ // t3 = pure(bar());
+ // f(foo(), t3);
+ // use(t3);
+ //
+ // If we clear the expected-inputs list we have the correct
+ // output:
+ // t1 = foo();
+ // t3 = pure(bar());
+ // f(t1, t3);
+ // use(t3);
+ //
+ // Clearing is, however, not optimal.
+ // Example:
+ // t1 = foo(); // t1 is now used by `pure`.
+ // t2 = bar(); // t2 is now used by `f`.
+ // t3 = pure(t1);
+ // f(t2, t3);
+ // use(t3);
+ //
+ // If we clear the expected-inputs we can't generate-at-use any of
+ // the instructions.
+ //
+ // The optimal solution is to move the inputs of 'pure' in
+ // front of the expectedInputs list. This makes sense, since we
+ // push expected-inputs from left-to right, and the `pure` function
+ // invocation is "more left" (i.e. before) the first argument of `f`.
+ // With that approach we end up with:
+ // t3 = pure(foo();
+ // f(bar(), t3);
+ // use(t3);
+ //
+ int oldLength = expectedInputs.length;
instruction.accept(this);
+ if (oldLength != 0 && oldLength != expectedInputs.length) {
+ // Move the pure instruction's inputs to the front.
+ List<HInstruction> newInputs = expectedInputs.sublist(oldLength);
+ int newCount = newInputs.length;
+ expectedInputs.setRange(
+ newCount, newCount + oldLength, expectedInputs);
+ expectedInputs.setRange(0, newCount, newInputs);
+ }
}
} else {
if (findInInputsAndPopNonMatching(instruction)) {
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/builder.dart ('k') | tests/language/pure_function2_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698