Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: About compiler optimizations

Author: Eugene Nalimov

Date: 14:59:46 12/19/02

Go up one level in this thread


The following is part of the ANSI/ISO C++ Standard (section 3.10, clause 15):

If a program attempts to access the stored value of an object through an lvalue
of other than one of the following type the behavior is undefined (footnote: the
intent of this list is to specify those circumstances in which an object may or
may not be aliased)
-- the dynamic type of the object,
-- a cv-qualified version of the dynamic type of the object,
-- a type that is the signed or unsigned type corresponding to the dynamic type
of the object,
-- a type that is signed or unsigned type  corresponding to a cv-qualified
version of the dynamic type of the object,
-- an aggregate or union type that includes one of the aforementioned types
among its members (incl., recursively, a member of a subaggregate or contained
union),
-- a type that is a (possibly cv-qualified) base class type of the dynamic type
of the object,
-- a char or unsigned char type.

I don't have C standard nearby, but it contains something similar.

Unfortunately, lot of real-world C/C++ code violate that part of the standard.
For example, it often assume that if (sizeof(x) == sizeof(y)) you can write
something like
    x  xVal;
    y* py;

    xVal = *(x*)py;
    ...
    *(x*)py = yVal;
and *(py) will contain its initial value.

Or here is another example from real-world code:
    void copy (long *plSrc, short *psDst)
    {
        int i;
        long lTemp;
        short *psSrc;

        assert (sizeof(long) % sizeof (short) == 0);
        lTemp = *plSrc;
        psSrc = (short*)&lTemp;
        for (i=0; i < sizeof(long)/sizeof(short); i++)
            psDst[i] = psSrc[i];
    }
Author used sizeof() and assert(), and was absolutely sure the program is 100%
portable on all systems he cared about (i.e. where short is 16 or 32 bits, long
is 32 or 64 bits). Of course it violates mentioned part of the standard, so
according to the standard the code is broken.

If compiler will strictly implement C/C++ aliasing rules it can generate
significally faster code for some benhmarks, but lot of programs will not work
being compiled with that compiler. Of course you can always say "The program
violates the standard", but when the customer has the choice -- try to find such
bugs in 30,000,000 lines of heavily multithreaded code, or use the compiler that
generates 10% slower code for the usual benchmarks, but will generate expected
code for such application -- how do you think, what compiler will be used?

Another examples? My own experience (from the last 2 weeks only):
(1) Huge program assumed that return value of wcscmp() is -1, 0, or +1, because
that was so on all the systems where program was ported till that moment. It is
not so on the new system (it took several person-days to figure the problem),
and after lot of discussion it was decided it's easier to change implementation
of wcscmp() than to check how each result of wcscmp() is used.
(2) Compiler assumed that constructors for all C++ global objects are executed
*before* any other user's code can be executed, and performed some optimizations
based on that. Of course user wrote his own version of startup code that first
executed some his code and only than called constructors, and used that code
instead of shipped startup code.

Thanks,
Eugene

On December 19, 2002 at 16:59:04, Dieter Buerssner wrote:

>On December 19, 2002 at 13:11:12, Robert Hyatt wrote:
>
>>If you do unsafe aliasing and such, it might have a problem, but nobody here
>>writes that kind of code...
>
>I wonder, what you mean by "unsafe aliasing". That pointers can alias each other
>is part of the C-language. If you write a memmove-alike yourself, it could very
>likely include, what you call unsafe aliasing. Compiler optimization switches
>that "assume no alias" may break the code. Of course, many functions cannot
>handle aliases by design (for example straight forward code for vector
>multiplication like cross_product(double *a, double *b, double *result) will not
>work when called like cross_product(a, b, b); With other algorithms, it can be
>more subtle).
>
>Regards,
>Dieter



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.