FPGA開発日記

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

LLVM13からRISC-Vのベクトル拡張のサポートを確かめる

こちらの記事を読んで、LLVMのAutomatic Vectorizationが少しずつ使い物になっていることを知った。RISC-Vを例に採っているので、使えるようになっているのだろうか?

blog.kmckk.com

丸一日かけてLLVM13をビルドして、オプションを調整してベクトル拡張命令が出力されるのか確かめてみた。

このようなテストプログラムを使って確かめてみる。

  • vec_vec_add.c
void vector_add (int *c, int *a, int *b, const int N)
{
  for (int i = 0; i < N; i++) {
    c[i] = a[i] + b[i];
  }
  return;
}

以下のバージョン番号で試行している。

$ clang --version
clang version 13.0.0 (https://github.com/llvm/llvm-project.git a7cb951fa40df14d98c51059194ae42855b96a08)
Target: x86_64-unknown-linux-gnu
Thread model: posix

以下のコマンドでClangとLLCを動かして動作を確認した。

$ clang   -O3 -march=rv64gcv0p10 -menable-experimental-extensions --target=riscv64-unknown-elf vec_vec_add.c -c -emit-llvm -o vec_vec_add.riscv64.static.bc
$ llc -march=riscv64           -mattr=experimetal-v -disable-tail-calls -riscv-v-vector-bits-min=256 "--debug" -relocation-model=static -filetype=asm  vec_vec_add.riscv64.static.bc -o vec_vec_add.riscv64.static.S

うーん、この時点ではまだベクトル関係のIRは出ていない。っていうかどの時点でLLVM-IRにベクトルの要素が入ってくるんだろう?

for.body:                                         ; preds = %for.body.preheader, %for.body
  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
  %0 = load i32, i32* %arrayidx, align 4, !tbaa !4
  %arrayidx2 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv
  %1 = load i32, i32* %arrayidx2, align 4, !tbaa !4
  %add = add nsw i32 %1, %0
  %arrayidx4 = getelementptr inbounds i32, i32* %c, i64 %indvars.iv
  store i32 %add, i32* %arrayidx4, align 4, !tbaa !4
  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
  %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count
  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !8

そして変換されたアセンブリコードにもベクトルっぽい要素は無かった。原因は何だろう?確認してみよう。

vector_add:                             # @vector_add
# %bb.0:                                # %entry
        blez    a3, .LBB0_3
# %bb.1:                                # %for.body.preheader
        slli    a3, a3, 32
        srli    a3, a3, 32
.LBB0_2:                                # %for.body
                                        # =>This Inner Loop Header: Depth=1
        lw      a4, 0(a1)
        lw      a5, 0(a2)
        add     a4, a4, a5
        sw      a4, 0(a0)
        addi    a0, a0, 4
        addi    a2, a2, 4
        addi    a3, a3, -1
        addi    a1, a1, 4
        bnez    a3, .LBB0_2