Friday, 26 August 2016

LLVM clang TAIL CALL

相変わらずLLVMと格闘しているんですが、

* 局所変数のポインタを取っているところがある

と、clang は、call lifetime.begin と call lifetime.end というダミーコードを LLVM IR にはさむのだけど、

* tail call の後に call lifetime.end をはさむ

という技を出してくれるので、tail call が「お尻になんかある」でcancel されてしまう。

なので、その後始末を tail call の直前に行うように。いや、まぁ、

* 局所変数は関数呼び出しから戻ってくるまでは生きてる

はずなんですが、CbCの場合は戻ってこないので呼び出し前に解放して良い。引数はCだからコピーのはずだし。

そもそも、局所変数のアドレスを取る必要なんかないコードなので、それ取れば動くんだけど、まあ、コンパイラのバグであることは確かなので。

で、綺麗に tail call は出るようになった。

なんだが、

* -O0 では動くが、-O では生成されたコードが動かない

なんだぁ?! 少し追求したんだけど原因不明。さらっと見たところ生成したコードは正しそうなのだが... 元のプログラムのせいか? 局所変数のアドレスとって、memcopy としかしているからなあ。

局所変数のアドレスを取らないまっとうなプログラムは動いているようなので、いじったところの問題かな。もともと、-O で動かないから始まったので、そこ直さないとな。

もう一つ変なところがあって、「お尻になんかある」の判断は生きているらしく、そこで IsTailCAll flag が切られていたりするんですが、そこは「本当のチェックは後でやる」みたいなコメントがついていて、実際には別なところで判断されているらしい。結局、tail call ( jmp 命令) は出てるので、さらに謎です。

だいたい最近のプログラムだと関数呼び出しのnestは30くらい。その大半は不要だってのが僕の主張なんだけど、まぁ、いろいろ複雑...

No comments: