再帰関数の展開

4.3.0の最適化は凄いらしい。
http://d.hatena.ne.jp/toge/20080229#1204238423

with ada.integer_text_io;
procedure test is
   function f(x : integer) return integer is
   begin
      if x <= 0 then
         return 1;
      else
         return x * f(x - 1);
      end if;
   end f;
begin
   ada.integer_text_io.put(f(10));
end test;

gcc -O3 -S

	.file	"test.adb"
	.text
	.p2align 4,,15
	.def	_test__f.437;	.scl	3;	.type	32;	.endef
_test__f.437:
LFB11:
	pushl	%ebp
LCFI0:
	movl	%esp, %ebp
LCFI1:
	subl	$36, %esp
LCFI2:
	movl	%ebx, -12(%ebp)
LCFI3:
	movl	%eax, %ebx
	movl	$1, %eax
	testl	%ebx, %ebx
	movl	%esi, -8(%ebp)
LCFI4:
	movl	%edi, -4(%ebp)
LCFI5:
	jle	L3
	movl	%ebx, %esi
	movl	$1, %eax
	subl	$1, %esi
	je	L5
	movl	%ebx, %edi
	movl	$1, %eax
	subl	$2, %edi
	je	L7
	movl	%ebx, %edx
	movl	$1, %eax
	subl	$3, %edx
	movl	%edx, -36(%ebp)
	je	L9
	movl	%ebx, %edx
	movl	$1, %eax
	subl	$4, %edx
	movl	%edx, -32(%ebp)
	je	L11
	movl	%ebx, %edx
	movl	$1, %eax
	subl	$5, %edx
	movl	%edx, -28(%ebp)
	je	L13
	movl	%ebx, %edx
	movl	$1, %eax
	subl	$6, %edx
	movl	%edx, -24(%ebp)
	je	L15
	movl	%ebx, %edx
	movl	$1, %eax
	subl	$7, %edx
	movl	%edx, -20(%ebp)
	je	L17
	movl	%ebx, %edx
	movl	$1, %eax
	subl	$8, %edx
	movl	%edx, -16(%ebp)
	je	L19
	leal	-9(%ebx), %eax
	call	_test__f.437
	imull	-16(%ebp), %eax
L19:
	imull	-20(%ebp), %eax
L17:
	imull	-24(%ebp), %eax
L15:
	imull	-28(%ebp), %eax
L13:
	imull	-32(%ebp), %eax
L11:
	imull	-36(%ebp), %eax
L9:
	imull	%edi, %eax
L7:
	imull	%esi, %eax
L5:
	imull	%ebx, %eax
L3:
	movl	-12(%ebp), %ebx
	movl	-8(%ebp), %esi
	movl	-4(%ebp), %edi
	movl	%ebp, %esp
	popl	%ebp
	ret
LFE11:
	.p2align 4,,15
.globl __ada_test
	.def	__ada_test;	.scl	2;	.type	32;	.endef
__ada_test:
LFB10:
	pushl	%ebp
LCFI6:
	movl	$8, %eax
	movl	%esp, %ebp
LCFI7:
	subl	$24, %esp
LCFI8:
	leal	-8(%ebp), %ecx
	movl	%ebx, -8(%ebp)
LCFI9:
	movl	_ada__integer_text_io__default_base, %ebx
	movl	%esi, -4(%ebp)
LCFI10:
	movl	_ada__integer_text_io__default_width, %esi
	call	_test__f.437
	movl	%ebx, 8(%esp)
	movl	%esi, 4(%esp)
	leal	(%eax,%eax,8), %eax
	leal	(%eax,%eax,4), %eax
	addl	%eax, %eax
	movl	%eax, (%esp)
	call	_ada__integer_text_io__put__2
	movl	-8(%ebp), %ebx
	movl	-4(%ebp), %esi
	movl	%ebp, %esp
	popl	%ebp
	ret
LFE10:
	.section	.eh_frame,"dr"
Lframe1:
	.long	LECIE1-LSCIE1
LSCIE1:
	.long	0x0
	.byte	0x1
	.def	___gnat_eh_personality;	.scl	2;	.type	32;	.endef
	.ascii "zP\0"
	.uleb128 0x1
	.sleb128 -4
	.byte	0x8
	.uleb128 0x5
	.byte	0x0
	.long	___gnat_eh_personality
	.byte	0xc
	.uleb128 0x4
	.uleb128 0x4
	.byte	0x88
	.uleb128 0x1
	.align 4
LECIE1:
LSFDE1:
	.long	LEFDE1-LASFDE1
LASFDE1:
	.long	LASFDE1-Lframe1
	.long	LFB11
	.long	LFE11-LFB11
	.uleb128 0x0
	.byte	0x4
	.long	LCFI0-LFB11
	.byte	0xe
	.uleb128 0x8
	.byte	0x85
	.uleb128 0x2
	.byte	0x4
	.long	LCFI1-LCFI0
	.byte	0xd
	.uleb128 0x5
	.byte	0x4
	.long	LCFI3-LCFI1
	.byte	0x83
	.uleb128 0x5
	.byte	0x4
	.long	LCFI5-LCFI3
	.byte	0x87
	.uleb128 0x3
	.byte	0x86
	.uleb128 0x4
	.align 4
LEFDE1:
LSFDE3:
	.long	LEFDE3-LASFDE3
LASFDE3:
	.long	LASFDE3-Lframe1
	.long	LFB10
	.long	LFE10-LFB10
	.uleb128 0x0
	.byte	0x4
	.long	LCFI6-LFB10
	.byte	0xe
	.uleb128 0x8
	.byte	0x85
	.uleb128 0x2
	.byte	0x4
	.long	LCFI7-LCFI6
	.byte	0xd
	.uleb128 0x5
	.byte	0x4
	.long	LCFI9-LCFI7
	.byte	0x83
	.uleb128 0x4
	.byte	0x4
	.long	LCFI10-LCFI9
	.byte	0x86
	.uleb128 0x3
	.align 4
LEFDE3:
	.def	_ada__integer_text_io__put__2;	.scl	2;	.type	32;	.endef

展開はされますけど、定数までたたみこんでくれません……。分岐も残ってます。
例外情報のラベルが除去できないとかそんなでしょうか。C++だとどうなんでしょ。