> NEON non-strictly ordered floating-point reduction instruction rules are 
> updated to avoid materialising a redundant `fadd`, and additionally now use 
> an immediate operand instead of a register.
> 
> Vector API and auto-vectorisation share the AddReductionV node which has to 
> support the needs of both - it models a scalar value plus a vector operand.  
> Since `reduceLanes()` has no scalar source the Vector API intrinsic generates 
> an identity scalar value which is passed as the first input to 
> AddReductionVF/VD.  Because addition with the identity value is unnecessary 
> when implementing a Vector API reduction, NEON non-strict floating-point 
> reductions no longer generate an extra instruction.  Furthermore, the matcher 
> has been updated to use zero-constrained immediate operands to guarantee that 
> the scalar value is zero.
> 
> Update the predicate of `reduce_non_strict_order_add2D_neon` to restrict it 
> to 128-bit vectors, ensuring vectors wider than 128 bits select 
> `reduce_addD_sve` for correct code generation on all SVE-capable systems.
> 
> Before:
> 
> faddp   v26.4s, v18.4s, v18.4s
> faddp   s19, v26.2s
> fadd    s19, s19, s17 // accum(s19) += s17(value 0.0)
> 
> 
> After:
> 
> faddp   v26.4s, v18.4s, v18.4s
> faddp   s19, v26.2s
> 
> 
> Throughput benchmarks are split into 2 different types, based on the 
> reduction benchmarks in
> `test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java`
> 
> 1. A naive version which performs lane reductions inside the loop, e.g. 
> `vectorDoubleAddReduce_naive`
> 2. 'reduction_after_loop' version which performs element-wise addition inside 
> the loop, followed by a single `reduceLanes` after the loop, e.g.  
> `vectorDoubleAddReduce_reduction_after_loop`
> 
> Benchmarking has been conducted on Arm Neoverse N1, Neoverse V2, as well as 
> Arm Cortex-A725, Cortex-X925 CPUs.
> 
> Mode: thrpt
> Units: ops/us
> ObjectAlignmentInBytes: 64
> 
> Number is speed-up, higher number is better
> 
> | Benchmark            | Type   | Count | A725 | X925 | N1   | V2   |
> | naive                | Double | 128   | 1.0  | 1.0  | 1.0  | 1.0  |
> | naive                | Double | 512   | 1.0  | 1.0  | 1.0  | 1.0  |
> | naive                | Double | 2048  | 1.0  | 1.0  | 1.0  | 1.0  |
> | naive                | Double | 4096  | 1.0  | 1.01 | 1.0  | 1.0  |
> | reduction_after_loop | Double | 128   | 1.02 | 1.02 | 1.03 | 1.01 |
> | reduction_after_loop | Double | 512   | 1.0  | 0.99 | 1.0  | 1.0  |
> | reduction_after_loop | Double | 2048  | 1.0  | 1.0  | 1.0  | 1.0  |
> | reduction_after_loop | Double | 4096  | 1.0  | 1.0  | 1.0  ...

Ivan Zhechev has updated the pull request with a new target base due to a merge 
or a rebase. The incremental webrev excludes the unrelated changes brought in 
by the merge/rebase. The pull request contains three additional commits since 
the last revision:

 - Add test
 - Merge branch 'master' into 8392077-ivan
 - 8392077: AArch64: Remove redundant FADD in floating-point add reductions on 
