Ich habe gegenüber einem Kollegen behauptet, dass er if (i < input.size() - 1) print(0);in dieser Schleife optimiert würde, damit er input.size()nicht in jeder Iteration gelesen wird, aber es stellt sich heraus, dass dies nicht der Fall ist!
void print(int x) {
std::cout << x << std::endl;
}
void print_list(const std::vector<int>& input) {
int i = 0;
for (size_t i = 0; i < input.size(); i++) {
print(input[i]);
if (i < input.size() - 1) print(0);
}
}
Laut dem Compiler Explorer mit gcc-Optionen -O3 -fno-exceptionslesen wir tatsächlich input.size()jede Iteration und verwenden sie lea, um eine Subtraktion durchzuführen!
movq 0(%rbp), %rdx
movq 8(%rbp), %rax
subq %rdx, %rax
sarq $2, %rax
leaq -1(%rax), %rcx
cmpq %rbx, %rcx
ja .L35
addq $1, %rbx
Interessanterweise findet diese Optimierung in Rust statt. Es sieht so aus, als würde es idurch eine Variable ersetzt j, die bei jeder Iteration dekrementiert wird, und der Test i < input.size() - 1wird durch so etwas ersetzt j > 0.
fn print(x: i32) {
println!("{}", x);
}
pub fn print_list(xs: &Vec<i32>) {
for (i, x) in xs.iter().enumerate() {
print(*x);
if i < xs.len() - 1 {
print(0);
}
}
}
Im Compiler-Explorer sieht die entsprechende Assembly wie folgt aus:
cmpq %r12, %rbx
jae .LBB0_4
Ich habe nachgesehen und bin mir ziemlich sicher, dass es der Zähler r12ist xs.len() - 1und rbxist. Früher gibt es ein addfür rbxund ein movaußerhalb der Schleife in r12.
Warum ist das? Es scheint, als ob GCC in der Lage ist, das zu integrieren, size()und operator[]wie es getan hat, sollte es wissen können, dass sich size()dies nicht ändert. Aber vielleicht urteilt der Optimierer von GCC, dass es sich nicht lohnt, ihn in eine Variable zu ziehen? Oder vielleicht gibt es eine andere mögliche Nebenwirkung, die dies unsicher machen würde - weiß jemand Bescheid?
cout.operator<<(). Der Compiler weiß nicht, dass diese Black-Box-Funktion keinen Verweis auf die std::vectorvon einem globalen erhält .
printlnoder der operator<<Schlüssel ist.
printlnist wahrscheinlich eine komplexe Methode, der Compiler kann Probleme haben zu beweisen, dassprintlnder Vektor nicht mutiert.