Ich habe im Compiler-Explorer herumgespielt und festgestellt, dass die Reihenfolge der an std :: min übergebenen Argumente die ausgegebene Assembly ändert.
Hier ist das Beispiel im Godbolt Compiler Explorer
double std_min_xy(double x, double y) {
return std::min(x, y);
}
double std_min_yx(double x, double y) {
return std::min(y, x);
}
Dies wird kompiliert (zum Beispiel mit -O3 in Clang 9.0.0), um:
std_min_xy(double, double): # @std_min_xy(double, double)
minsd xmm1, xmm0
movapd xmm0, xmm1
ret
std_min_yx(double, double): # @std_min_yx(double, double)
minsd xmm0, xmm1
ret
Dies bleibt bestehen, wenn ich std :: min in einen ternären Operator der alten Schule ändere. Es bleibt auch bei allen modernen Compilern bestehen, die ich ausprobiert habe (clang, gcc, icc).
Die zugrunde liegende Anweisung lautet minsd
. Beim Lesen der Dokumentation ist das erste Argument von minsd
auch das Ziel für die Antwort. Anscheinend ist xmm0 der Ort, an dem meine Funktion ihren Rückgabewert setzen soll. Wenn also xmm0 als erstes Argument verwendet wird, ist dies nicht movapd
erforderlich. Aber wenn xmm0 das zweite Argument ist, muss es movapd xmm0, xmm1
den Wert in xmm0 bekommen. (Anmerkung des Herausgebers: Ja, x86-64 System V übergibt FP-Argumente in xmm0, xmm1 usw. und gibt in xmm0 zurück.)
Meine Frage: Warum ändert der Compiler nicht die Reihenfolge der Argumente selbst, so dass dies movapd
nicht notwendig ist? Es muss sicher wissen, dass die Reihenfolge der Argumente zu minsd die Antwort nicht ändert? Gibt es eine Nebenwirkung, die ich nicht schätze?