svn commit: r300965 - head/lib/libc/stdlib

Andrey Chernov ache at freebsd.org
Mon May 30 06:42:01 UTC 2016


On 30.05.2016 6:09, Bruce Evans wrote:
> On Sun, 29 May 2016, Conrad Meyer wrote:
> 
>> Does clang actually generate different code with this change?
> 
> It should, on exotic arches.
> 
>> On Sun, May 29, 2016 at 9:39 AM, Andrey A. Chernov <ache at freebsd.org>
>> wrote:
>>> Log:
>>>   Micro optimize: C standard guarantees that right shift for unsigned
>>> value
>>>   fills left bits with zero, and we have exact 32bit unsigned value
>>>   (uint32_t), so there is no reason to add "& 0x7fffffff" here.
> 
> Using uint32_t at all is an unportable pessimization.  On exotic arches
> that don't have native uint32_t registers, a theoretically perfect
> implementation wouldn't implement uint32_t.  This would expose the
> brokenness of broken code, so a practical implementation would emulate
> uint32_t so that the broken code would just run slower for arithmetic
> and much slower for locked memory operations.
> 
> uint32_t might be implemented not very slowly using 128-bit integer
> registers, or more slowly using the 53-bit mantissa part of an IEEE
> double precision floating point register.
> 
> If uint32_t is emulated, then the compiler is forced to act as if the
> code uses a longer type and does "& 0xffffffff" after every operation.
> Thes extra operations can only be combined sometimes.  More careful
> code can use a minimal number of this or similar "&" operations.  In
> checksum calculations, one "&" at the end is usually enough.
> 
>>> Modified: head/lib/libc/stdlib/random.c
> 
> random.c was mostly written before uint32_t was standard, so it used
> u_long and long.  Perhaps it wasn't careful enough with the "&"s to
> actually work unless u_long is precisely uint32_t and long is normal
> 2's complement with benign overflow.
> 
> Anyway, it was "fixed" (unimproved) using s/u_long/uint32_/ in most
> places where the API/ABI doesn't require longs (there is 1 dubious
> long left in a comment).  The correct fix is s/u_long/uint_fast32_t
> in most places and s/u_long/uint_least32_t/ in some places and then
> fix any missing "&"'s.  The "fast" and "least" types always exist,
> unlike the fixed-width types, and using them asks for time/space
> efficiency instead of emulated fixed-width.
> 
> On non-exotic arches, fast == least == fixed-width, so the correct
> substitution works as a quick fix even with missing "&"s.
> 
> It is not necessary to use the newfangled standard integer types to
> fix this here, since correct use of long types would work (they give
> 32 bits), but long is wasteful if it actually 64 bits or longer.
> 
> Even larger problems are looming with uintmax_t.  Any code that is
> careful enough to use it is likely to break or be bloated if it is
> expanded.  This is just like using u_long in old random().
> 
>>> ==============================================================================
>>>
>>> --- head/lib/libc/stdlib/random.c       Sun May 29 16:32:56
>>> 2016        (r300964)
>>> +++ head/lib/libc/stdlib/random.c       Sun May 29 16:39:28
>>> 2016        (r300965)
>>> @@ -430,7 +430,7 @@ random(void)
>>>                  */
>>>                 f = fptr; r = rptr;
>>>                 *f += *r;
>>> -               i = (*f >> 1) & 0x7fffffff;     /* chucking least
>>> random bit */
>>> +               i = *f >> 1;    /* chucking least random bit */
> 
> This gives an "&" to restore in the version with correct substitutions.
> 
> It also breaks the indentation.  (This file mostly indents comments to the
> right of code to column 40, but column 48 was used here and now column 32
> is used.)
> 
>>>                 if (++f >= end_ptr) {
>>>                         f = state;
>>>                         ++r;
> 
> Bruce
> 

I don't introduce uint32_t and int32_t here and don't have a slightest
idea of which types will be better to change them. F.e. *f += *r;
suppose unsigned 32bit overflow which don't naturally happens for large
types. Assigning uint32_t to some large type then clip it to smaller
after calculation - all of that can produce more code than save for
calculation itself.



More information about the svn-src-head mailing list