【问题标题】:Static vs. external intrinsics静态与外部内在函数
【发布时间】:2019-11-28 00:36:27
【问题描述】:

Clang 6.0.1 avxintrin.h 有声明:

static __inline __m256i __DEFAULT_FN_ATTRS _mm256_set1_epi32(int)

GCC 5.5 有:

extern __inline __m256i __attribute__((__gnu_inline__, _always_inline__, __artificial__)) _mm256_set1_epi32(int)

为什么会有一个extern 和一个static 这在一个调用_mm256_set1_epi32inline 函数中为我显示。 Clang 希望它被声明为static

#include <immintrin.h>

inline void SimdBlockBloomFilter_make_mask() {
  _mm256_set1_epi32(1);
}

-Weverything:

warning: static function '_mm256_set1_epi32' is used in an inline
function with external linkage [-Wstatic-in-inline]

使用 Clang++ 编译时,不会显示此错误。

【问题讨论】:

  • 可能写它们的人认为差异并不重要。内在函数的全部意义在于完全内联,链接是无关紧要的,除非作为后备,以防有人获取内在函数的地址。我不确定正确的解决方法是什么。
  • @PeterCordes 我想知道他们为什么还要写修饰符staticextern。他们似乎可以不用。
  • static inline 在使用-fPIC 编译的代码中很有用。并非所有编译器都同意 inline foo() { ... } 取代具有非隐藏 ELF 可见性的符号的符号插入。因此该函数实际上可能无法内联。除此之外,是的inline foo() { ... } 确实意味着不必发出独立定义(假设编译器选择在任何地方内联它),因此不需要static。我也很好奇 staticextern 在 C 或 C++ 中还有什么其他原因。
  • @PeterCordes 您的编译器将始终为inline foo() 发出普通函数代码和符号,因为该函数具有外部链接并且可以在翻译单元之外被引用。但是如果它永远不会被调用,你的链接器会删除该代码。
  • @user6556709:这仅适用于 C 中的 extern inline,而在 C++ 中则完全不适用。 godbolt.org/z/y2AoK7 显示 gcc/clang asm 输出,甚至在组装之前。常规的inline 还承诺每个呼叫站点都可以看到相同的定义。当前编译器通过仅在当前翻译中存在编译器选择不内联的调用站点时才发出独立定义来优化该过程,从而节省编译和链接期间的工作。 (顺便说一句,我认为在写我之前的评论时我可能会得到一个独立的定义,但我检查了 Godbolt 所以把它省略了。)

标签: c gcc static clang intrinsics


【解决方案1】:

在 GCC 版本中,gnu_inline attribute 在 C99 及更高模式下的行为接近于static inline

C 委员会在重新定义 extern inline 的含义时忽略了 GNU 的先例:对于 GNU 编译器,extern inline 意味着编译器永远不应该生成函数的非内联副本(即使它的地址被占用) .在 C99 中,extern inline 表示一个翻译单元中的定义完成了另一个翻译单元中的 inline 定义。

&lt;immintrin.h&gt; 的 GCC 版本使用 gnu_inline 属性在所有编译器模式(尤其是 C89/C90 和 C99)中获得预期的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    相关资源
    最近更新 更多