Stack, Funktionsaufruf
-
blurry333 schrieb:
ohnein !! schrieb:
und schon sind nur noch 50 Pointer auf dem Stack.
Warum sollen 50 pointer besser sein als 50 int ? Kommt doch aufs selbe raus.
Ist net garantiert.
Aber irgnorier diesen Post.
-
blurry333 schrieb:
So jetzt werden alle Variablen benutzt

int funk1( int zahl ) { int a = zahl+1; int b = zahl +2 ; int c = zahl +3; int d = zahl -1 ; if( zahl > 0 ) { funk(zahl - 2 ); } int e = a+b+c+d ; return e ; }Und was soll das jetzt werden, eine Übung in "Wir spielen Optimierer"? Ein optimierender Compiler würde auch hier alles wegoptimieren und nur
return zahl+1+zahl+2+zahl+3+zahl-1;stehen lassen (und das auch nochmal zusammenfassen, vermutlich.) Das ist aber eine ziemlich nutzlose Übung, deine Frage sollte doch wohl beantwortet sein?
-
Nathan schrieb:
Frage an alle anderen: Funktionsaufruf wegoptimiert, da keine Seiteneffekt?
Ich würde sagen nein und mein Compiler ebenfalls. Um zu beweisen, dass der Funktionsaufruf keine Seiteneffekte hat, müsste er beweisen, dass funk1, welches von funk1 aufgerufen wird, keine Seiteneffekte hat. Dazu wiederum, müsste er beweisen, dass funk1 keine Seiteneffekte hat, wozu er beweisen müsste, dass funk1 keine Seiteneffekte hat. Du siehst, worauf das hinaus läuft.

Einem Menschen ist natürlich klar, dass die Kette zahl -2 irgendwann kleiner wird als 0, aber der Compiler müsste das allgemein für jede vorstellbare Eingabe beweisen, was dann doch eine recht heftige mathematische Leistung wäre für ein Computerprogramm. Zumal viele Sonderfälle von Nebenbedingungen abhängen, wie MAX_INT oder dem Unterlaufverhalten, die dem Compiler zwar prinzipiell bekannt wären, aber nicht unbedingt offensichtlich in ihrer Anwendung sind.
Wenn da
if(false)stünde, könnte das natürlich ohne Probleme wegoptimiert werden.
-
SeppJ schrieb:
Nathan schrieb:
Frage an alle anderen: Funktionsaufruf wegoptimiert, da keine Seiteneffekt?
Ich würde sagen nein und mein Compiler ebenfalls. Um zu beweisen, dass der Funktionsaufruf keine Seiteneffekte hat, müsste er beweisen, dass funk1, welches von funk1 aufgerufen wird, keine Seiteneffekte hat. Dazu wiederum, müsste er beweisen, dass funk1 keine Seiteneffekte hat, wozu er beweisen müsste, dass funk1 keine Seiteneffekte hat. Du siehst, worauf das hinaus läuft.

Ja, Kompilierung könnte sich dann etwas in die Länge ziehen.

-
SeppJ schrieb:
Nathan schrieb:
Frage an alle anderen: Funktionsaufruf wegoptimiert, da keine Seiteneffekt?
Ich würde sagen nein und mein Compiler ebenfalls. Um zu beweisen, dass der Funktionsaufruf keine Seiteneffekte hat, müsste er beweisen, dass funk1, welches von funk1 aufgerufen wird, keine Seiteneffekte hat. Dazu wiederum, müsste er beweisen, dass funk1 keine Seiteneffekte hat, wozu er beweisen müsste, dass funk1 keine Seiteneffekte hat. Du siehst, worauf das hinaus läuft.

