2016-11-30 20 views
1

Вот мой код для добавления всех int16x4 элемента в полосе:Как добавить все int32 элемента в полосе с использованием неона присущей

#include <arm_neon.h> 
... 
int16x4_t acc = vdup_n_s16(1); 
int32x2_t acc1; 
int64x1_t acc2; 
int32_t sum; 
acc1 = vpaddl_s16(acc); 
acc2 = vpaddl_s32(acc1); 
sum = (int)vget_lane_s64(acc2, 0); 
printf("%d\n", sum);// 4 

И я пытался добавить все int32x4 элемент в переулке.

но мой код выглядит неэффективен:

#include <arm_neon.h> 
... 
int32x4_t accl = vdupq_n_s32(1); 
int64x2_t accl_1; 
int64_t temp; 
int64_t temp2; 
int32_t sum1; 
accl_1=vpaddlq_s32(accl); 
temp = (int)vgetq_lane_s64(accl_1,0); 
temp2 = (int)vgetq_lane_s64(accl_1,1); 
sum1=temp+temp2; 
printf("%d\n", sum);// 4 

Есть просто и ясно способ сделать это? Я надеюсь, что код сборки LLVM просто и четко после компиляции. и я также надеюсь, что окончательный тип sum - 32 бит.

Я использовал ellcc базу кросс-компилятора в инфраструктуре компилятора LLVM для ее компиляции.

Я видел подобный вопрос (Add all elements in a lane) на stackoverflow, но встроенный addv не работает на моем хосте.

+0

Почему вы чувствуете, что ваш код выглядит неэффективным? Я не вижу сложного цикла или ветвления. Просто последовательный. И есть ли проблема, кроме эффективности, которую вы пытаетесь решить? т. е. делает ли код то, что он должен делать? – ryyker

+0

Поскольку код сборки LLVM усложняется после компиляции, поэтому я хотел бы знать, есть ли более простой способ сделать это, например, неоновый внутренний. – Shun

+0

Проблема для моей цели - автоматически генерировать LLVM-IR через проход, мне сложно, если код LLVM-IR сложный. – Shun

ответ

1

Если вы хотите только результат на 32-битную, предположительно либо промежуточное переполнение маловероятно, или вы просто не заботятся об этом, в этом случае вы можете просто остаться 32-битную весь путь:

int32x2_t temp = vadd_s32(vget_high_s32(accl), vget_low_s32(accl)); 
int32x2_t temp2 = vpadd_s32(temp, temp); 
int32_t sum1 = vget_lane_s32(temp2, 0); 

Однако, используя накопление 64-битную на самом деле не больше хлопот, а также может быть сделано без выпадения из NEON - это просто другой порядок операций:

int64x2_t temp = vpaddlq_s32(accl); 
int64x1_t temp2 = vadd_s64(vget_high_s64(temp), vget_low_s64(temp)); 
int32_t sum1 = vget_lane_s32(temp2, 0); 

любой из тех, сводится к только 3 NEON и нет скалярной арифметики. Ключевым трюком в 32-битной ARM является то, что попарное добавление двух половин регистра Q является просто нормальным добавлением двух регистров D - это не относится к AArch64, где макет регистра SIMD отличается, но тогда AArch64 имеет вышеупомянутый горизонтальный addv в любом случае.

Теперь, как ужасно любой из них выглядит в LLVM IR. Я не знаю. Я полагаю, это зависит от того, как он относится к типам векторов и операциям внутри, но с точки зрения окончательного машинного кода ARM оба могут считаться оптимальными.

+0

Ваш ответ полезен! Существуют инструкции 'shufflevector' вместо инструкции преобразования типа, такие как' trunc' или 'sext' в моем LLVM IR. Большое спасибо! – Shun

 Смежные вопросы

  • Нет связанных вопросов^_^