興味本位ではあるが、高速C++コンパイラとしてオープンソース化されたZapccが非常に気になっている。
LLVMがベースとなっていることだし、いつも新しいコンパイラプラットフォームが公開されたときはRISC-Vの対応について見てしまうので、アーキテクチャの移行という点でもどのようなものなのか気になっている。現状のC++プロジェクトをZapccに移行して試行してみることにした。
Zapcc – A (Much) Faster C++ Compiler
そもそもZapccは何故高速なのか
以下の記事を見るといろいろと書いてある。
Caching Clang-Based C++ Compiler Zapcc Open-Sourced
Zapccの高速化におけるカギとなるアイデアは、コンパイルサーバ(zapccs)を用意するということだ。 このコンパイルサーバはメモリチュウに常駐し、クライアントからコンパイルコマンドを受け付ける。 zapccsはC+ヘッダファイルを一度だけ解析し、すべてのテンプレートインスタンスと、生成されたコードをメモリ中に保持する。 この点について、zapccは、ステロイド剤としてプリコンパイルされたヘッダの類を使用しているとみることができるが、プリコンパイルされたヘッダよりも多くの情報をメモリ中にキャッシュすることができる。
ははあ、コンパイルアルゴリズムがどうのこうのというより、コンパイルフロー中で生成されるファイル群をより多くメモリ中に保持することで高速化を図っているのか。
既存のプロジェクトをZapccに移行する
ここでは、開発中の自作RISC-Vシミュレータを、
の順番で移行してみることにした。移行方法としては、CMakeを使っているのでターゲットコンパイラを変えるだけである。
$ cmake . -DCMAKE_CXX_COMPILER=[ターゲットC++コンパイラ] && make -j4
Clangへの移行
GCC→Clangの移行は簡単に終わった。
$ cmake . -DCMAKE_CXX_COMPILER=clang++ && make -j4
一方で、Clang→Zapccでは最後のリンク時に怒られてしまった。これはなんでだろう?
$ cmake . -DCMAKE_CXX_COMPILER=zapcc++ && make -j4 ... /usr/bin/cmake -E cmake_link_script CMakeFiles/riscvforest.dir/link.txt --verbose=1 /home/msyksphinz/work/zapcc/build/bin/zapcc++ -O0 -g -Wall -fstack-protector -g -rdynamic CMakeFiles/riscvforest.dir/home/msyksphinz/work/forest/riscv_forest_zapcc/src/swimmer_main.cpp.o CMakeFiles/riscvforest.dir/home/msyksphinz/work/forest/riscv_forest_zapcc/src/ris cv_bfd_env.cpp.o -o riscvforest -L/home/msyksphinz/work/forest/riscv_forest_zapcc/build_riscvforest/../vendor/gflags/lib -L/home/msyksphinz/work/forest/riscv_forest_zapcc/build_riscvforest/../vendor/softfloat/build -Wl,-rpath,/home/msyksphinz/work/forest/riscv_forest_ zapcc/build_riscvforest/../vendor/gflags/lib:/home/msyksphinz/work/forest/riscv_forest_zapcc/build_riscvforest/../vendor/softfloat/build libriscv_cedar.a -lgflags -lpthread -lbfd -lsoftfloat -lgmp -lgmpxx libriscv_cedar.a(inst_ops_riscv.cpp.o): In function `InstOps::FloatMadd(int, int, int, unsigned int*)': /home/msyksphinz/work/forest/riscv_forest_zapcc/src/inst_ops_riscv.cpp:693: undefined reference to `f32_mul(float32_t, float32_t)' /home/msyksphinz/work/forest/riscv_forest_zapcc/src/inst_ops_riscv.cpp:693: undefined reference to `f32_add(float32_t, float32_t)' libriscv_cedar.a(inst_ops_riscv.cpp.o): In function `InstOps::FloatAdd(int, int, unsigned char, unsigned int*)':