移动 __m128 的上下浮点数

move lower and upper floats of __m128

如何将 __m128 的上下浮点数移动成两个 __m128 并清零另一半。

由于您没有指定,我假设意图是使用 SSE 内在函数。我还假设至少 SSE2 可用,因为这基本上是最近 x86-64 设置的基线……

一种非常直白的方式来做你上面描述的是简单地复制输入的低 64 位并通过 _mm_move_epi64()

将高 64 位归零
__m128 lo2(__m128 x)
{
    return _mm_castsi128_ps(_mm_move_epi64(_mm_castps_si128(x)));
}

并使用_mm_move_sd()复制输入的高64位和从零开始复制低64位

__m128 hi2(__m128 x)
{
    return _mm_castpd_ps(_mm_move_sd(_mm_castps_pd(x), _mm_setzero_pd()));
}

工作示例here

_mm_movelh_ps()_mm_movehl_ps() 与全零寄存器相结合,可以满足您的需求吗?

#include <iostream>
#include <x86intrin.h>

void print_vec(__m128 a) {
  alignas(16) float res[4];
  _mm_store_ps(res, a);
  std::cout << res[0] << '\t' << res[1] << '\t' << res[2] << '\t' << res[3]
            << '\n';
}

int main() {
  __m128 vec = _mm_set_ps(4.0f, 3.0f, 2.0f, 1.0f);

  __m128 lo = _mm_movelh_ps(vec, _mm_setzero_ps());
  __m128 hi = _mm_movehl_ps(vec, _mm_setzero_ps());

  std::cout << "Orig:\t";
  print_vec(vec);
  std::cout << "Lower:\t";
  print_vec(lo);
  std::cout << "Upper:\t";
  print_vec(hi);

  return 0;
}

编译和 运行 这会产生:

Orig:   1   2   3   4
Lower:  1   2   0   0
Upper:  0   0   3   4