如何在 gcc 中静态初始化 __m128i 数组?

Posted

技术标签:

【中文标题】如何在 gcc 中静态初始化 __m128i 数组?【英文标题】:How to initialize __m128i array statically in gcc? 【发布时间】:2013-03-19 12:15:30 【问题描述】:

我正在将一些 SSE 优化代码从 Windows 移植到 Linux。而且我发现以下在 MSVC 中运行良好的代码在 GCC 中无法运行。

代码是初始化一个__m128i的数组。每个__mi28i 包含16 个int8_t。它确实使用 gcc 编译,但结果不如预期。

实际上,由于gcc将__m128i定义为long long int,代码会初始化一个数组,如:

long long int coeffs_ssse3[4] = 64, 83, 64, 36.

我用谷歌搜索并被告知“初始化向量的唯一可移植方法是使用 _mm_set_XXX 内在函数。”但是,我想知道还有其他方法可以初始化__m128i 数组吗?静态更好,并且不需要太多修改以下代码(因为我有大量以下格式的代码)。任何建议表示赞赏。

static const __m128i coeffs_ssse3[4] =

     64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0,
     83, 0, 36, 0,-36,-1,-83,-1, 83, 0, 36, 0,-36,-1,-83, -1,
     64, 0,-64,-1,-64,-1, 64, 0, 64, 0,-64,-1,-64,-1, 64, 0,
     36, 0,-83,-1, 83, 0,-36,-1, 36, 0,-83,-1, 83, 0,-36,-1
;

【问题讨论】:

【参考方案1】:

似乎gcc 没有将__m128* 类型视为聚合初始化的候选对象。由于它们不是标准类型,因此这种行为会因编译器而异。一种方法是将数组声明为 8 位整数的对齐数组,然后将指针转换为它:

static const int8_t coeffs[64] __attribute__((aligned(16))) =

     64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0,
     83, 0, 36, 0,-36,-1,-83,-1, 83, 0, 36, 0,-36,-1,-83, -1,
     64, 0,-64,-1,-64,-1, 64, 0, 64, 0,-64,-1,-64,-1, 64, 0,
     36, 0,-83,-1, 83, 0,-36,-1, 36, 0,-83,-1, 83, 0,-36,-1
;
static const __m128i *coeffs_ssse3 = (__m128i *) coeffs;

但是,我认为 Visual Studio 不支持这种语法 (__attribute__((aligned(x)))),因此您需要在其中使用一些 #ifdef 技巧来使用正确的指令来实现您想要的所有对齐方式目标平台。

【讨论】:

谢谢@Jason!我试过你的方法,效果很好。 (在您的回答中, uint8_t 应该是 int8_t ,因为该数组包含负值。这可能是一个错字,您可以编辑您的答案以使其完美:)

以上是关于如何在 gcc 中静态初始化 __m128i 数组?的主要内容,如果未能解决你的问题,请参考以下文章

打印 _mm_cmpeq_epi8 的输出(__m128i 类型)

从四个 __m128i 变量的 64 个高位或低位初始化 __m256i

用内在函数初始化 __m128i 常量的最快方法?

如何在 MSVC 中高效地将两个 __m128d 转换为一个 __m128i?

SSE:如何将 _m128i._i32[4] 减少到 _m128i._i8

如何在 C 中打印 __m128i 变量的位?