4

I was wondering if GCC will use the knowledge that the struct I created is overaligned and consider it simply as an integer when it comes to the generation of comparison asm.

It does not. I wonder if this is due to ABI issues, some other factor I missed or is it really a missing optimization?

godbolt link

code:

struct S{
    short a,b;
    bool operator == (const S&) const = default;
};

struct alignas(alignof(int)) S2  {
    short a,b;
    bool operator == (const S2&) const = default;
};

bool f(const S& s){
    constinit static S c{11,22};
    return c==s;
}

bool f2(const S2& s2){
    constinit static S2 c2{11,22};
    return c2==s2;
}

static_assert(alignof(S)==2);
static_assert(alignof(S2)==4);
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 1
    I don't think it has anything to do with alignment though especially since you linked the x86 version. – Jester Dec 23 '19 at 16:59
  • 2
    Fun fact: `return memcmp(this, &s, sizeof(s)) == 0;` gets compiled to a single integer sized compare, but that in turn doesn't seem to use the constants. – Jester Dec 23 '19 at 17:09

1 Answers1

3

It's most likely a missed optimization. A mere replacement of the defaulted comparison operator with a manual implementation results in 32-bit comparison being output in the overaligned struct version. I.e. this

struct alignas(alignof(int)) S4
{
    short a,b;
    bool operator == (const S4& s) const { return a==s.a && b==s.b; }
};
bool f4(const S4& s)
{
    constinit static S4 c{11,22};
    return c==s;
}

results in this:

f4(S4 const&):
        mov     eax, DWORD PTR [rdi]
        cmp     DWORD PTR f4(S4 const&)::c[rip], eax
        sete    al
        ret

Another optimization is obviously missed in this version (making c an immediate operand to yield cmp eax, 0x16000b), but at least there's no separate 16-bit comparisons.

See the full playground with your two versions and two with manually-defined operators.

Ruslan
  • 18,162
  • 8
  • 67
  • 136