Ich wurde von der Optimierung der Tail-Call-Frage Was ist Tail Call Optimization <
Also habe ich beschlossen zu sehen, wie ich es in normalem C machen kann.
Also habe ich die 2 faktoriellen Programme geschrieben, 1. wo die Tail Call Optimierung angewendet werden kann. Ich nenne diese Tatsache Funktion als Tatsache (n, 1).
%Vor%2. ist die normale Rekursion, bei der mehrere Stapelrahmen benötigt werden.
%Vor%Dies ist die Assembly, die von einem 32-Bit-Compiler für den ersten mit -O2
generiert wird %Vor%Dies ist die Assembly, die von einem 32-Bit-Compiler für letztere mit -O2 generiert wird.
%Vor%Kompilieren Sie beide Programme, und sehen Sie sich die erzeugte Assembly an. Beide Programme haben immer noch rekursive Aufrufe. Aber, wenn ich kompiliere mit -O2-Option (Assembly oben gepostet) in ersterem, sehe ich überhaupt keine rekursiven Aufrufe und so denke ich, gcc tut Tail Call Optimierung Zeug.
Aber wenn ich das letztere mit der Option -O2 kompiliere, entfernt es auch die rekursiven Aufrufe und stellt statt dessen eine ziemlich große Anzahl von Assemblerbefehlen im Vergleich zu dem, was mit dem vorherigen on -O2 passiert.
Ich wollte genau verstehen, was der Compiler in letzterem macht und warum er nicht in die Assembly transformiert werden konnte, die durch den Example selbst mit O4 erzeugt wurde.
Der Unterschied ist, dass die erste Version eine Variable int
für die Berechnung verwendet, die dann am Ende auf unsigned long long
erweitert wird, während die letzte Version unsigned long long
den ganzen Weg verwendet.
Der Compiler scheint die rekursiven Aufrufe in Schleifen optimiert zu haben. Beachten Sie, dass Ihr C-Code nur Vorwärtszweige hat (wenn-dann-sonst), aber der Assembler hat Rückwärtszweige (Schleifen).
Wenn Sie wirklich eine Tail-Call-Optimierung in Aktion sehen wollen, rufen Sie eine andere Funktion auf. Natürlich ist das keine Rekursion, aber der Compiler ist zu schlau für kleine Testfälle wie diese.
Tags und Links c gcc compiler-construction compiler-optimization tail-call-optimization