Ich experimentiere mit der generierten Assembly und fand eine interessante Sache. Es gibt zwei Funktionen, die eine identische Berechnung durchführen. Der einzige Unterschied zwischen ihnen ist die Art und Weise, wie die Ergebnisse zusammengefasst werden.Harte Unterschiede in der generierten Assembly von Gleitkomma-Vergleichen < and > =
#include <cmath>
double func1(double x, double y)
{
double result1;
double result2;
if (x*x < 0.0) result1 = 0.0;
else
{
result1 = x*x+x+y;
}
if (y*y < 0.0) result2 = 0.0;
else
{
result2 = y*y+y+x;
}
return (result1 + result2) * 40.0;
}
double func2(double x, double y)
{
double result = 0.0;
if (x*x >= 0.0)
{
result += x*x+x+y;
}
if (y*y >= 0.0)
{
result += y*y+y+x;
}
return result * 40.0;
}
Die Montage von x86 Klirren 3.7 mit -O2
Schalter auf gcc.godbolt.org erzeugt ist noch so viel anders und unerwartet. (Kompilierung auf gcc Ergebnisse in ähnlicher Montage)
.LCPI0_0:
.quad 4630826316843712512 # double 40
func1(double, double): # @func1(double, double)
movapd %xmm0, %xmm2
mulsd %xmm2, %xmm2
addsd %xmm0, %xmm2
addsd %xmm1, %xmm2
movapd %xmm1, %xmm3
mulsd %xmm3, %xmm3
addsd %xmm1, %xmm3
addsd %xmm0, %xmm3
addsd %xmm3, %xmm2
mulsd .LCPI0_0(%rip), %xmm2
movapd %xmm2, %xmm0
retq
.LCPI1_0:
.quad 4630826316843712512 # double 40
func2(double, double): # @func2(double, double)
movapd %xmm0, %xmm2
movapd %xmm2, %xmm4
mulsd %xmm4, %xmm4
xorps %xmm3, %xmm3
ucomisd %xmm3, %xmm4
xorpd %xmm0, %xmm0
jb .LBB1_2
addsd %xmm2, %xmm4
addsd %xmm1, %xmm4
xorpd %xmm0, %xmm0
addsd %xmm4, %xmm0
.LBB1_2:
movapd %xmm1, %xmm4
mulsd %xmm4, %xmm4
ucomisd %xmm3, %xmm4
jb .LBB1_4
addsd %xmm1, %xmm4
addsd %xmm2, %xmm4
addsd %xmm4, %xmm0
.LBB1_4:
mulsd .LCPI1_0(%rip), %xmm0
retq
func1
kompiliert zu einer branchless Versammlung, an denen viel weniger Anweisungen als func2
. somit wird erwartet, dass func2
viel langsamer als func1
ist.
Kann jemand dieses Verhalten erklären?
Der offensichtlichste Unterschied ist, dass der Optimierer weiß, dass 'x * x <0.0 'auf' false 'optimiert werden kann, aber nicht' x * x> = 0.0 'kann optimiert werden wahr '. Bei der Betrachtung vieler optimierter Assemblierungen von mehreren Compilern habe ich nie irgendwelche vernünftigen Muster gesehen, was Optimierer verstehen oder nicht verstehen. – JSF