Skip to content
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

improve dead/redundant store elimination #38454

Closed
4 tasks done
mraleph opened this issue Sep 18, 2019 · 9 comments
Closed
4 tasks done

improve dead/redundant store elimination #38454

mraleph opened this issue Sep 18, 2019 · 9 comments
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. type-performance Issue relates to performance or code size vm-aot-code-size Related to improvements in AOT code size

Comments

@mraleph
Copy link
Member

mraleph commented Sep 18, 2019

At some point we were considering to allocate objects uninitialized - however this is not the case at the moment so any store of null into newly allocated object is in fact dead. This issues consists of two several items:

  • Initializing stores of null can simply be dropped (e.g. in the canonicalization pass)
  • LoadOptimizer can be taught to remove redundant stores (e.g. storing value into a field which already has this value is redundant). This would remove non-initializing stores of null into newly allocated objects.
  • StoreOptimizer::CanEliminateStore should be revisited because it currently does not eliminate initializing stores - which seems wrong.
  • Context objects can be allocated uninitialized as a performance optimization (all initializing stores are inlined into he caller, which allocates the context). Investigate if this can be changed to align with normal Dart objects for code size reasons. AOT does not lower context allocation - only JIT does.

/cc @mkustermann

@mraleph mraleph added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. type-performance Issue relates to performance or code size labels Sep 18, 2019
@mraleph
Copy link
Member Author

mraleph commented Sep 18, 2019

/cc @mkustermann

@mraleph mraleph added the vm-aot-code-size Related to improvements in AOT code size label Sep 20, 2019
dart-bot pushed a commit that referenced this issue Sep 20, 2019
Dart objects are allocated null-initialized so initializing stores of
null value can be removed from the graph.

Issue #38454

Change-Id: I1ba0c3a21462ba8a3409fc648027b4ebf0b1040e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118286
Reviewed-by: Samir Jindel <sjindel@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
dart-bot pushed a commit that referenced this issue Sep 20, 2019
This reverts commit 96b8401.

Reason for revert: works incorrectly because kernel-to-il emits multiple initializing stores for the same field. see language_2/field_parameter
_test

Original change's description:
> [vm/compiler] Drop redundant initializing stores of null
> 
> Dart objects are allocated null-initialized so initializing stores of
> null value can be removed from the graph.
> 
> Issue #38454
> 
> Change-Id: I1ba0c3a21462ba8a3409fc648027b4ebf0b1040e
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118286
> Reviewed-by: Samir Jindel <sjindel@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Vyacheslav Egorov <vegorov@google.com>

TBR=vegorov@google.com,kustermann@google.com,sjindel@google.com

Change-Id: Ic0c51986168cb51316d3872514719b34cfc780cb
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118289
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
dart-bot pushed a commit that referenced this issue Oct 11, 2019
Dart objects are allocated null-initialized so initializing stores of
null value can be removed from the graph.

Issue #38454

Change-Id: I692398b67a5f9d27ebc6e6c90c68838c1135de4a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121330
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
@mraleph
Copy link
Member Author

mraleph commented Oct 14, 2019

Simple removal of redundant initialising stores have landed and has the following effect

Benchmark Change Metric Target Hardware Arch
flutter_gallery_instructions_size -1.05 % CodeSize flutter-profile Moto G4 android-armv7
flutter_gallery_instructions_size -1.29 % CodeSize flutter-release Moto G4 android-armv7
flutter_gallery_instructions_size -1.23 % CodeSize flutter-release Pixel 2 android-armv8

@aartbik
Copy link
Contributor

aartbik commented Oct 15, 2019

Given the guaranteed clearing semantics of allocation, I am looking into D/R(S/L)E improvements that will eliminate both a = null statements from code like this (currently we only remove one, solely based on kill sets). There may be some other low hanging fruits.

class Bar {
  Bar() { a = null; }
  Object a;
}

@pragma("vm:never-inline")
Bar foo() {
  Bar bar = new Bar();
  bar.a = null;
  return bar;
}

@mraleph
Copy link
Member Author

mraleph commented Oct 15, 2019

I am looking into DSE improvements

I have been actually pondering on this topic a bit - which made me wonder if our DSE should be merged in the LoadOptimizer which can be made to compute all the necessary information that DSE needs. Additionally LoadOptimizer already computes information about the state of the object fields (for load forwarding) and this is exactly the information that you need to discover redundant stores (i.e. store that stores a value which is already in the field). So it seems natural that this should be handled in the same pass.

Given the guaranteed clearing semantics of allocation

