-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dart2JS pattern code less efficient than manual check. #54115
Comments
dart2js has a structural problem that prevents it from generating nice code for examples like this. The root cause is that dart2js was originally envisioned to be a more JIT-like compiler, so the CFG and translation from optimized CFG to JavaScript made a compromise that the CFG structure is immutable, and JavaScript generation was guided by the original Dart program structure. We have limped along with this for a long time. dart2js never generated nice code for complex conditionals (the condition becoming reified), and with more elaborate lowerings coming out of the CFE, this is no longer appropriate. Fixing this in dart2js will be a significant effort since it will require rewrites of the code generator and pieces of the optimizer. Being able to reshape the CFG is a necessary to doing better, but, as the similar issue you opened on the VM shows, it is not sufficient. The VM optimizer has excellent CFG reshaping capabilities. If the CFE could generate better lowerings (there has been progress), that would help a lot with naive compilers like DDC. This is the lowered Kernel IR:
/cc @johnniwinther @alexmarkov @nshahan I don't think we should all try to solve this in our little silos. Perhaps we should meet somehow to figure out what we would need to allow the most straight-forward generation of better code. |
@rakudrama Do you have an alternative lowering in mind for this example that would help dart2js? |
@johnniwinther Sink binding as late as possible. If the binding occurs in one place, is not actually tested (as here) and not needed in more than one path, sink it into the 'then' part of the if-then-else. Best case would be something like
but this might be OK too:
A more general framing might be to push the irrefutable tail of a pattern into the 'then' part of the if-then-else. |
…attern In response to #54115 Closes #54114 Change-Id: I6d1d29c19173e703a467f43ec09a7de383b4a80b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/338881 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
With the fix c634738, the generated code for pattern$0() {
var _0_0 = this._x;
if (_0_0 != null)
A.print(_0_0);
else
A.print("null");
}, |
Rewrite `phi(true, false)` to the controlling condition. This patchset comparison shows the general effect: https://dart-review.googlesource.com/c/sdk/+/340065/2..3/pkg/compiler/test/codegen/data/phi_to_condition_test.dart This change is a partial remedy for http://dartbug.com/54115 Issue: #54115 Change-Id: Ibcc5d17f6c4c8ad9600840ec106f84edcd008e4a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/340065 Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Stephen Adams <sra@google.com>
Reopening due to revert: https://dart-review.googlesource.com/c/sdk/+/350006 |
This reverts commit 75b1973. Reason for revert: Breaks g3 tests Original change's description: > [dart2js] Replace phi with controlling condition > > Rewrite `phi(true, false)` to the controlling condition. > > This patchset comparison shows the general effect: https://dart-review.googlesource.com/c/sdk/+/340065/2..3/pkg/compiler/test/codegen/data/phi_to_condition_test.dart > > This change is a partial remedy for http://dartbug.com/54115 > > Issue: #54115 > Change-Id: Ibcc5d17f6c4c8ad9600840ec106f84edcd008e4a > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/340065 > Reviewed-by: Nate Biggs <natebiggs@google.com> > Commit-Queue: Stephen Adams <sra@google.com> Issue: #54115 Change-Id: Id717ef469b09a5b07e43b3ffafc54bc6b409f0df Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350006 Reviewed-by: Sigmund Cherem <sigmund@google.com> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Commit-Queue: Mayank Patke <fishythefish@google.com>
The issue causing the revert is addressed by https://dart-review.googlesource.com/c/sdk/+/352443 The branch condition in B4 is not controlling for the join at B12 |
This reverts commit aec3ec0. - Corrected 'controlling condition' detection. - Added test that is incorrectly compiled to infinite loop with incorrect controlling condition detection. See #54115 (comment) for an image of part of the CFG for `doWhileLoop` where the condition in B4 was previously mis-identified as controlling `phi(true,false)` at B12. Issue: #54115 Change-Id: I0d2c2ff83b202071f6d7050d34de8ff25d05cb22 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352443 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Stephen Adams <sra@google.com>
If I compile this with
dart compile js -O4 --no-minify
, the code for thepattern
method is less efficient than the other two:It looks like some desugaring of patterns ends up reifying the match result as a boolean value, and introducing a temporary variable for the non-matching branch too, in a way that the Dart2JS compiler doesn't manage to optimize afterwards. (It seems like code that should be easily optimizable, so is optimization omitted for "lowered" Dart code?)
I'd prefer to use the
case
version, but only if it's actually as efficient.The text was updated successfully, but these errors were encountered: