Arm 用氖指令与零的比较

Arm 用氖指令与零的比较,arm,compare,simd,neon,Arm,Compare,Simd,Neon,我有下面的代码 if(值==0) { 数值=1; } 使用霓虹灯矢量化指令,我需要执行上述操作。如何将NEON寄存器的值与0进行比较,使其一次等于4个元素,如果元素为0,则将该值更改为1。可能看起来像这样: uint32x4_t value = {7, 0, 0, 3}; uint32x4_t zero = {0, 0, 0, 0}; uint32x4_t one = {1, 1, 1, 1}; uint32x4_t mask = vceqq_u32(value, zero); value

我有下面的代码

if(值==0)
{
数值=1;
}

使用霓虹灯矢量化指令,我需要执行上述操作。如何将NEON寄存器的值与0进行比较,使其一次等于4个元素,如果元素为0,则将该值更改为1。

可能看起来像这样:

uint32x4_t value = {7, 0, 0, 3};
uint32x4_t zero = {0, 0, 0, 0};
uint32x4_t one = {1, 1, 1, 1};

uint32x4_t mask = vceqq_u32(value, zero);

value = vbslq_u32(mask, one, value);

要获得更多信息,请参见。

假设整数数据,然后感谢NEON具有特定的“与零比较”指令,以及按位方式比较结果的工作方式,使用一个备用寄存器就可以实现这一点。在广义伪汇编中:

VCEQ.type  mask, data, #0    @ Generate bitmask vector with all bits set in elements
                             @  corresponding to zero elements in the data
VSUB.type  data, data, mask  @ Interpret "mask" as a vector of 0s and -1s, with the
                             @  result of incrementing just the zero elements of "data"
                             @  (thanks to twos complement underflow)
这个技巧对浮点数据不起作用,因为非零值的位模式更复杂,如果替换值不是1(或-1),它也不起作用,因此,在这些情况下,您需要构建一个包含适当替换元素的单独向量,并使用比较掩码执行条件选择,如。

如果您想检查向量的任何元素是否为非零并在该向量上分支:


可以使用“跨向量车道获取最小值/最大值”

if(vmaxvq_u32(value) == 0) { // Max value across quad vector, equals zero?
    value = vmovq_n_u32(1); // Set all lanes to 1
}
对于双向量

if(vmaxv_u32(value) == 0) { // Max value across double vector, equals zero?
    value = vmov_n_u32(1); // Set all lanes to 1
}

请注意,唯一的区别是“q”,它用于表示四元128位向量或64位双向量(如果不是)。编译器将使用mov指令从neon single传输到arm通用寄存器进行比较。

我需要上述程序的汇编代码,请回复@Ermlgthank u@Ermlg,我在汇编中实现了它,因为
(float)0
的位表示与ieee754 float中的
(int)0
相同,您可以使用浮点表示法
1
(或任何您想将零元素设置为的其他值)按位和掩码,然后进行加法而不是减法。@EOF…但一旦手头有替换值向量,按位然后添加是两条指令,而对于带有结果掩码的向量的直接条件选择只有一条指令;)另见。还可以看到,这个问题并不是关于检查所有元素是否为零,而是关于如何使用-
vceq
获得0/-1的掩码。这将是一个答案。我不确定是否存在该问题的32位ARM版本。如果人们在实际查找您的答案时碰巧发现了这个问题(如果向量的任何元素与条件匹配,则为标量分支),那么它在这里会有些有用。