svn commit: r247460 - head/sys/dev/acpica

Bruce Evans brde at optusnet.com.au
Fri Mar 1 04:16:04 UTC 2013


On Thu, 28 Feb 2013, Alexander Motin wrote:

> On 28.02.2013 18:25, Alexey Dokuchaev wrote:
>> On Thu, Feb 28, 2013 at 11:27:02AM +0000, Davide Italiano wrote:
>>> New Revision: 247460
>>> URL: http://svnweb.freebsd.org/changeset/base/247460
>>>
>>> Log:
>>>   MFcalloutng (r247427 by mav):
>>>   We don't need any precision here. Let it be fast and dirty shift then
>>>   slow and excessively precise 64-bit division.
>>>
>>> -    if (sbt >= 0 && us > sbt / SBT_1US)
>>> -	us = sbt / SBT_1US;
>>> +    if (sbt >= 0 && us > (sbt >> 12))
>>> +	us = (sbt >> 12);
>>
>> Does this really buy us anything?  Modern compilers should be smart enough to
>> generate correct code.  Do you have evidence that this is not the case here?
>> Not to mention that it obfuscates the code by using some magic constant.
>
> SBT_1US is 4294 (0x10c6). The best that compiler may do is replace
> division with multiplication. In fact, Clang even does this on amd64.
> But on i386 it calls __divdi3(), doing 64bit division in software. Shift
> is definitely cheaper and 5% precision is fine here.

I missed the additional magic in my previous reply.

But you should write the sloppy scaling as division by a sloppy factor:

#define	SSBT_1us	4096		/* power of 2 closest to SSBT_1US */

      if (sbt >= 0 && us > (uint64_t)sbt / SSBT_1us)
  	us = (uint64_t)sbt / SSBT_1us;

or provide and use conversion functions that do sloppy and non-sloppy
scaling.  I don't like having conversion functions for every possible
conversion, but this one is much more magic than for example
TIMEVAL_TO_TIMESPEC().  The casts to (uint64_t) are to help the compiler
understand that the sign bit is not there.

The need for magic scaling shows that the binary representation given
by sbintime_t isn't very good.  Mose clients want natural units of
microseconds or nanoseconds and need scale factors like
(4294.967206 / 4096) to adjust (4294 is already sloppy).  The binary
representation allows some minor internal optimizations and APIs are
made unnatural to avoid double conversions.

While here, I will point out style bugs introduced in the above:
- parentheses in "us = (sbt >> 12);" are redundant and reduce clarity,
    like parentheses in "us = (sbt / N);" would have, since the shift
    operator binds much more tightly than the assignment operator.
- parentheses in "us > (sbt >> 12);" are redundant but may increase
    clarity, since the shift operator doesn't bind much more tightly
    than the '<' comparison operator.  This one is hard to remember, but
    looking it up confirms that the precedence is not broken as designed
    in this case, but that the precedence is only 1 level higher for the
    shift operator.  The main broken as designed cases are the shift
    operator being 1 level lower than addition and subtraction, and
    bitwise operators being many more levels lower than other aritmetic
    operators and even below all comparision operators.

Bruce


More information about the svn-src-all mailing list