0

If I define static instance of a class, is there optimization in compilers (particularly g++/clang) to omit base register (for thiscalls) when data members accessed directly or indirectly (I mean [base + index * scale + displacement] formula) and just use single displacement constant for all of them? All member functions may became static (in case of sole instance of the class it is reasonable).

I can't check this, because on godbolt.org compiler aggressively optimizes following code to xor eax, eax; ret:

struct A
{

    int i;
    void f()
    {
        ++i;
    }

};

static A a;

int main(int argc, char * argv[])
{
    a.i = argc;
}
Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • 1
    seems like it: https://godbolt.org/g/7f7c9F but asking whether a compiler has a particular optimization is hardly ever a good choice. Who knows what the next version will have, or what seemingly unrelated bit of code you change will modify how the optimizer optimizes. – xaxxon Mar 14 '18 at 06:01
  • You used `static`, instead of making `a` global, so gcc can optimize it away if nothing else in the compilation unit does anything with it. I don't even know what you're asking; `a.i`'s address is known at compile time, so why would there be any register involved ever, except to load a pointer from the GOT for PIC in 32-bit code? You're not passing around a `this` pointer anywhere. You just get a `mov [a], eax` after loading `argc` from the stack (in 32-bit code with a stack-args calling convention: https://godbolt.org/g/woRZp2). – Peter Cordes Mar 14 '18 at 08:31
  • Do you optimize specifically for 32 bits? Because on a 64-bit system you need a large 8-byte address for global variables. If you have several access to class members, having a `this`-pointer in a register gives you a significant code size reduction. – Bo Persson Mar 14 '18 at 10:05
  • @BoPersson I think on 64-bit systems there is RIP-relative addressing userd for global variables (not 8-byte, but just 32bit signed offset). – Tomilov Anatoliy Mar 14 '18 at 11:08

1 Answers1

2

Short answer: Maybe.

Long answer: A modern compiler certainly has the ability to optimize away fetching the this pointer, and using complex addressing modes is definitely within the reach of all modern compilers that I'm aware of (including, but not limited to: gcc, clang and MS Visual C).

Whether a particular compiler chooses to do so on a specific construct is down to how well the compiler "understands" the code presented to it. As you've just experienced, the compiler removes all of your code, because it doesn't actually "do" anything. You're just assigning a member of a global struct, which is never again used, so the compiler can reason that "well, you never use it again, so I won't do that". Remove static, and it's plausible that the compiler can't know that it's not used elsewhere. Or print the value of a.i, or pass it to an external function that can't be inlined, etc, etc.

In your example, I would really just expect the compiler to store the value of argc into the address of a.i, and that can probably be done in two instructions, move argc from stack into a register, and move that register into the memory calculated for a.i - which is probably a constant address according to the compiler. So no fancy addressing modes needed in this case.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227