Как расширить int32x2_t до int32x4_t со встроенными NEON в clang / AArch64, когда вас не волнуют новые дорожки? - PullRequest
2 голосов
/ 17 апреля 2020

Товарищи ARMists,
Я хотел бы сузить и насытить 2 s32 до 2 s16 с кодом NEON и упаковать их в GPR. Мне нужно соответствовать определенному 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 не инициализирована? Я бы хотел избежать встроенной сборки.
Спасибо!

Ответы [ 2 ]

2 голосов
/ 30 апреля 2020

Я не знаю ни одного хорошего решения с использованием общих arm_neon.h встроенных функций, но, по крайней мере, с Clang, возможно, используя встроенные Clang Speci c, чтобы создать вектор, в котором некоторые элементы установлены как неопределенные, поэтому кодегену не нужно заполнять их каким-либо конкретным значением.

Установка, которая использует такой вид:

$ 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

https://godbolt.org/z/N_NsSE

См. https://clang.llvm.org/docs/LanguageExtensions.html#builtin -shufflevector для документации по __builtin_shufflevector.

РЕДАКТИРОВАТЬ: кажется также возможно достичь того же с Clang с помощью неинициализированной переменной ( хотя это может генерировать предупреждения с помощью `-Wuninitialized):

$ 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);
}

Clang выдает то же самое для этого (https://godbolt.org/z/TzHuon), в то время как G CC все еще включает mov v0.8b, v0.8b (https://godbolt.org/z/wZTAU9).

0 голосов
/ 30 апреля 2020
$ 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

https://godbolt.org/z/ATr4D7

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...