🏋

Cranelift IRを簡単に実行する

2023/07/23に公開

手軽にCranelift IR(.clifファイル)を実行する方法が意外とドキュメントで見つからなかったので、備忘録として残しておきます。

cranelift-toolsをインストールする

clif-toolというコマンドが欲しいので、含まれているcranelift-toolsをインストールします。
cranelift-tools は crates.io にはないので、git からインストールします。


$ cargo install --git=https://github.com/bytecodealliance/wasmtime.git cranelift-tools

clif を書く

なんでもいいです

add.clif
function %add(i32, i32) -> i32 fast {
    block0(v0: i32, v1: i32):
        v2 = iadd v0, v1
        return v2
}

clif-util 用のコメントを書く

add.clif
function %add(i32, i32) -> i32 fast {
    block0(v0: i32, v1: i32):
        v2 = iadd v0, v1
        return v2
}

;print: %add(1, 2)
;run: %add(1, 2) == 3

行内の;以降はclifのコメントです。
print: %add(1, 2)%add(1, 2)の結果を表示するように指示します。
run: %add(1, 2) == 3%add(1, 2)の結果が3であることをテストします。

実行する

$ clif-util run -v add.clif
%add(1, 2) -> 3
add.clif
1 file

-vをつけないと clif の文法とかでエラーが出た場合にどこが悪いのかわからないので、つけておきましょう。
;run の部分はテストに失敗した場合にエラーが表示されます。

cliu-util test

clif-util testサブコマンドを-vオプションと一緒に使うと実行時間がでてくるので、簡単なベンチマークとして使えます。
これは filetestをラッパしてるコマンドです。

適当に作ったナイーブなフィボナッチ数列

fib.clif
test run
target x86_64

function %fib(i32) -> i32 fast {
	fn0 = %fib(i32) -> i32

	block0(v0: i32):
		v1 = iconst.i32 2
		v3 = icmp ult v0, v1
		brif v3, block1, block2


	block1:
		return v0

	block2:
		v4 = iconst.i32 1

		v5 = isub v0, v1
		v6 = isub v0, v4


		v7 = call fn0(v5)
		v8 = call fn0(v6)

		v9 = iadd v7, v8
		return v9
}

;print: %fib(42)

実行結果

$ clif-util test -v fib.clif
%fib(42) -> 267914296
1.448 fib.clif
1 tests

実行時間 1.448 秒

ちなみに clang でコンパイルした場合はこんな感じです。

fib.c
#include <stdio.h>

int fib(int x)
{
	if (x < 2)
	{
		return x;
	}
	else
	{

		return fib(x - 2) + fib(x - 1);
	}
}

int main()
{
	printf("%d\n", fib(42));
	return 0;
}
$ clang -O3 fib.c
$ time ./a.out
267914296

real    0m0.830s
user    0m0.831s
sys     0m0.001s

Cranelift 思ったより速いですね。

GitHubで編集を提案

Discussion