Original C function:
Partial assembly generated by Microsoft's compiler. (With or without optimizations there is no recursion removal.)int recursiveFact(int number) { if (number == 0) return 1; else return number * recursiveFact(number - 1); }
; iterativeFact ; int factor = 1; ; for (int count = 2; count <= number; count++) mov edx, DWORD PTR _number$[esp-4] mov ecx, 2 cmp edx, ecx mov eax, 1 jl SHORT $L1434 push esi $L1432: ; factor = factor * count; mov esi, ecx imul eax, esi inc ecx cmp ecx, edx jle SHORT $L1432 pop esi $L1434: |
; recursiveFact push esi ; if (number == 0) mov esi, DWORD PTR _number$[esp] test esi, esi jne SHORT $L1438 ; return 1; mov eax, 1 pop esi $L1438: ; else ; return number * recursiveFact(number - 1); lea eax, DWORD PTR [esi-1] push eax call recursiveFact imul eax, esi add esp, 4 pop esi |
GCC generated assembly:
Non-optimized 619 bytes | Optimized (-O1) 513 bytes | Optimized (-O2) 437 bytes | Optimized (-O3) 2,374 bytes | Optimized for size (-Os) 385 |
---|---|---|---|---|
.file "fact.cpp" .text .globl _Z13recursiveFacti .type _Z13recursiveFacti, @function _Z13recursiveFacti: .LFB0: pushq %rbp movq %rsp, %rbp subq $16, %rsp movl %edi, -4(%rbp) cmpl $0, -4(%rbp) jne .L2 movl $1, %eax jmp .L3 .L2: movl -4(%rbp), %eax subl $1, %eax movl %eax, %edi call _Z13recursiveFacti imull -4(%rbp), %eax .L3: leave ret .LFE0: .size _Z13recursiveFacti, .-_Z13recursiveFacti .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4" .section .note.GNU-stack,"",@progbits |
.file "fact.cpp" .text .globl _Z13recursiveFacti .type _Z13recursiveFacti, @function _Z13recursiveFacti: .LFB0: pushq %rbx movl %edi, %ebx movl $1, %eax testl %edi, %edi je .L2 leal -1(%rdi), %edi call _Z13recursiveFacti imull %ebx, %eax .L2: popq %rbx ret .LFE0: .size _Z13recursiveFacti, .-_Z13recursiveFacti .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4" .section .note.GNU-stack,"",@progbits |
.file "fact.cpp" .text .p2align 4,,15 .globl _Z13recursiveFacti .type _Z13recursiveFacti, @function _Z13recursiveFacti: .LFB0: testl %edi, %edi movl $1, %eax je .L2 .p2align 4,,10 .p2align 3 .L3: imull %edi, %eax subl $1, %edi jne .L3 .L2: rep ret .LFE0: .size _Z13recursiveFacti, .-_Z13recursiveFacti .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4" .section .note.GNU-stack,"",@progbits |
.file "fact.cpp" .text .p2align 4,,15 .globl _Z13recursiveFacti .type _Z13recursiveFacti, @function _Z13recursiveFacti: .LFB0: testl %edi, %edi je .L10 movl %edi, %edx movl %edi, %esi shrl $2, %edx leal 0(,%rdx,4), %ecx testl %ecx, %ecx je .L11 cmpl $9, %edi jbe .L11 leal -1(%rdi), %eax movl %eax, -20(%rsp) leal -2(%rdi), %eax movd -20(%rsp), %xmm6 movl %eax, -16(%rsp) leal -3(%rdi), %eax movd -16(%rsp), %xmm0 movl %edi, -16(%rsp) movl %eax, -12(%rsp) movd -16(%rsp), %xmm1 xorl %eax, %eax movd -12(%rsp), %xmm4 punpckldq %xmm6, %xmm1 punpckldq %xmm4, %xmm0 movdqa .LC1(%rip), %xmm4 punpcklqdq %xmm0, %xmm1 movdqa .LC0(%rip), %xmm0 jmp .L9 .p2align 4,,10 .p2align 3 .L36: movdqa %xmm3, %xmm1 .L9: movdqa %xmm1, %xmm5 movdqa %xmm1, %xmm3 psrlq $32, %xmm1 addl $1, %eax pmuludq %xmm0, %xmm5 psrlq $32, %xmm0 pmuludq %xmm0, %xmm1 pshufd $8, %xmm5, %xmm0 cmpl %eax, %edx paddd %xmm4, %xmm3 pshufd $8, %xmm1, %xmm1 punpckldq %xmm1, %xmm0 ja .L36 movdqa %xmm0, %xmm7 subl %ecx, %edi cmpl %esi, %ecx psrldq $8, %xmm7 movdqa %xmm7, %xmm2 movdqa %xmm7, %xmm6 psrlq $32, %xmm2 pmuludq %xmm0, %xmm6 psrlq $32, %xmm0 pshufd $8, %xmm6, %xmm1 pmuludq %xmm2, %xmm0 pshufd $8, %xmm0, %xmm0 punpckldq %xmm0, %xmm1 movdqa %xmm1, %xmm7 psrldq $4, %xmm7 pmuludq %xmm7, %xmm1 movd %xmm1, -20(%rsp) movl -20(%rsp), %eax je .L2 .L3: movl %edi, %edx imull %edi, %eax subl $1, %edx je .L2 imull %edx, %eax movl %edi, %edx subl $2, %edx je .L2 imull %edx, %eax movl %edi, %edx subl $3, %edx je .L2 imull %edx, %eax movl %edi, %edx subl $4, %edx je .L2 imull %edx, %eax movl %edi, %edx subl $5, %edx je .L2 imull %edx, %eax movl %edi, %edx subl $6, %edx je .L2 imull %edx, %eax movl %edi, %edx subl $7, %edx je .L2 imull %edx, %eax subl $8, %edi movl %eax, %edx imull %edi, %edx testl %edi, %edi cmovne %edx, %eax ret .p2align 4,,10 .p2align 3 .L10: movl $1, %eax .p2align 4,,10 .p2align 3 .L2: rep ret .p2align 4,,10 .p2align 3 .L11: movl $1, %eax jmp .L3 .LFE0: .size _Z13recursiveFacti, .-_Z13recursiveFacti .section .rodata.cst16,"aM",@progbits,16 .align 16 .LC0: .long 1 .long 1 .long 1 .long 1 .align 16 .LC1: .long -4 .long -4 .long -4 .long -4 .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4" .section .note.GNU-stack,"",@progbits |
.file "fact.cpp" .text .globl _Z13recursiveFacti .type _Z13recursiveFacti, @function _Z13recursiveFacti: .LFB0: movl $1, %eax .L3: testl %edi, %edi je .L2 imull %edi, %eax decl %edi jmp .L3 .L2: ret .LFE0: .size _Z13recursiveFacti, .-_Z13recursiveFacti .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4" .section .note.GNU-stack,"",@progbits |