Ach nö, man kann das ganz einfach beweisen.
Wenn der Returnwert ignoriert wird, was ja hier der Fall ist, dann tut func1 nichts ausser sich selbst aufzurufen.
Da ein Aufruf einer Funktion kein beobachtbarer Seiteneffekt ist, tut func1 also nichts.
Beweis fertig. Ich sehe da kein Problem.Liesse sich auch ganz einfach in einem Compiler implementieren - man guckt ob eine Funktion auf irgend einem Ausführungspfad beobachtbare Seiteneffekte hat, und verfolgt rekursive Pfade einfach nicht weiter.
Ob aktuelle Compiler das können oder nicht ist eine andere Frage.
-
hustbaer schrieb:
Ach nö, man kann das ganz einfach beweisen.
Wenn der Returnwert ignoriert wird, was ja hier der Fall ist, dann tut func1 nichts ausser sich selbst aufzurufen.
Da ein Aufruf einer Funktion kein beobachtbarer Seiteneffekt ist, tut func1 also nichts.
Beweis fertig. Ich sehe da kein Problem.Ich schon: Endlosrekursion. Es gibt zwar die komische Klausel, dass in C++ angenommen werden darf, dass jede Schleife irgendwann einmal abbricht, aber wenn wir diese unintuitive Ausrede mal nicht zulassen, dann muss hier bewiesen werden, dass die Funktion überhaupt jemals zurück kehrt. Und das führt zu oben genannten Problemen.
-
Aber genau dafür gibt es diese "unintuitive(n)" Klausel(n) ja.
Wobei ich nichmal sicher bin dass man die Progress-Klausel braucht.
Man muss nur sagen dass ein korrektes Programm keinen Stack-Overflow produzieren darf.
Unter der Annahme dass das Programm korrekt ist, gibt es dann nur mehr die Möglichkeit dass func1 irgendwann zurückkehrt.
Und damit können wir es wegoptimieren.Finde ich auch nicht sehr unintuitiv.
-
SeppJ schrieb:
Ich sehe da kein Problem.
Ich schon:
Ich nicht.
Clang (sorry für tinyurl, der Link* ist für das Forum zu lang) macht darausfunk(int): # @funk(int) leal 5(,%rdi,4), %eax ret*:
http://gcc.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22int%20funk%28%20int%20zahl%20%29\n{\n\n%20%20int%20a%20%3D%20zahl%2B1%3B\n%20%20int%20b%20%3D%20zahl%20%2B2%20%3B\n%20%20int%20c%20%3D%20zahl%20%2B3%3B\n%20%20int%20d%20%3D%20zahl%20-1%20%3B\n\n%20%20if%28%20zahl%20%3E%200%20%29\n%20%20%20%20{\n%20%20%20%20%20%20funk%28zahl%20-%202%20%29%3B\n%20%20%20%20}\n\n%20%20int%20e%20%3D%20a%2Bb%2Bc%2Bd%20%3B\n%20%20return%20e%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fclang%2B%2B%22%2C%22options%22%3A%22-O3%20-march%3Dnative%20-std%3Dc%2B%2B11%22}]}
-
SeppJ schrieb:
Es gibt zwar die komische Klausel, dass in C++ angenommen werden darf, dass jede Schleife irgendwann einmal abbricht, aber wenn wir diese unintuitive Ausrede mal nicht zulassen
Nö.
Man darf davon ausgehen dass ein Programm nie in einen Zustand wechselt wo es nix mehr macht.
(In C++ 11 gilt das vermutlich für jeden Thread eines Programms einzeln.)Wobei jeder beobachtbare Seiteneffekt als "was machen" gilt. Endlosschleifen sind dabei nicht verboten - sie müssen nur einen möglichen Ausführungspfad enthalten der einen beobachtbaren Seiteneffekt produziert.
Und damit wird das ganze auch weit weniger unintuitiv.
EDIT: @himmlischer klang: Danke für den Link, die Seite kannte ich noch nicht! ICC kann es übrigens auch wegoptimieren.
EDIT2: Man kann sogar das "if" wegmachen und Clang/ICC können es immer noch optimieren.
-
hustbaer schrieb:
SeppJ schrieb:
Es gibt zwar die komische Klausel, dass in C++ angenommen werden darf, dass jede Schleife irgendwann einmal abbricht, aber wenn wir diese unintuitive Ausrede mal nicht zulassen
Nö.
Man darf davon ausgehen dass ein Programm nie in einen Zustand wechselt wo es nix mehr macht.
(In C++ 11 gilt das vermutlich für jeden Thread eines Programms einzeln.)Wobei jeder beobachtbare Seiteneffekt als "was machen" gilt. Endlosschleifen sind dabei nicht verboten - sie müssen nur einen möglichen Ausführungspfad enthalten der einen beobachtbaren Seiteneffekt produziert.
Und damit wird das ganze auch weit weniger unintuitiv.
Hast du dich neulich nicht selber mal beschwert, dass man hier immer Seitenlange Disclaimer schreiben muss, wenn man irgendeine Aussage tätigt? Natürlich reden wir hier von seiteneffektfreien Schleifen wie die, um die es hier schon über zwei Seiten hinweg geht.
EDIT2: Man kann sogar das "if" wegmachen und Clang/ICC können es immer noch optimieren.
Und genau das ist das unintuitive. Erwartetes Verhalten: Endlosschleife, theoretisch unterbrechbar mit Signal. Tatsächliches Verhalten: Ausgabe einer Zahl und Return aus der main!
-
@SeppJ
OK.Nur finde ich es nicht sinnvoll damit zu antworten das deiner Meinung nach sein sollte, wenn Nathan fragt was aktuelle Compiler können bzw. dürfen.
Sie dürfen, und sie können.Dein "nein" war nicht hilfreich (da falsch).
Die klassifizierung einer Klausel im Standard als "unintuitive Ausrede" ändert daran auch nix.ps: Ja, auf den ersten Blick ist es unintuitiv. Man kann aber schnell verstehen was das ganze soll und auch ein gutes Verständnis dafür entwickeln was OK ist und was nicht - von daher finde ich es nicht sehr unintuitiv. Und was den Teil Ausrede angeht: nuja, es ermöglicht einige Dinge zu optimieren, die sonst nur mit viel mehr Aufwand zu optimieren wären. Und es tut nicht weh. Strict Aliasing tut viel mehr weh.