引言
RISC-V的Vector扩展使得RISC-V处理器能够执行向量计算, 目前的编译器已经提供了一部分自动向量化的能力, 但如果要更加充分地发挥处理器向量化计算的能力, 还是需要由程序员理解计算的过程, 灵活调用intrinsic指令进行优化。然而, RISC-V 的Vector intrinsic指令细分下来有上万条, 具体该如何去调用?如何避免一不小心因为函数名很类似而调用错误的intrinsic指令?
基本指南
- The RISC-V Instruction Set Manual Volume I: Unprivileged ISA
- RISC-V Vector C Intrinsic Specification
可以参考这两个已经Ratified的标准, 来使用intrinsic指令。
另外有一个网页可以比较方便地查找intrinsic指令的定义:dzaima.github.io/intrinsics-viewer
LSP
现代的编辑器一般都会带有LSP(Language Server Protocol)的支持, 可以实现语法补全, 跳转, 代码检查, 格式化等功能。
clangd 是一个LSP服务器, 在VSCode, Neovim等编辑器中都有支持,
但是它对于这些RVV的intrinsic指令的支持并不是很好。
相关讨论
相关的issue:clangd/2143
Clangd doesn’t understand the RISC-V vector intrinsics generated by
#pragma clang riscv intrinsic vectorin<riscv_vector.h>. The __riscv_vsetvl_xxx defines work, but operations such as__riscv_vadd_vv_u64m4()aren’t detected properly and are flagged as errors.
从这里可以看到, <riscv_vector.h> 中虽然通过 #pragma clang riscv intrinsic vector
生成了intrinsic指令, 使得编译器能够识别, 但是clangd无法识别。
从目前的讨论结果来看, 主要还是等上游更新支持。
临时的解决方案
从表面的现象来说, clangd无法识别intrinsic指令,
只需要额外添加一些intrinsic指令的声明就能够解决这个问题。
因此我写了一个脚本, 根据rvv-intrinsic-doc
中所列出的intrinsic指令, 自动生成相应的头文件, 然后在clangd的配置文件中添加这些头文件即可。
相关的实现参考仓库:qiujiandong/rvv-intrinsic
只需要在项目的compile_commands.json同级的目录中添加一个.clangd的配置文件, 并添加如下类似的配置:
1 | CompileFlags: |
clangd 就能够正确识别intrinsic指令了。
Demo:
