Ich habe dieses kleine Programm zu testen, wenn gfortran tut Beseitigung Endrekursion:Unterstützt gfortran Tail Call Elimination?
program tailrec
implicit none
print *, tailrecsum(5, 0)
contains
recursive function tailrecsum (x, running_total) result (ret_val)
integer, intent(in) :: x
integer, intent(in) :: running_total
integer :: ret_val
if (x == 0) then
ret_val = running_total
return
end if
ret_val = tailrecsum (x-1, running_total + x)
end function tailrecsum
end program
Um zu überprüfen, habe ich es mit der -S-Option kompiliert, einen Blick auf die Anweisungen zu nehmen. Hier werden die Leitungen für die tailrecsum Funktion:
tailrecsum.3429:
.LFB1:
.cfi_startproc
movl (%rdi), %eax
testl %eax, %eax
jne .L2
movl (%rsi), %eax
ret
.p2align 4,,10
.p2align 3
.L2:
subq $24, %rsp
.cfi_def_cfa_offset 32
leal -1(%rax), %edx
addl (%rsi), %eax
leaq 8(%rsp), %rdi
leaq 12(%rsp), %rsi
movl %edx, 8(%rsp)
movl %eax, 12(%rsp)
call tailrecsum.3429
addq $24, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
Am Ende sehe ich call tailrecsum.3429
und daher denken, dass es keine Endrekursion Beseitigung ist. Dies gilt auch, wenn ich -O2
oder -O3
und -foptimize-sibling-calls
verwende. Also, unterstützt Gfortran dies nicht oder ist es ein Problem meines Codes?
Vielen Dank! Ich experimentiere noch mehr und 'gfortran -optimize-sibling-calls tailrec.f90' ist nicht genug, um es funktionieren zu lassen (-> segfaults). '-O1' funktioniert auch nicht. Betrachtet man die Baugruppe der "-O2" -Version, sieht es so aus, als wäre die ganze Funktion in die Hauptplatine ... ... okai, '-O1 -optimize-sibling-calls' funktioniert! –
Ja, es ist inline, aber Sie können es separat kompilieren und Sie werden sehen, es ist voll von GOTOs, aber es enthält keinen Anruf. –
Okai, jetzt möchte ich wissen, warum die Verwendung von '-optimize-sibling-calls' nicht ausreicht. Also versuche ich verschiedene Kombinationen der Optionen, die im Moment mit "-O1" kommen ... –