Mit -Ofast wird bei folgenden Code die Power Funktion weg optimiert und durch die dritte Wurzel ersetzt.
auto func(double MANNING2, double qNorm, double H ) { return MANNING2 * qNorm / (pow(H,(7.0/3.0))); }
Im Assembler Code ist nur noch cbrt zu erkennen, kein pow mehr.
func(double, double, double): subq $40, %rsp movsd %xmm0, 8(%rsp) # MANNING2 movapd %xmm2, %xmm0 # H nach xmm0 für cbrt movsd %xmm1, 24(%rsp) # qNorm movsd %xmm2, 16(%rsp) # H call cbrt # cbrt(H) nach xmm0 movsd 16(%rsp), %xmm2 # xmm2 = H movsd 24(%rsp), %xmm1 # xmm1 = qNorm mulsd 8(%rsp), %xmm1 # xmm1 = MANNING2*qNorm addq $40, %rsp mulsd %xmm2, %xmm2 # xmm2 = H*H mulsd %xmm0, %xmm2 # xmm2 = H*H*cbrt(H) divsd %xmm2, %xmm1 # xmm1 = MANNING2*qNorm /(H*H*cbrt(H)) movapd %xmm1, %xmm0 ret
Der Assembler Code zurück nach C++ übersetzt gibt folgenden:
auto func(double MANNING2, double qNorm, double H ) { return MANNING2 * qNorm / (H*H*cbrt(H)); }
Die pow Funktion mit zwar bekannten, aber "unschönen" Exponenten wurde ersetzt durch eine Multiplikation und eine Power Funktion mit bekannte und "schönen" Exponenten: 1/3
Aber es könnte besser sein. Es fällt auf, dass die Funktionsargumente erst einmal auf den Stack gepusht werden. Offenbar braucht die cbrt Funktion die Register xmm0, xmm1, xmm2 selbst. Und so müssen die Werte eben gesichert werden. Da sie erst danach gebraucht werden. ...
Natürlich kann man MANNING2*qNorm berechnen bevor vor Nenner der Formel fertig berechnet ist. Mathematisch kann man das tun, die Klammern kann man setzten.
Aber den Compiler stört das nicht. Es wird immer erst cbrt vor MANNING2*qNorm. Ich denke cbrt braucht einfach mehr Zeit als eine Multiplikation. Und daher wird dieser Befehl als erstes ausgeführt. Und zwischenzeitlich können davon unabhängige Variablen bearbeitet werden.
Aber eine Sache kann dennoch optimiert werden. Indem H als ersten Parameter übergeben wird. Dann liegt es gleich im xmm0 Register für cbrt bereit und muss nicht erst dorthin kopiert werden. An der Anzahl der Instruktionen ändert dies nichts. Aber die mov Operation wird auch erst nach cbrt ausgeführt.