c - 如何阻止 GCC 将此逐字节复制优化为 memcpy 调用?
问题描述
我将这段代码memcpy
作为标准 C 库实现的一部分,它一次将内存从一个字节复制src
到dest
一个字节:
void *memcpy(void *restrict dest, const void *restrict src, size_t len)
{
char *dp = (char *restrict)dest;
const char *sp = (const char *restrict)src;
while( len-- )
{
*dp++ = *sp++;
}
return dest;
}
,gcc -O2
生成的代码是合理的:
memcpy:
.LFB0:
movq %rdi, %rax
testq %rdx, %rdx
je .L2
xorl %ecx, %ecx
.L3:
movzbl (%rsi,%rcx), %r8d
movb %r8b, (%rax,%rcx)
addq $1, %rcx
cmpq %rdx, %rcx
jne .L3
.L2:
ret
.LFE0:
但是,在 处gcc -O3
,GCC 将这种简单的逐字节复制优化为memcpy
调用:
memcpy:
.LFB0:
testq %rdx, %rdx
je .L7
subq $8, %rsp
call memcpy
addq $8, %rsp
ret
.L7:
movq %rdi, %rax
ret
.LFE0:
这不起作用(memcpy
无条件调用自身),并且会导致段错误。
我试过通过-fno-builtin-memcpy
and -fno-loop-optimizations
,同样的事情发生了。
我正在使用 GCC 8.3.0 版:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-cros-linux-gnu/8.3.0/lto-wrapper
Target: x86_64-cros-linux-gnu
Configured with: ../configure --prefix=/usr/local --libdir=/usr/local/lib64 --build=x86_64-cros-linux-gnu --host=x86_64-cros-linux-gnu --target=x86_64-cros-linux-gnu --enable-checking=release --disable-multilib --enable-threads=posix --disable-bootstrap --disable-werror --disable-libmpx --enable-static --enable-shared --program-suffix=-8.3.0 --with-arch-64=x86-64
Thread model: posix
gcc version 8.3.0 (GCC)
如何禁用导致副本转换为memcpy
调用的优化?
解决方案
一件事在这里似乎就足够了:而不是使用-fno-builtin-memcpy
use-fno-builtin
来编译memcpy
单独的翻译单元!
另一种方法是通过-fno-tree-loop-distribute-patterns
;尽管这可能很脆弱,因为它禁止编译器首先重新组织循环代码,然后用mem*
函数调用替换其中的一部分。
或者,由于您不能依赖 C 库中的任何内容,因此-ffreestanding
可能需要按顺序使用。
推荐阅读
- excel - Excel 矩阵:搜索值并在其旁边提供值
- adb - LDplayer 连接到 vpn 时看不到播放器
- google-apps-script - 优化组功能Google Docs(App Script)是否有任何可能性?
- python - 设置文件中 long_description 的 Tox 错误
- android - Azure DevOps gradle 构建失败
- java - NonGUIDriver org.apache.jorphan.util.JMeterStopTestException 中的 JMeter 错误
- c# - 检测 C# 中的公共 IP 更改
- macos - 在 macOS 中单击“打开”时 Intellij IDEA 冻结
- session - Google 同意模式:通过 Google Analytics 上的同意来识别会话
- gnome-shell - 如何结束生成的 shell 脚本?