【发布时间】:2018-03-28 05:28:35
【问题描述】:
我想为函数的一部分手动编写一些内联程序集,但仅在编译它所针对的架构时才使用该程序集,然后回退到其他架构上的通用 C 实现。
当编译器在匹配的架构上时,让编译器使用内联程序集的最佳方法是什么? asm 块的语法是否指定它仅适用于特定架构,或者我应该在配置脚本中使用 autoconf target triplet 来定义预处理器符号?例如
配置.ac:
case $host in
x86_64-*)
AC_DEFINE([AMD64])
;;
esac
.c 源文件:
void f() {
#ifdef AMD64
asm (/* ... */)
#else
/* C code */
#endif
}
我想对于较大的或独立的函数,可以类似地使用 AM_CONDITIONAL 来选择不同的源文件(.c 或特定于平台的 .s)来选择程序集或 C。
还有其他选择吗?这是惯用语吗?
编辑:问题更多是关于是否有替代品,例如
asm "i386" ( ... )
或
asm "aarch64" ( ... )
或其他一些不涉及预处理器ifdefs的替代方案。
编辑 2:我正在寻找 GCC 的 Function Multiversioning 功能,其中可以根据特定架构提供多种替代实现,并且链接器在运行时自动选择最佳版本。如果允许我重新提出问题,我会将其放在答案中。
编辑 3:这个问题既适用于架构家族,如 x86/amd64/arm64,也适用于 instruction set architectures (ISAs),如 x86-SSE2、amd64-AVX 等。
【问题讨论】:
-
编译器定义了一堆宏,告诉你你在什么架构上。无需手动测试。
-
使用
#ifdef __x86_64__或__i386__。运行gcc -dM -E - </dev/null | less转储所有预定义的宏。添加-march=native或任何其他内容以定义__AVX__以及您的CPU 具有的其他内容。 (当然,查找它们以确保选择最便携的宏是个好主意。) -
没有像
asm "i386" ( ... )这样在 i386 上扩展的语法,并且在 GNU C 或我听说过的任何其他编译器中对其他目标都是无操作的。使用宏,编译器已经定义了 is 惯用的,以及每个人都在做什么。 -
这看起来仍然像 How do I identify x86 vs. x86_64 at compile time in gcc? 的副本。函数多版本化 (gcc.gnu.org/onlinedocs/gcc/Function-Multiversioning.html) 用于在运行时调度架构内的不同功能,而不是在编译时为不同架构选择代码。我可以重新打开,但任何基于此的答案似乎都会回答与问题所要求的完全不同的东西。
-
术语:x86-64 + AVX 不被视为与基线 x86-64 不同的 ISA。它是 x86-64(和 IA32)的可选扩展。您关于功能多版本化在这里相关或有用的论点现在终于有意义了。但它并没有实现避免使用预处理器进行架构选择的目标,不是吗? ARM 内部函数或 asm 指令在为 x86-64 构建时会导致编译或汇编错误,对吧,不管
target()属性如何?
标签: gcc assembly inline-assembly autotools