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. >