ARM NEON aarch64:如何以优化方式比较和更新 neon 寄存器?

ARM NEON aarch64: How to compare and update neon registers in optimized way?

实际上,我正在尝试找出一种比较从“unsigned short”数组加载的霓虹灯寄存器值的好方法。由于我正在处理一个大型项目,因此无法解释共享整个代码部分。相反,我将分享一个类似的例子,以便每个人都能理解实际的问题场景。


C++ 实现:

unsigned short *values = new unsigned short[8];
for(int i=0; i<8; i++){
    if(values[i] > 255){
            values[i] = 255;
    }
}

程序集实现:

MOV W3, #255
UMOV W2, V4.H[0]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[0], W2

UMOV W2, V4.H[1]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[1], W2

UMOV W2, V4.H[2]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[2], W2

UMOV W2, V4.H[3]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[3], W2

UMOV W2, V4.H[4]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[4], W2

UMOV W2, V4.H[5]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[5], W2

UMOV W2, V4.H[6]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[6], W2

UMOV W2, V4.H[7]
CMP W2, #0x00FF
CSEL W2,W3, W2, GT
MOV V4.H[7], W2

我知道对于这种情况,这是一个糟糕的程序集实现。是否可以用更少的指令执行此任务?我没有找到很多关于这个比较和更新指令的汇编文档。
任何好主意将不胜感激。谢谢。

正如其他人指出的那样,您可以使用 UMIN 或 VMIN in 32bit neon. Sample implementation using neon 内在函数,它适用于 32 位和 64 位霓虹灯:

#include <stdint.h>
#include <arm_neon.h>

void clamp8(uint16_t values[8])
{
    uint16x8_t v = vld1q_u16(values);
    uint16x8_t x255 = vdupq_n_u16(255);
    uint16x8_t clamped = vminq_u16(v, x255);
    vst1q_u16(values, clamped);
}

这会产生这个 arm64 neon 代码:

ldr q0, [x0]
movi v1.2d, #0xff00ff00ff00ff
umin v0.8h, v0.8h, v1.8h
str q0, [x0]