Arm 当您不使用'时,如何在clang/AArch64上使用NEON intrinsic将int32x2_t扩展为int32x4_t;你不在乎新车道吗?

Arm 当您不使用'时,如何在clang/AArch64上使用NEON intrinsic将int32x2_t扩展为int32x4_t;你不在乎新车道吗?,arm,simd,intrinsics,arm64,neon,Arm,Simd,Intrinsics,Arm64,Neon,各位武装主义者, 我想缩小和饱和2 s32到2 s16与霓虹灯代码,并把他们在一个探地雷达。 我需要符合特定的API,所以请不要在这里讨论效率或设计:) 以下是片段: int32x2_t stuff32 = ...; int16x4_t stuff16 = vqmovn_s32(vcombine_s32(stuff32, stuff32)); return vget_lane_u32(stuff16, 0) 产生 mov v0.d[1], v0.d[0] sqxtn v0.4h, v

各位武装主义者,
我想缩小和饱和2 s32到2 s16与霓虹灯代码,并把他们在一个探地雷达。 我需要符合特定的API,所以请不要在这里讨论效率或设计:)
以下是片段:

int32x2_t stuff32 = ...;
int16x4_t stuff16 = vqmovn_s32(vcombine_s32(stuff32, stuff32));
return vget_lane_u32(stuff16, 0)
产生

mov    v0.d[1], v0.d[0] 
sqxtn  v0.4h, v0.4s 
fmov   w0, s0 
ret           
是否有人知道一种方法来保持类型系统愉快,并使d寄存器的后半部分未初始化?我希望避免内联汇编。
谢谢大家!

$cat空调
$ cat a.c
#include <arm_neon.h>

int32_t narrow_saturate(int32x2_t stuff32) {
  int32x2_t zero = {0, 0};
  int16x4_t stuff16 = vqmovn_s32(vcombine_s32(stuff32, zero));
  return vget_lane_s32(vreinterpret_s32_s16(stuff16), 0);
}

$ gcc -O2 a.c -S -o-
[...]
narrow_saturate:
        mov     v0.8b, v0.8b
        sqxtn   v0.4h, v0.4s
        umov    w0, v0.s[0]
        ret

#include

我不知道使用通用
arm_neon.h
内部函数有什么好的解决方案,但至少对于Clang,使用特定于Clang的内置函数可以生成一个向量,其中一些元素被设置为未定义,因此codegen不需要用任何特定的值填充它们

使用的设置如下所示:

$ cat test.c
#include <arm_neon.h>

int32_t narrow_saturate(int32x2_t stuff32) {
  int16x4_t stuff16 = vqmovn_s32(__builtin_shufflevector(stuff32, stuff32, 0, 1, -1, -1));
  return vget_lane_s32(vreinterpret_s32_s16(stuff16), 0);     
}

$ clang -target aarch64-linux-gnu test.c -S -o - -O2
[...]
narrow_saturate:
        sqxtn   v0.4h, v0.4s
        fmov    w0, s0
        ret

Clang为这个()生成了与上面相同的结果,而GCC仍然包含一个
mov v0.8b,v0.8b
()。

我尝试了各种方法,但都没有成功。看来他和十年前一样愚蠢。(GCC 9.2.1)感谢您的尝试!也许没有办法。但是有可能使用叮当声
\uuuuuuuuuuuuuuShuffleVector
,将
vcombine_s32
替换为具有相同功能但表示上面两个元素可能未定义的内容-但这显然不是一个可移植的解决方案。如果使用未初始化的变量执行
vcombine_s32
,Clang似乎也会产生相同的预期结果-但可能会产生警告虽然。这在本质上不是仍然一样吗?你有多余的
mov v0.8b,v0.8b
指令,这是要避免的全部问题。太好了,我在这个平台上使用了clang,所以。。。非常感谢。
$ cat test.c
#include <arm_neon.h>

int32_t narrow_saturate(int32x2_t stuff32) {
  int32x2_t uninitialized;
  int16x4_t stuff16 = vqmovn_s32(vcombine_s32(stuff32, uninitialized));
  return vget_lane_s32(vreinterpret_s32_s16(stuff16), 0);
}