2009年07月07日
gccのビルトイン関数 (数学関数)
前回に続いてもう少しgccのビルドイン関数を見ていきます。
gccはとてもたくさんのビルトイン関数があります。
オンラインマニュアルのこのページにリストがあります。
http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Other-Builtins.html#Other-Builtins
標準の数学関数はほとんどがビルトイン関数になっています。引数が定数の場合にはコンパイル時に計算されてしまいます。
具体例を見てみましょう。
#includedouble sin0() { return sin(0.0); } double sqrt3() { return sqrt(3.0); }
これをコンパイルした時に生成されるコードは以下の通り。
(ARMのコードです。見やすくするために -O オプションをつけました。)
... sin0: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mov r0, #0 mov r1, #0 bx lr .size sin0, .-sin0 .align 2 .global sqrt3 .type sqrt3, %function sqrt3: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. ldr r0, .L5 ldr r1, .L5+4 bx lr .L6: .align 2 .L5: .word -396866390 .word 1073460858 .size sqrt3, .-sqrt3 .ident "GCC: (GNU) 4.3.3"
ライブラリのdouble sin(double) も double sqrt(double) も呼ばれません。コンパイル時に計算しておいた値を取り出してきて返しています。
ARMではVFPの命令でsqrtを計算できます。
#includedouble sqrt_n(int n) { return sqrt(n); }
これはこんなコードが出ます。
... sqrt_n: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 str lr, [sp, #-4]! sub sp, sp, #4 fmsr s15, r0 @ int fsitod d6, s15 # intからdoubleに変換 fsqrtd d7, d6 # VFPのsqrt命令 fcmpd d7, d7 fmstat beq .L2 fmrrd r0, r1, d6 bl sqrt # ライブラリのsqrt呼び出し fmdrr d7, r0, r1 .L2: fmrrd r0, r1, d7 add sp, sp, #4 ldmfd sp!, {pc}
VFPのsqrt命令の後に何やら比較をして再度ライブラリのsqrtを呼び出すようなコードが出ています。これはどういうことでしょう?
sqrtは引数が負の値の場合は結果がNaNになります。NaNとNaNの比較は偽になると定義されています。
fcmpd d7, d7 fmstat beq .L2
この部分では d7がNaNかどうかのチェックをしています。
NaNでなければ、その結果を返します。
NaNの場合にはライブラリのsqrtを呼び出すことで、エラー処理(変数errnoに値をセットするなど)がなされるようになっています。
(追記 2009.7.10)
同じプログラムに -fno-math-errno をつけると以下のようなすっきりしたコードが生成されます。
sqrt_n: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. fmsr s12, r0 @ int fsitod d7, s12 fsqrtd d6, d7 fmrrd r0, r1, d6 bx lr
errnoをチェックしない場合はこっちの方がいいですね。
-fno-math-errno に関してはこちらを。
http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Optimize-Options.html#Optimize-Options