RFR: 8318446: C2: optimize stores into primitive arrays by combining values into larger store [v18]

Emanuel Peter epeter at openjdk.org
Wed Apr 3 08:36:26 UTC 2024


> This is a feature requiested by @RogerRiggs and @cl4es .
> 
> **Idea**
> 
> Merging multiple consecutive small stores (e.g. 8 byte stores) into larger stores (e.g. one long store) can lead to speedup. Recently, @cl4es and @RogerRiggs had to review a few PR's where people would try to get speedups by using Unsafe (e.g. `Unsafe.putLongUnaligned`), or ByteArrayLittleEndian (e.g. `ByteArrayLittleEndian.setLong`). They have asked if we can do such an optimization in C2, rather than in the Java library code, or even user code.
> 
> This patch here supports a few simple use-cases, like these:
> 
> Merge consecutive array stores, with constants. We can combine the separate constants into a larger constant:
> https://github.com/openjdk/jdk/blob/adca9e220822884d95d73c7f070adeee2632130d/test/hotspot/jtreg/compiler/c2/TestMergeStores.java#L383-L395
> 
> Merge consecutive array stores, with a variable that was split (using shifts). We can essentially undo the splitting (i.e. shifting and truncation), and directly store the variable:
> https://github.com/openjdk/jdk/blob/adca9e220822884d95d73c7f070adeee2632130d/test/hotspot/jtreg/compiler/c2/TestMergeStores.java#L444-L456
> 
> The idea is that this would allow the introduction of a very simple API, without any "heavy" dependencies (Unsafe or ByteArrayLittleEndian):
> 
> https://github.com/openjdk/jdk/blob/adca9e220822884d95d73c7f070adeee2632130d/test/hotspot/jtreg/compiler/c2/TestMergeStores.java#L327-L338
> https://github.com/openjdk/jdk/blob/adca9e220822884d95d73c7f070adeee2632130d/test/hotspot/jtreg/compiler/c2/TestMergeStores.java#L467-L472
> 
> **Details**
> 
> This draft currently implements the optimization in an additional special IGVN phase:
> https://github.com/openjdk/jdk/blob/adca9e220822884d95d73c7f070adeee2632130d/src/hotspot/share/opto/compile.cpp#L2479-L2485
> 
> We first collect all `StoreB|C|I`, and put them in the IGVN worklist (see `Compile::gather_nodes_for_merge_stores`). During IGVN, we call `StoreNode::Ideal_merge_stores` at the end (after all other optimizations) of `StoreNode::Ideal`. We essentially try to establish a chain of mergable stores:
> 
> https://github.com/openjdk/jdk/blob/adca9e220822884d95d73c7f070adeee2632130d/src/hotspot/share/opto/memnode.cpp#L2802-L2806
> 
> Mergable stores must have the same Opcode (implies they have the same element type and hence size). Further, mergable stores must have the same control (or be separated by only a RangeCheck). Further, they must either both store constants, or adjacent segments of a larger value ...

Emanuel Peter has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 48 commits:

 - Merge branch 'master' into JDK-8318446
 - a little bit of casting for debug printing code
 - Merge branch 'master' into JDK-8318446
 - fix test for trapping examples
 - WIP test with out of bounds exception
 - allow only array stores of same type as container
 - mismatched access test
 - add test300
 - make it happen in post_loop_opts
 - fix invalid case
 - ... and 38 more: https://git.openjdk.org/jdk/compare/e3e6c2a8...d97fa2b4

-------------

Changes: https://git.openjdk.org/jdk/pull/16245/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=16245&range=17
  Stats: 2391 lines in 13 files changed: 2387 ins; 0 del; 4 mod
  Patch: https://git.openjdk.org/jdk/pull/16245.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/16245/head:pull/16245

PR: https://git.openjdk.org/jdk/pull/16245


More information about the hotspot-compiler-dev mailing list