Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't GCC and Clang do this aliasing-optimization?

I have a case where a friend casts a non-base class object of type "Base" to a class type object "Derived", where "Derived" is a derived class of "Base" and only adds functions, but no data. In the below code, I did add a data member x to the derived class

struct A {   int a; };  struct B : A {   // int x;   int x; };  A a;  int g(B *b) {    a.a = 10;    b->a++;    return a.a; } 

With strict alias analysis on, GCC (also Clang) always returns 10, and not 11, because b can never point to a in a well-defined code. However, if I remove B::x (as is actually the case in the code of my friend), GCC's output assembler code does not optimize the return access of a.a and reloads the value from memory. So the code of my friend that calls g "works" on GCC (as he intended) even though I think it still has undefined behavior

g((B*)&a); 

So in essentially the same two cases, GCC optimizes one case and doesn't optimize the other case. Is it because b can then legally point to a? Or is it because GCC just wants to not break real-world code?


I tested the answer that states

If you remove B::x, then B meets the requirements in 9p7 for a standard-layout class and the access becomes perfectly well-defined because the two types are layout-compatible, 9.2p17.

With two layout compatible enums

enum A : int { X, Y }; enum B : int { Z };  A a;  int g(B *b) {    a = Y;    *b = Z;    return a; } 

The assembler output for g returns 1, not 0, even though A and B are layout compatible (7.2p8).


So my further question is (quoting an answer): "two classes with exactly the same layout may be considered "almost the same" and they are left out of the optimization.". Can someone provide a proof of this for GCC or Clang?

like image 972
Johannes Schaub - litb Avatar asked Jun 19 '13 14:06

Johannes Schaub - litb


People also ask

Does clang optimize better than GCC?

GCC consistently outperformance Clang on all optimization levels. 32 Bit Performance is on a bit lower side with respect to corresponding 64-bit compilers & optimization levels. This can be attributed to being able to utilize the RAM properly. The contrast between O0 & Other optimization levels is very visible.

Why is clang faster than GCC?

Clang is much faster and uses far less memory than GCC. Clang aims to provide extremely clear and concise diagnostics (error and warning messages), and includes support for expressive diagnostics. GCC's warnings are sometimes acceptable, but are often confusing and it does not support expressive diagnostics.

Does Clang compile faster than GCC?

GCC is slower to compile than clang, so I spend a lot of time compiling, but my final system is (usually) faster with GCC, so I have set GCC as my system compiler.

Why is aliasing strict?

This is done because they referred to the same memory location. Strict Aliasing: GCC compiler makes an assumption that pointers of different types will never point to the same memory location i.e., alias of each other. Strict aliasing rule helps the compiler to optimize the code.


1 Answers

If you remove B::x, then B meets the requirements in 9p7 for a standard-layout class and the access becomes perfectly well-defined because the two types are layout-compatible, 9.2p17 and the members both have the same type.


A standard-layout class is a class that:

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

Two standard-layout struct types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types.

like image 106
Ben Voigt Avatar answered Sep 20 '22 08:09

Ben Voigt