👋
MLIRでHello, World!
音に聞くMLIRを使ってみようと思ったんですが、公式のチュートリアルとか非公式のブログ記事とか見てもなんか最初からダイアレクトを作成していて、それより手前のとりあえずMLIRで書かれたサンプルコードを動かすというところだけをやってくれている記事が見当たりませんでした。それでもなんとか自力で動かすことができたので、ここではダイアレクトの作成とかは傍に置いておき、簡単にHello, World!するところまでやってみます。ZennにMLIRに関する記事ってまだ一つもないようですし、最初にふさわしいネタですよね。
hello.mlir
module {
memref.global "private" constant @string : memref<14xi8> = dense<[0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0]>
llvm.func external @puts(!llvm.ptr<i8>) -> ()
func.func @main() -> i64 {
%c0_i64 = arith.constant 0 : i64
%0 = memref.get_global @string : memref<14xi8>
%1 = memref.extract_aligned_pointer_as_index %0 : memref<14xi8> -> index
%2 = arith.index_cast %1 : index to i64
%3 = llvm.inttoptr %2 : i64 to !llvm.ptr<i8>
llvm.call @puts(%3) : (!llvm.ptr<i8>) -> ()
return %c0_i64 : i64
}
}
MLIRはまだまだ発展途上で、今回もmemref.extract_aligned_pointer_as_index
というかなり新しめのオペレーションを利用しており、LLVMのmain
ブランチをクローンしてきて自前ビルドする必要があります(筆者が使ったのは52bff450dd
)。ビルドコマンドは以下の通り。
cmake -S llvm -B build -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$PWD" \
-DLLVM_ENABLE_ZLIB=OFF \
-DLLVM_ENABLE_ZSTD=OFF \
-DLLVM_ENABLE_BINDINGS=OFF \
-DLLVM_ENABLE_PROJECTS=mlir \
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_CCACHE_BUILD=OFF
make -C build -j`nproc` install
ずらずらと並んでいるコマンドラインオプションは出てきたエラーを見ながらググったりしてちまちま設定したものなので、環境によっては少し変えないとうまくいかないかもしれません(ちなみに筆者の環境はM1 MacBook Air、macOS 12.5.1です)。ビルドが済んだらカレントディレクトリにインストールされるので、./bin
に$PATH
を通して各種コマンドラインツールを使えるようにしてください。
冒頭のテキストをhello.mlir
などに保存したら、それを以下のコマンドでLLVM IRに変換します。
mlir-opt \
--convert-arith-to-llvm \
--convert-func-to-llvm \
--convert-memref-to-llvm \
--reconcile-unrealized-casts \
hello.mlir | mlir-translate --mlir-to-llvmir > hello.ll
以下のようなLLVM IRコードが出来上がります。
hello.ll
; ModuleID = 'LLVMDialectModule'
source_filename = "LLVMDialectModule"
@string = private constant [14 x i8] c"Hello, World!\00"
declare ptr @malloc(i64)
declare void @free(ptr)
declare void @puts(ptr)
define i64 @main() {
call void @puts(ptr @string)
ret i64 0
}
!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}
lli
で実行してハロワ完了。
> lli hello.ll
Hello, World!
もちろんclang
で実行可能形式にすることもできます。
> llc -filetype=obj hello.ll -o hello.o
> clang hello.o -o hello
> ./hello
Hello, World!
草草
Discussion