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