Search code examples
c++assemblyoptimizationlanguage-lawyeralignas

Is gcc missing an optimization opportunity on this comparison of overaligned struct of 2 shorts?


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);

Solution

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