Tru64 UNIXで遊ぼう!(inline編)

Tru64 UNIXでlibarchiveをコンパイル出来るように試行錯誤していたところ、面白いものを見つけました。

github.com

どうやら、Tru64 UNIXの場合は関数指定子inlineを__inlineと定義しているようです。

どういうことなの?

せっかくなのでアセンブラを出力させてみました。

まずは普通のinline版

$ more inline.c

static inline int
max(int i1, int i2) {
        return (i1 > i2) ? i1:i2;
}
 
int
main(int argc, char *argv[])
{
        return max(1,5);
}

コンパイラCompaq C Compilerです。

$ cc -V
Compaq C V6.5-303 (dtk) on HP Tru64 UNIX V5.1B (Rev. 2650)
Compiler Driver V6.5-302 (dtk) cc Driver
$ cc -S inline.c
                                                                                                                                                                                                    
$ more inline.s                                                                                                                                                                                                     
	.set noat
	.set noreorder
	.text
	.arch	generic
	.align 4
	.file 1 "inline.c"
	.loc 1 1
 #      1 static inline int
	.ent 	$$1$max
	.loc 1 1
	.loc 1 2
 #      2 max(int i1, int i2) {
$$1$max:														   # 000002
	.frame  $sp, 0, $26
	.prologue 0
	.context full
	sextl	$17, $17
	sextl	$16, $0
	.loc 1 3
 #      3         return (i1 > i2) ? i1:i2;
	cmplt	$0, $17, $1												   # 000003
	cmovne	$1, $17, $0
	.loc 1 4
 #      4 }
	ret	($26)													   # 000004
	.end 	$$1$max
	unop
	unop
	unop
	.loc 1 1
	.loc 1 6
 #      5  
 #      6 int
	.globl  main
	.ent 	main
	.loc 1 6
	.loc 1 7
 #      7 main(int argc, char *argv[])
main:															   # 000007
	.frame  $sp, 0, $26
	.prologue 0
	.loc 1 9
 #      8 {
 #      9         return max(1,5);
	.context full
	mov	5, $17													   # 000009
	mov	1, $16
	br	$$1$max
	.end 	main
	.loc 1 6

おおう、普通にmaxを呼び出してますね...

では待望の__inline版

$ more __inline.c

static __inline int
max(int i1, int i2) {
        return (i1 > i2) ? i1:i2;
}
 
int
main(int argc, char *argv[])
{
        return max(1,5);
}
$ cc -S __inline.c
                                                                                                                                                                                                  
$ more __inline.s                                                                                                                                                                                                   
	.set noat
	.set noreorder
	.text
	.arch	generic
	.align 4
	.file 1 "__inline.c"
	.loc 1 6
 #      6 int
	.globl  main
	.ent 	main
	.loc 1 6
	.loc 1 7
 #      7 main(int argc, char *argv[])
main:															   # 000007
	.frame  $sp, 0, $26
	.prologue 0
	.loc 1 3
	.context full
	mov	5, $0													   # 000003
	.loc 1 10
 #      8 {
 #      9         return max(1,5);
 #     10 }
	ret	($26)													   # 000010
	.end 	main
	.loc 1 6

おーっ!インライン展開されています!

というわけで、Compaq C Compilerの場合、関数指定子inlineを__inlineと定義すれば、最適化をかけなくてもインライン展開されるということがわかりました〜
(もちろん普通?のinlineの場合でも最適化をかけるとインライン展開される)

ちなみにコンパイラgccを使った場合は、関数指定子inline、__inlineどちらを使っても結果は変わりませんでした〜
(もちろん最適化をかけると、どちらもインライン展開される)

$ gcc -v 
Using built-in specs.
Target: alphaev68-dec-osf5.1b
Configured with: ./configure --enable-languages=c,c++ --enable-threads=posix --disable-nls --without-gnu-ld --with-ld=/usr/ccs/bin/ld --without-gnu-as --with-as=/usr/bin/as --disable-libssp
Thread model: posix
gcc version 4.4.7 (GCC) 
$ /usr/local/bin/gcc -S __inline.c
  
$ more __inline.s                                                                                                                                                                                                   
	.file	1 "__inline.c"
	.verstamp 3 11
	.set noreorder
	.set volatile
	.set noat
	.arch ev6
	.text
	.align 2
	.ent max
$max..ng:
max:
	.frame $15,32,$26,0
	.mask 0x4008000,-32
	lda $30,-32($30)
	stq $26,0($30)
	stq $15,8($30)
	bis $31,$30,$15
	.prologue 0
	bis $31,$16,$2
	bis $31,$17,$1
	stl $2,16($15)
	stl $1,20($15)
	ldl $2,20($15)
	ldl $1,16($15)
	cmple $2,$1,$3
	cmoveq $3,$2,$1
	addl $31,$1,$1
	bis $31,$1,$0
	bis $31,$15,$30
	ldq $26,0($30)
	ldq $15,8($30)
	lda $30,32($30)
	ret $31,($26),1
	.end max
	.align 2
	.globl main
	.ent main
main:
	.frame $15,32,$26,0
	.mask 0x4008000,-32
	ldgp $29,0($27)
$main..ng:
	lda $30,-32($30)
	stq $26,0($30)
	stq $15,8($30)
	bis $31,$30,$15
	.prologue 1
	bis $31,$16,$1
	stq $17,24($15)
	stl $1,16($15)
	lda $16,1($31)
	lda $17,5($31)
	bsr $26,$max..ng
	bis $31,$0,$1
	bis $31,$1,$0
	bis $31,$15,$30
	ldq $26,0($30)
	ldq $15,8($30)
	lda $30,32($30)
	ret $31,($26),1
	.end main

うーむ、libarchiveにこの修正を突っ込んだ人はどこで発見したんですかね?
有名な話なのかな?