ビットシフト演算が遅い・・・? Part2

gccの-Sオプションで、コンパイルまでで止めてみました。

gcc -O0 -S ord.c
gcc -O0 -S bit.c

// ord.s
.L5:
	cmpl	$10000000, -8(%ebp)
	jle	.L8
	jmp	.L6
.L8:
	call	rand
	movl	%eax, -12(%ebp)
	cmpl	$0, -12(%ebp)
	jns	.L9
	addl	$127, -12(%ebp)
.L9:
	movl	-12(%ebp), %eax
	sarl	$7, %eax
	movl	%eax, -4(%ebp)
	movl	-4(%ebp), %eax
	sall	$3, %eax
	movl	%eax, -4(%ebp)
	leal	-8(%ebp), %eax
	incl	(%eax)
	jmp	.L5
// bit.s
.L5:
	cmpl	$10000000, -8(%ebp)
	jle	.L8
	jmp	.L6
.L8:
	call	rand
	movl	%eax, -12(%ebp)
	cmpl	$0, -12(%ebp)
	jns	.L9
	addl	$127, -12(%ebp)
.L9:
	movl	-12(%ebp), %eax
	sarl	$7, %eax
	movl	%eax, -4(%ebp)
	leal	-4(%ebp), %eax
	sall	$3, (%eax)
	leal	-8(%ebp), %eax
	incl	(%eax)
	jmp	.L5
// ord.s
	movl	-4(%ebp), %eax
	sall	$3, %eax
	movl	%eax, -4(%ebp)
// bit.s
	leal	-4(%ebp), %eax
	sall	$3, (%eax)

どうやら、この辺りに問題がありそうです。
どちらもビットシフトで計算していました。-O0オプションを付けていたのに・・・。
ord.sでは、スタックの内容をアキュムレータ(eax)に代入してビットシフトしていますが、
bit.sでは、スタックのアドレスをアキュムレータ(eax)に代入してビットシフトしているようです。(推測)
gccが賢すぎたorz
ということで、当該個所を以下のように置き換え、ord.sでは乗算命令を使ってみました。

// ord.s
	movl	-4(%ebp), %eax
	imul	$8, %eax
	movl	%eax, -4(%ebp)
// bit.s
	movl	-4(%ebp), %eax
	sall	$3, %eax
	movl	%eax, -4(%ebp)

gcc -O0 -Wa,-n -oord ord.s
gcc -O0 -Wa,-n -obit bit.s

それぞれ5回実行した結果。
乗算: 平均 341ミリ秒
ビットシフト: 平均 328.4ミリ秒
となりました。


ちなみに、手元のgcc version 3.3.1 (mingw special 20030804-1)でコンパイルしてみたところ、該当部分は以下のようになりました。

	movl	%eax, -4(%ebp)
	movl	-4(%ebp), %edx
	movl	%edx, %eax
	addl	%eax, %eax
	addl	%edx, %eax
	movl	%eax, -4(%ebp)
	movl	-4(%ebp), %eax
	shrl	%eax
	movl	%eax, -4(%ebp)

ずいぶんとややこしいです。