使用氖指令与零比较

时间:2015-12-29 04:07:04

标签: arm compare simd neon

我有以下代码

if(value  == 0)
{
    value = 1;
}

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

3 个答案:

答案 0 :(得分:3)

假设整数数据,那么由于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),它也不起作用,因此,在这些情况下,您需要构建一个包含相应替换元素的单独向量,并根据@Ermlg's answer使用比较掩码进行条件选择。

答案 1 :(得分: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);

要获取更多信息,请参阅here

答案 2 :(得分:1)

如果要检查向量的 any 元素是否为非零并在其上分支:


您可以在矢量通道上使用get min / max。

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指令从霓虹灯单一寄存器转移到Arm通用寄存器进行比较。