RFR: 8318446: C2: implement StoreNode::Ideal_merge_stores

Vladimir Kozlov kvn at openjdk.org
Tue Jan 16 23:10:52 UTC 2024


On Wed, 18 Oct 2023 13:04:35 GMT, Emanuel Peter <epeter at openjdk.org> wrote:

> 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 ...

About changes. May be you can use something similar to ClearArrayNode. Collect all stores into one node and corresponding Mach (machine) nodes will implement it using available instructions instead of C2 decide the size of combined store.

One drawback for these changes I see that you may use a lot more registers to keep all values.

For constants you need to keep in mind the order of memory (little or big endian).

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

PR Comment: https://git.openjdk.org/jdk/pull/16245#issuecomment-1894665744


More information about the hotspot-compiler-dev mailing list