RFR: 8234331: Add robust and optimized utility for rounding up to next power of two+
Claes Redestad
claes.redestad at oracle.com
Tue Dec 3 23:38:55 UTC 2019
Hi Thomas and others,
thanks for the thorough feedback!
I also had offline discussions about the existing utilities in
zUtils.inline.hpp with Per Liden, and decided to try and work this into
a templated solution that enables both 32-bit and 64-bit
implementations to work correctly - along with signed variants
(especially nice with types such as size_t).
http://cr.openjdk.java.net/~redestad/8234331/open.03
This is a pretty significant rework. Changes since .01:
- introduce utilities/powerOfTwo.hpp
- move round_up_* and round_down_* from zUtils, re-implement to use
the new implementation
- implement next_* as round_up_*(value + 1) as per John's suggestion.
- added tests
- corrected the issues Thomas, Ivan and others pointed out, mainly
ensuring we don't depend on undefined behavior in neither product
code, asserts nor tests
- .. and ensure to use next and round_up as appropriate to preserve
behavior
Other notes:
- Moving existing power-of-two functions like is_power_of_2 from
globalDefinitions.hpp to powerOfTwo.hpp would be straightforward, but
tedious. I'd like to defer this to a follow-up
- The xlc implementation is untested, but should work. If someone can
verify, I'd be much obliged.
- Many thanks to Erik Österlund, who guided me through a maze of
undefined behavior and template metaprogramming to a workable and
relatively clean implementation
- HotSpot shrinks by ~15Kb :-)
Testing: tier1-5
On 2019-11-28 08:34, Thomas Stüfe wrote:
> Hi Claes,
>
> I think this is useful. Why not a 64bit variant too? If you do not want
> to go through the hassle of providing a count_leading_zeros(uint64_t),
> you could call the 32bit variant twice and take care of endianness for
> the caller.
>
> --
>
> In inline int32_t next_power_of_two(int32_t value) , should we weed out
> negative input values right away instead of asserting at the end of the
> function?
>
> --
>
> The functions will always return the next power of two, even if the
> input is a power of two - e.g. "2" for "1". Is that intended? It would
> be nice to have an API comment in the header describing these corner
> cases (what happens for negative input, what happens if input is power 2).
>
> --
>
> The patch can cause subtle differences in some caller code, I think, if
> input value is a power of 2 already. See e.g:
>
> http://cr.openjdk.java.net/~redestad/8234331/open.01/src/hotspot/share/libadt/dict.cpp.udiff.html
>
> - i=16;
> - while( i < size ) i <<= 1;
> + i = MAX2(16, (int)next_power_of_two(size));
>
> If i == size == 16, old code would keep i==16, new code would come to
> i==32, I think.
>
> http://cr.openjdk.java.net/~redestad/8234331/open.01/src/hotspot/share/opto/phaseX.cpp.udiff.html
>
> //------------------------------round_up---------------------------------------
> // Round up to nearest power of 2
> -uint NodeHash::round_up( uint x ) {
> - x += (x>>2); // Add 25% slop
> - if( x <16 ) return 16; // Small stuff
> - uint i=16;
> - while( i < x ) i <<= 1; // Double to fit
> - return i; // Return hash table size
> +uint NodeHash::round_up(uint x) {
> + x += (x >> 2); // Add 25% slop
> + return MAX2(16U, next_power_of_two(x));
> }
>
> same here. If x == 16, before we'd return 16, now 32.
>
> ---
>
> http://cr.openjdk.java.net/~redestad/8234331/open.01/src/hotspot/share/runtime/threadSMR.cpp.udiff.html
>
> I admit I do not understand the current coding :) I do not believe it
> works for all input values, e.g. were
> get_java_thread_list()->length()==1025, we'd get 1861 - if I am not
> mistaken. Your code is definitely clearer but not equivalent to the old one.
FTR, the algorithm used is described here:
http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
(1025 should round up to 2048)
Thanks!
/Claes
>
> ---
>
> In the end, I wonder whether we should have two kind of APIs, or a
> parameter, distinguishing between "next power of 2" and "next power of 2
> unless input value is already power of 2".
>
> Cheers, Thomas
>
>
>
>
>
> On Tue, Nov 26, 2019 at 10:42 AM Claes Redestad
> <claes.redestad at oracle.com <mailto:claes.redestad at oracle.com>> wrote:
>
> Hi,
>
> in various places in the hotspot we have custom code to calculate the
> next power of two, some of which have potential to go into an infinite
> loop in case of an overflow.
>
> This patch proposes adding next_power_of_two utility methods which
> avoid infinite loops on overflow, while providing slightly more
> efficient code in most cases.
>
> Bug: https://bugs.openjdk.java.net/browse/JDK-8234331
> Webrev: http://cr.openjdk.java.net/~redestad/8234331/open.01/
>
> Testing: tier1-3
>
> Thanks!
>
> /Claes
>
More information about the hotspot-compiler-dev
mailing list