gpt4 book ai didi

c++ - 为什么这个简短的比较没有按我预期的方式优化?

转载 作者:可可西里 更新时间:2023-11-01 17:37:49 25 4
gpt4 key购买 nike

我有一个复合索引类型,它由两个 16 位整数组成,这些整数打包到一个 32 位对象中,旨在传递并像指针一样处理。但我偶然注意到我定义的比较运算符并没有按照我预期的方式进行优化。

给定这个缩减代码:

#include <cstdint>

struct TwoParter {
std::uint16_t blk;
std::uint16_t ofs;
};
static_assert (sizeof(TwoParter) == sizeof(std::uint32_t), "pack densely");

bool equal1 (TwoParter const & lhs, TwoParter const & rhs) {
return lhs.blk == rhs.blk && lhs.ofs == rhs.ofs;
}

bool equal2 (TwoParter const & lhs, TwoParter const & rhs) {
auto lp = reinterpret_cast <std::uint32_t const *> (&lhs);
auto rp = reinterpret_cast <std::uint32_t const *> (&rhs);
return *lp == *rp;
}

GCC(7.1 on Compiler Explorer)生成以下程序集(选项 -m64 -std=c++11 -O3):

equal1(TwoParter const&, TwoParter const&):
movzwl (%rsi), %edx
xorl %eax, %eax
cmpw %dx, (%rdi)
je .L5
rep ret
.L5:
movzwl 2(%rsi), %eax
cmpw %ax, 2(%rdi)
sete %al
ret
equal2(TwoParter const&, TwoParter const&):
movl (%rsi), %eax
cmpl %eax, (%rdi)
sete %al
ret

其中一个似乎比另一个做的工作更多。但我看不出它们有何不同:断言保证结构的布局使得作为 uint23_t 的比较 必须 比较所有相同的data 分别检查 uint16_t 字段。更重要的是,这是 x86,所以编译器已经知道会是这种情况。 && 的短路行为对输出不应该很重要,因为它的右手操作数没有影响(编译器可以看到这一点),并且由于没有其他有趣的事情发生,我可以'想象一下为什么它会想要例如延迟加载数据的后半部分。

& 运算符替换 && 可以摆脱跳转,但不会从根本上改变代码的作用:它仍然会生成两个单独的 16 位比较,而不是一次比较所有数据,这表明短路可能不是问题所在(尽管它确实提出了一个相关问题,即为什么它不编译 &&& 同样的方式 - 在这两种情况下,两者之一肯定应该“更好”)。

令我感兴趣的是,同样根据 Compiler Explorer,所有主要编译器(GCC、Clang、Intel、MSVC)似乎都在做大致相同的事情。这减少了这是一个优化器疏忽的可能性,但我看不到我自己对此的评估实际上是错误的。

所以这有两个部分:

1) equal1 真的和 equal2 做同样的事情吗?我在这里错过了什么疯狂的东西吗?

2) 如果是这样,为什么编译器会选择不发出较短的指令序列?

我确信优化在这种情况下一定是编译器知道的事情,因为它们对于加速其他更严肃的代码(例如memcmp 将内容插入 vector 寄存器以一次比较更多数据。

最佳答案

对齐要求不同,TwoParterstd::uint16_t 具有相同的对齐方式。

TwoParter 更改为

struct alignas(std::uint32_t) TwoParter {
std::uint16_t blk;
std::uint16_t ofs;
};

为 gcc 7.1 生成相同的 asm:

equal1(TwoParter const&, TwoParter const&):
movl (%rsi), %eax
cmpl %eax, (%rdi)
sete %al
ret
equal2(TwoParter const&, TwoParter const&):
movl (%rsi), %eax
cmpl %eax, (%rdi)
sete %al
ret

Demo

关于c++ - 为什么这个简短的比较没有按我预期的方式优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43926441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com