【问题标题】:Is gcc missing an optimization opportunity on this comparison of overaligned struct of 2 shorts?在对 2 条短裤的过度对齐结构进行比较时,gcc 是否错过了优化机会?
【发布时间】:2020-04-14 22:43:21
【问题描述】:

我想知道 GCC 是否会使用我创建的结构过度对齐的知识,并在生成比较 asm 时将其简单地视为一个整数。

它没有。 我想知道这是否是由于 ABI 问题,我错过了其他一些因素,还是真的缺少优化?

godbolt link

代码:

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

【问题讨论】:

  • 我认为这与对齐没有任何关系,特别是因为您链接了 x86 版本。
  • 有趣的事实:return memcmp(this, &s, sizeof(s)) == 0; 被编译为单个整数大小的比较,但这似乎又不使用常量。

标签: c++ assembly optimization language-lawyer alignas


【解决方案1】:

这很可能是错过了优化。仅用手动实现替换 defaulted 比较运算符会导致在过度对齐的结构版本中输出 32 位比较。 IE。这个

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

结果:

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

这个版本显然遗漏了另一个优化(使c 成为直接操作数以产生cmp eax, 0x16000b),但至少没有单独的16 位比较。

查看full playground 的两个版本和两个手动定义的运算符。

【讨论】:

    猜你喜欢
    • 2019-03-02
    • 2019-11-09
    • 2011-10-10
    • 1970-01-01
    • 2018-08-28
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    相关资源
    最近更新 更多