Does Java optimize division by powers of two to bitshifting?

前端 未结 3 1949
抹茶落季
抹茶落季 2020-12-18 01:43

Does the Java compiler or the JIT compiler optimize divisions or multiplications by a constant power of two down to bitshifting?

For example, are the follow

3条回答
  •  一个人的身影
    2020-12-18 02:15

    If the JVM does not do it, you can easily do it yourself.

    As noted, right shifts on negative numbers do not behave the same as division because the result is rounded in the wrong direction. If you know that the dividend is non-negative, you can safely replace the division by a shift. If it might be negative, you can use the following technique.

    If you can express your original code in this form:

    int result = x / (1 << shift);
    

    You can replace it with this optimized code:

    int result = (x + (x >> 31 >>> (32 - shift))) >> shift;
    

    Or, alternatively:

    int result = (x + ((x >> 31) & ((1 << shift) - 1))) >> shift;
    

    These formulae compensate for the incorrect rounding by adding a small number computed from the sign bit of the dividend. This works for any x with all shift values from 1 to 30.

    If the shift is 1 (i.e., you are dividing by 2) then the >> 31 can be removed in the first formula to give this very tidy snippet:

    int result = (x + (x >>> 31)) >> 1;
    

    I have found these techniques to be faster even when the shift is non-constant, but obviously they benefit the most if the shift is constant. Note: For long x instead of int, change 31 and 32 respectively to 63 and 64.

    Examining the generated machine code shows that (unsurprisingly) the HotSpot Server VM can do this optimization automatically when the shift is constant, but (also unsurprisingly) the HotSpot Client VM is too stupid to.

提交回复
热议问题