I wonder if item nr 4 on the list (null-initialized context allocations - and potentially uninlining context cloning) might yield better size savings then more sophisticated DSE. (at least it looks easier to crunch some numbers on this).

@aartbik
Copy link
Contributor

aartbik commented Oct 15, 2019

@mraleph I have implemented the redundant store removal in the LoadOptimizer, and agree that DSE is almost a special case of this optimization now. We can do that refactoring as a follow-up.

@aartbik
Copy link
Contributor

aartbik commented Oct 15, 2019

Redundant store elimination yields very modest saving of 13K bytes.

+---------------------------+---------------------------+--------------+
| Library                   | Method                    | Diff (Bytes) |
+---------------------------+---------------------------+--------------+
| dart:collection           | MapMixin.entries          |          -64 |
| package:flutter/src/wid.. | _AnimatedPhysicalModelS.. |          -64 |
| package:flutter_gallery.. | FullScreenDialogDemoSta.. |          -64 |
| package:flutter_gallery.. | ContactsDemoState.build   |          -80 |
| package:flutter_gallery.. | _ChipDemoState.build.<a.. |          -80 |
| package:flutter_gallery.. | _DataTableDemoState.build |          -80 |
| package:flutter_gallery.. | _ExpansionPanelsDemoSta.. |          -96 |
| package:flutter/src/wid.. | GestureDetector.build     |         -112 |
| package:flutter/src/wid.. | _AnimatedContainerState.. |         -112 |
| package:flutter_gallery.. | _DataTableDemoState.bui.. |         -128 |
+---------------------------+---------------------------+--------------+
Comparing ./old.json (old) to ./sizes.json (new)
Old   : 6964496 bytes.
New   : 6950816 bytes.
Change: -13680 bytes.

Some more data.

When naively doing point (3) above (which actually seems required for backward flowing DSE since we want to keep the first; I did not need it for the forward flowing CSE), this only saves an additional 16 bytes compared to the optimized version above.

Removing the two bail-outs in load/store optimizer (which seemed to have been put in place to avoid OOM for some unspecified situations) has no impact, as these cases are not encountered for the gallery.

dart-bot pushed a commit that referenced this issue Oct 16, 2019
We inline allocation of contexts and closures manually so stores
which are effectively initializing were not marked as such.

Additionally permit elimination of initializing stores into context
objects in AOT mode because all contexts are null-initialized there.

Bug: #38454
Change-Id: I27886d85160b8600e6e0d38d7bf389d20006fa44
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121849
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
dart-bot pushed a commit that referenced this issue Oct 16, 2019
Rationale:
Storing the same value into a field/array is now
detected and the redundant store is removed. Note
that this is closely related, but not exactly the
same as dead store elimination.

gallery savings: 13.7K bytes

#38454

Change-Id: I57100ef67a8e0132436933226ceecba95825458e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121823
Commit-Queue: Aart Bik <ajcbik@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
@aartbik
Copy link
Contributor

aartbik commented Oct 16, 2019

All four points have been addressed.

@aartbik aartbik closed this as completed Oct 16, 2019
dart-bot pushed a commit that referenced this issue Oct 16, 2019
This reverts commit eb87e79.

Reason for revert: Multiple configurations are red

IRTest_InitializingStores:

https://ci.chromium.org/p/dart/builders/ci.sandbox/vm-dartkb-linux-debug-simarm64/1684
https://ci.chromium.org/p/dart/builders/ci.sandbox/vm-dartkb-linux-product-simarm64/1796

http_server_test:
https://ci.chromium.org/p/dart/builders/ci.sandbox/vm-kernel-precomp-linux-release-simarm/6796


Original change's description:
> [vm/compiler] Mark more stores as initializing.
> 
> We inline allocation of contexts and closures manually so stores
> which are effectively initializing were not marked as such.
> 
> Additionally permit elimination of initializing stores into context
> objects in AOT mode because all contexts are null-initialized there.
> 
> Bug: #38454
> Change-Id: I27886d85160b8600e6e0d38d7bf389d20006fa44
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121849
> Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>

TBR=vegorov@google.com,kustermann@google.com

Change-Id: I4c2df7b675fa3cdab22a8708440dc45ff3ec3476
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: #38454
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121885
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
@yaymalaga
Copy link

Should this issue be opened again due to c4a7f1c?

@mraleph
Copy link
Member Author

mraleph commented Oct 18, 2019

We have relanded the reverted change in: https://dart-review.googlesource.com/c/sdk/+/121982

I forgot to connect it to this issue though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. type-performance Issue relates to performance or code size vm-aot-code-size Related to improvements in AOT code size
Projects
None yet
Development

No branches or pull requests

3 participants