FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LLVM16で遭遇したマスク命令の奇妙な命令生成メモ

RISC-V Vector Intrinsicを使っていた時に引っかかった問題をメモ.結論としてはLLVMのバグっぽいのだけれども,最新版で発生しているかどうかも確認する.

マスク付きのGather命令のレジスタ割り付けについて,正直が付きにくい問題が発生していた:

vdest = __riscv_vluxei64_v_f64m1_m(mask, base_ptr, vindex, vl);

このとき,vindexvdestがベクトルレジスタに相当し,maskがベクトル用のベクトルマスクレジスタになる. マスクレジスタにより部分的な書き込みが発生するため,vdestvindexを共用してはいけないが,以下のような命令が生成されていた.

vluxei64.v v8, rs2, v8, v0.t

これだと,vdestvindexの値が伝搬してしまい(マスクが有効でない部分),値がずれてしまう.

本来はこのようなレジスタ割り付け自体がされるべきではないが,無理やり修正するならば以下のようになるだろう.

vdest_tmp = __riscv_vluxei64_v_f64m1_m(mask, base_ptr, vindex, vl);
// mask ? vdest_tmp : vdest
vdest = __riscv_vmerge_vvm_f64m1(vdest,  vdest_tmp, mask, vl);

あるいは,

vdest = __riscv_vmerge_vvm_f64m1 (vdest,
                                  __riscv_vluxei64_v_f64m1_m(mask, base_ptr, vindex, vl), 
                                  mask, vl);

とすべきだろう.