【问题标题】:Architecture-specific inline assembly特定于架构的内联汇编
【发布时间】: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


【解决方案1】:

对于编译时架构的选择,比如amd64 & arm64的区别,compiler-defined preprocessor directives上的#ifdef是常用的做法。 cpp -dM - 提供了编译器定义的宏列表:

例如:

#ifdef __x86_64__
// impl.
#else
// default impl
#endif

当 CPU 支持时,对于优化汇编替代方案的运行时链接选择,Function Multi-versioning 提供了一种方法来提供函数的多个实现。运行时链接器根据可用的 CPU 功能确定使用哪个。

__attribute__ ((target("default")))
void f() {
}

__attribute__ ((target("sse4.2")))
void f() {
}

【讨论】:

    猜你喜欢
    • 2012-10-20
    • 2019-04-10
    • 2013-07-23
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多