You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ARM NEON内在函数实现ARMv7与AArch64兼容的向量全零检查?

问题:ARM NEON内在函数兼容ARMv7与AArch64实现全零向量检查

我正在使用ARM官方发布的ARM NEON内在函数开发,希望代码同时兼容ARMv7和AArch64架构。我原本采用如下汇编代码检查向量是否全零:

shrn v0.8b, v0.8h, #4    // 把v0中的字节压缩为半字节
fcmp d0, #0.0

当v0的所有字节为0x00或0xff时(我的代码场景符合该条件),这段汇编可正常工作。

我尝试将其转为如下C代码,该代码可在AArch64上成功编译并生成预期机器码:

static int
veq_zero(uint8x16_t v)
{
    uint8x8_t narrowed;

    /* 把每个字节压缩为半字节 */
    narrowed = vshrn_n_u16(vreinterpretq_u16_u8(v), 4);

    /* 检查该向量是否全零 */
    return (vdupd_lane_f64(vreinterpret_f64_u16(narrowed), 0) == 0.0);
}

但ARMv7中不存在vdupd_lane_f64和vreinterpret_f64_u16调用,甚至整个float64x1_t类型及其相关函数都缺失。

请问如何将该程序逻辑转为兼容ARMv7 NEON与AArch64的C内在函数实现?


兼容实现方案

核心思路是保留原有的压缩逻辑(这部分在ARMv7和AArch64中通用),将向量全零检查改为使用64位整数操作,避开ARMv7不支持的float64x1_t相关接口:

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

static int veq_zero(uint8x16_t v)
{
    // 与原汇编逻辑一致:将16字节向量拆为8个16位元素,每个右移4位后窄化为8字节
    uint8x8_t narrowed = vshrn_n_u16(vreinterpretq_u16_u8(v), 4);
    
    // 将8字节向量重新解释为64位单元素向量,取出后转为标准uint64_t类型
    uint64_t vec_val = vget_lane_u64(vreinterpret_u64_u8(narrowed), 0);
    
    // 判断是否全零,对应原汇编的fcmp d0, #0.0
    return (vec_val == 0);
}

说明

  1. 压缩逻辑复用:vreinterpretq_u16_u8和vshrn_n_u16是ARMv7和AArch64 NEON都支持的内在函数,完全复现原汇编的字节压缩行为。
  2. 跨架构全零检查:
    • vreinterpret_u64_u8将uint8x8_t向量重新解释为uint64x1_t(64位单元素向量),该接口在两种架构下均存在。
    • vget_lane_u64取出64位向量的唯一元素,得到标准C语言的uint64_t类型,直接与0比较即可判断压缩后的向量是否全零。
  3. 适配场景需求:如果你的实际需求是检测原向量全0x00或全0xff(即压缩后的向量全0x00或全0xff),可将返回条件修改为:
    return (vec_val == 0 || vec_val == UINT64_C(0xffffffffffffffff));
    

内容的提问来源于stack exchange,提问作者fuz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:28:10