https://github.com/cassioneri/eaf suggest this code for leap year calculation:

    public static boolean isLeap(long year) {
        int d = year % 100 != 0 ? 4 : 16;
        return (year & (d - 1)) == 0;
    }

.. with a claim this would compile down to branchless, easily pipelined code.

This doesn't currently happen with C2. In the meantime I think we can improve 
the current code in `Year.isLeap` and `IsoChronology.isLeapYear` by leveraging 
the fact that the `% 100` check is only needed if `(year & 15) != 0`:


    public static boolean isLeap(long year) {
        return (year & 15) == 0 ? (year & 3) == 0 : (year & 3) == 0 && year % 
100 != 0;
    }


Mac M1:

Name                           Cnt  Base   Error   Test   Error   Unit  Change
LeapYearBench.isLeapYear        15 0,743 ± 0,009  0,994 ± 0,005 ops/us   1,34x 
(p = 0,000*)
LeapYearBench.isLeapYearChrono  15 0,748 ± 0,006  0,991 ± 0,003 ops/us   1,32x 
(p = 0,000*)
LeapYearBench.isLeapYearNS      15 0,558 ± 0,026  0,552 ± 0,033 ops/us   0,99x 
(p = 0,602 )
  * = significant


Linux x64:

Name                           Cnt  Base   Error   Test   Error   Unit  Change
LeapYearBench.isLeapYear        15 0.534 ± 0.001  0.765 ± 0.004 ops/us   1.43x 
(p = 0.000*)
LeapYearBench.isLeapYearChrono  15 0.535 ± 0.000  0.753 ± 0.040 ops/us   1.41x 
(p = 0.000*)
LeapYearBench.isLeapYearNS      15 0.352 ± 0.000  0.351 ± 0.001 ops/us   1.00x 
(p = 0.000*)
  * = significant


30% higher throughput on M1, 40% on x64. `isLeapYearNS` runs a variant of the 
code from https://github.com/cassioneri/eaf ported to java - perhaps the JIT 
can be improved to do whatever clang/gcc does here and achieve an even better 
speed-up.

Testing: so far only java/time/tck/java/time locally, will run a few tiers 
before filing an enhancement and opening the PR for review.

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

Commit messages:
 - Add comment
 - Delegate IsoChronology.isLeapYear to Year.isLeap (both specified to behave 
identically), add microbenchmark testing the variant that optimize well with gcc
 - Merge branch 'master' into leapyear
 - Leap year optimization inspired by Neri & Schneider

Changes: https://git.openjdk.org/jdk/pull/16491/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=16491&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8319423
  Stats: 101 lines in 3 files changed: 99 ins; 0 del; 2 mod
  Patch: https://git.openjdk.org/jdk/pull/16491.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/16491/head:pull/16491

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

Reply via email to