コードの最適化

関数

#include <stdio.h>

void func1 (int x, int a[]) {
  int i, j;
  for (i = 0; i < 10; i ++) {
    a[i] = i;
  }
}

int main (void) {
  int x[10];
  func1 (5, x);
  return 0;
}

gcc -O0 -S でこんぱいる

	.file	"ex4.c"
	.text
.globl func1
	.type	func1, @function
func1:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$16, %esp
	movl	$0, -4(%ebp)
	jmp	.L2
.L3:
	movl	-4(%ebp), %eax
	sall	$2, %eax
	addl	12(%ebp), %eax
	movl	-4(%ebp), %edx
	movl	%edx, (%eax)
	addl	$1, -4(%ebp)
.L2:
	cmpl	$9, -4(%ebp)
	jle	.L3
	leave
	ret
	.size	func1, .-func1
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$56, %esp
	leal	-40(%ebp), %eax
	movl	%eax, 4(%esp)
	movl	$5, (%esp)
	call	func1
	movl	$0, %eax
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
	.section	.note.GNU-stack,"",@progbits


gcc -O1 -Sでこんぱいる

	.file	"ex4.c"
	.text
.globl func1
	.type	func1, @function
func1:
	pushl	%ebp
	movl	%esp, %ebp
	movl	12(%ebp), %edx
	movl	$0, %eax
.L2:
	movl	%eax, (%edx,%eax,4)
	addl	$1, %eax
	cmpl	$10, %eax
	jne	.L2
	popl	%ebp
	ret
	.size	func1, .-func1
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$56, %esp
	leal	-40(%ebp), %eax
	movl	%eax, 4(%esp)
	movl	$5, (%esp)
	call	func1
	movl	$0, %eax
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
	.section	.note.GNU-stack,"",@progbits

mainは変わらず。
func1のfor文で変わってる。
俺がわかる範囲だと、
配列のインデックスに使ってるeaxの計算を、
sall云々からmovlで一行にしてる。

movl	%eax, (%edx,%eax,4)

右の(%edx,%eax,4)は、(edx+eax*4)みたいな計算をする。
あとは、ジャンプの回数を少なくしたり。


gcc -O2 -Sでこんぱいる

	.file	"ex4.c"
	.text
	.p2align 4,,15
.globl func1
	.type	func1, @function
func1:
	pushl	%ebp
	xorl	%eax, %eax
	movl	%esp, %ebp
	movl	12(%ebp), %edx
	.p2align 4,,7
	.p2align 3
.L2:
	movl	%eax, (%edx,%eax,4)
	addl	$1, %eax
	cmpl	$10, %eax
	jne	.L2
	popl	%ebp
	ret
	.size	func1, .-func1
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	pushl	%ebp
	xorl	%eax, %eax
	movl	%esp, %ebp
	subl	$48, %esp
	leal	-40(%ebp), %edx
	.p2align 4,,7
	.p2align 3
.L7:
	movl	%eax, (%edx,%eax,4)
	addl	$1, %eax
	cmpl	$10, %eax
	jne	.L7
	xorb	%al, %al
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
	.section	.note.GNU-stack,"",@progbits

もはやfunc1は呼んでいない。
そのかわり同様の構造がmainに組み込まれている。
それと頻繁にalign命令を使ってロケーションカウンタを調整してる。
他はeaxを0にするために、xorで0にしてる。
alを使ってるのは、レジスタの操作を最小限にしようとしているからだと思う。


gcc -O3 -s でこんぱいる

	.file	"ex4.c"
	.text
	.p2align 4,,15
.globl func1
	.type	func1, @function
func1:
	pushl	%ebp
	movl	%esp, %ebp
	movl	12(%ebp), %eax
	movl	$0, (%eax)
	movl	$1, 4(%eax)
	movl	$2, 8(%eax)
	movl	$3, 12(%eax)
	movl	$4, 16(%eax)
	movl	$5, 20(%eax)
	movl	$6, 24(%eax)
	movl	$7, 28(%eax)
	movl	$8, 32(%eax)
	movl	$9, 36(%eax)
	popl	%ebp
	ret
	.size	func1, .-func1
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	pushl	%ebp
	xorl	%eax, %eax
	movl	%esp, %ebp
	popl	%ebp
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
	.section	.note.GNU-stack,"",@progbits

配列の中は0〜9が確定しているので、その値がぶち込まれてしまった。