RISC-V Vector Intrinsicを使っていた時に引っかかった問題をメモ.結論としてはLLVMのバグっぽいのだけれども,最新版で発生しているかどうかも確認する.
マスク付きのGather命令のレジスタ割り付けについて,正直が付きにくい問題が発生していた:
vdest = __riscv_vluxei64_v_f64m1_m(mask, base_ptr, vindex, vl);
このとき,vindexとvdestがベクトルレジスタに相当し,maskがベクトル用のベクトルマスクレジスタになる.
マスクレジスタにより部分的な書き込みが発生するため,vdestとvindexを共用してはいけないが,以下のような命令が生成されていた.
vluxei64.v v8, rs2, v8, v0.t
これだと,vdestにvindexの値が伝搬してしまい(マスクが有効でない部分),値がずれてしまう.
本来はこのようなレジスタ割り付け自体がされるべきではないが,無理やり修正するならば以下のようになるだろう.
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);
とすべきだろう.