NEON
   
   NEON non-strictly ordered floating-point reduction instruction rules are
   updated to avoid materialising a redundant `fadd`, and additionally now
   use an immediate operand instead of a register.
   
   Vector API and auto-vectorisation share the AddReductionV node which has
   to support the needs of both - it models a scalar value plus a vector
   operand.  Since `reduceLanes()` has no scalar source the Vector API
   intrinsic generates an identity scalar value which is passed as the
   first input to AddReductionVF/VD.  Because addition with the identity
   value is unnecessary when implementing a Vector API reduction, NEON
   non-strict floating-point reductions no longer generate an extra
   instruction.  Furthermore, the matcher has been updated to use
   zero-constrained immediate operands to guarantee that the scalar value
   is zero.
   
   Update the predicate of `reduce_non_strict_order_add2D_neon` to restrict
   it to 128-bit vectors, ensuring vectors wider than 128 bits select
   `reduce_addD_sve` for correct code generation on all SVE-capable
   systems.
   
   Before:
   
   faddp   v26.4s, v18.4s, v18.4s
   faddp   s19, v26.2s
   fadd    s19, s19, s17 // accum(s19) += s17(value 0.0)
   
   After:
   
   faddp   v26.4s, v18.4s, v18.4s
   faddp   s19, v26.2s
   
   Throughput benchmarks are split into 2 different types, based on the
   reduction benchmarks in
   test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java
   
   1. A naive version which performs lane reductions inside the loop, e.g.
      vectorDoubleAddReduce_naive
   2. 'reduction_after_loop' version which performs element-wise addition
      inside the loop, followed by a single reduceLanes after the loop,
      e.g.  vectorDoubleAddReduce_reduction_after_loop
   
   Benchmarking has been conducted on Arm Neoverse N1, Neoverse V2, as well
   as Arm Cortex-A725, Cortex-X925 CPUs.
   
   Mode: thrpt
   Units: ops/us
   ObjectAlignmentInBytes: 64
   
   Number is speed-up, higher number is better
   
   | Benchmark            | Type   | Count | A725 | X925 | N1   | V2   |
   | naive                | Double | 128   | 1.0  | 1.0  | 1.0  | 1.0  |
   | naive                | Double | 512   | 1.0  | 1.0  | 1.0  | 1.0  |
   | naive                | Double | 2048  | 1.0  | 1.0  | 1.0  | 1.0  |
   | naive                | Double | 4096  | 1.0  | 1.01 | 1.0  | 1.0  |
   | reduction_after_loop | Double | 128   | 1.02 | 1.02 | 1.03 | 1.01 |
   | reduction_after_loop | Double | 512   | 1.0  | 0.99 | 1.0  | 1.0  |
   | reduction_after_loop | Double | 2048  | 1.0  | 1.0  | 1.0  | 1.0  |
   | reduction_after_loop | Double | 4096  | 1.0  | 1.0  | 1.0  | 1.0  |
   | naive                | Float  | 128   | 1.02 | 1.01 | 1.21 | 1.0  |
   | naive                | Float  | 512   | 1.02 | 1.0  | 1.16 | 1.0  |
   | naive                | Float  | 2048  | 1.02 | 1.0  | 1.14 | 1.0  |
   | naive                | Float  | 4096  | 1.06 | 1.01 | 1.14 | 1.0  |
   | reduction_after_loop | Float  | 128   | 1.02 | 1.02 | 1.03 | 1.01 |
   | reduction_after_loop | Float  | 512   | 1.01 | 1.01 | 1.0  | 1.01 |
   | reduction_after_loop | Float  | 2048  | 1.0  | 1.0  | 1.0  | 1.0  |
   | reduction_after_loop | Float  | 4096  | 1.0  | 1.0  | 1.0  | 1.0  |
   
   Speed-up is observed on Neoverse N1 for the naive Float benchmark, as
   well as a slight general improvement for low trip counts of
   reduction_after_loop.
   
   As well as, a latency benchmark which uses reduction results in
   subsequent reductions, which forms a latency-sensitive instruction
   sequence.
   
   Mode: avgt
   Units: ns/op
   ObjectAlignmentInBytes: 64
   
   Number is reduction in time, lower number is better
   
   | Count | Type   | A725 | X925 | N1   | V2   |
   | 128   | Double | 0.73 | 0.64 | 0.74 | 0.73 |
   | 512   | Double | 0.75 | 0.73 | 0.75 | 0.75 |
   | 2048  | Double | 0.75 | 0.74 | 0.75 | 0.75 |
   | 4096  | Double | 0.75 | 0.75 | 0.75 | 0.75 |
   | 128   | Float  | 0.8  | 0.76 | 0.81 | 0.8  |
   | 512   | Float  | 0.82 | 0.8  | 0.82 | 0.82 |
   | 2048  | Float  | 0.82 | 0.82 | 0.82 | 0.82 |
   | 4096  | Float  | 0.82 | 0.82 | 0.82 | 0.82 |

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

Changes:
  - all: https://git.openjdk.org/jdk/pull/33319/files
  - new: https://git.openjdk.org/jdk/pull/33319/files/1281953c..23d7a5e6

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=33319&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=33319&range=00-01

  Stats: 133943 lines in 2856 files changed: 82550 ins; 36205 del; 15188 mod
  Patch: https://git.openjdk.org/jdk/pull/33319.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/33319/head:pull/33319

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

Reply via email to