On Sat, Jan 10, 2009 at 12:55 PM, Richard Guenther
<richard.guent...@gmail.com> wrote:
> On Sat, Jan 10, 2009 at 12:19 PM, Raoul Gough <raoulgo...@clara.co.uk> wrote:
>> I've been investigating a code-reordering question to do with g++ strict
>> alias analysis, and I suspect there is a deficiency in the way type-based
>> alias analysis works. I realise that's unlikely to be the case, so I'll try
>> to present a concise demonstration which uses (I think) well-defined C code.
>> The original problem (now long worked around) was in a much larger C++
>> codebase and did result in a harmful reordering of code (although, that was
>> with g++ 3.4.3). Output below is from 4.3.2
>>
>> Take these two example functions:
>>
>> extern int foo(int* p1, char* p2)
>> {
>>   int result = *p1;
>>   *p2 = 4;
>>   return result;
>> }
>>
>> extern int bar(int* p1, double* p2)
>> {
>>   int result = *p1;
>>   *p2 = 4;
>>   return result;
>> }
>>
>> Both of these read via one pointer, assign via another and return the first
>> value. Obviously, if the two pointers alias the same storage and the
>> compiler reorders the read and the write, the wrong value will result. In
>> the first case, it's obvious that p2 may alias p1, since it has type char*.
>> Indeed, -fdump-tree-salias from g++ 4.3.2, shows the following:
>>
>>
>> Alias information for int foo(int*, char*)
>> [...]
>> Symbol memory tags
>>
>> SMT.4, UID D.1674, int, is addressable, is global, score: 960006, direct
>> reads: 0, direct writes: 0, indirect reads: 1, indirect writes: 1, call
>> clobbered (is global var, is incoming pointer), may aliases: { SMT.5 }
>> SMT.5, UID D.1675, char, is addressable, is global, score: 960006, direct
>> reads: 0, direct writes: 0, indirect reads: 1, indirect writes: 1, call
>> clobbered (is global var, is incoming pointer), may aliases: { SMT.4 }
>> [...]
>>
>>
>> I guess this means the compiler knows that the int* and char* "may alias"
>> the same storage. Now for the second function, type based alias analysis
>> tells us that p1 and p2 cannot alias each other, because an int and a double
>> can't simultaneously occupy the same storage. So -fdump-tree-salias shows
>> the following:
>>
>>
>> Alias information for int bar(int*, double*)
>> [...]
>> Symbol memory tags
>>
>> SMT.18, UID D.1688, int, is addressable, is global, score: 320002, direct
>> reads: 0, direct writes: 0, indirect reads: 1, indirect writes: 0, call
>> clobbered (is global var, is incoming pointer)
>> SMT.19, UID D.1689, double, is addressable, is global, score: 640004, direct
>> reads: 0, direct writes: 0, indirect reads: 0, indirect writes: 1, call
>> clobbered (is global var, is incoming pointer)
>> [...]
>>
>>
>> This doesn't show any "may aliases" lists, so I assume this means the
>> compiler thinks it can reorder accesses via the pointers. I've included the
>> full salias output below, in case I'm missing something. So here's a
>> problematic example (which was first pointed out to me by James Kanze on
>> comp.std.c++):
>>
>> union A
>> {
>>   int i_;
>>   double d_;
>> };
>>
>> void bar_bad()
>> {
>>   A a;
>>   a.i_ = 3;
>>   assert(bar(&a.i_, &a.d_) == 3);
>> }
>>
>> Here we pass into bar a pointer to int and double at the same storage
>> location. So now, if the compiler goes ahead and reorders the read and write
>> in function bar, the assertion would fail. Note that this code does *not*
>> write one type into a union and read another. It writes an int, reads an int
>> and then writes a double. All that's happening is that the storage is being
>> *reused* for a different type. However, this re-use takes place within
>> function bar, which doesn't necessarily know about the union (especially if
>> it's in a different compilation unit).
>>
>> So, my question is, does the salias analysis indicate that the compiler
>> thinks it can reorder the operations in function bar?
>
> There is a defect report about this and I'm sure numerous bugreports
> in bugzilla.
> The conclusion is that the above invokes undefined behavior because the
> accesses are not done through a union type, so the static memory typing rules
> of C apply.

http://www.open-std.org/JTC1/SC22/WG14/www/docs/dr_236.htm

> Richard.
>

Reply via email to