Я провел простой эксперимент, чтобы сравнить if-else только с if (с установленными значениями по умолчанию). Пример:
void test0(char c, int *x) {
*x = 0;
if (c == 99) {
*x = 15;
}
}
void test1(char c, int *x) {
if (c == 99) {
*x = 15;
} else {
*x = 0;
}
}
Для вышеперечисленных функций я получил точный код сборки (используя cmovne
).
Однако при добавлении дополнительной переменной:
void test2(char c, int *x, int *y) {
*x = 0;
*y = 0;
if (c == 99) {
*x = 15;
*y = 21;
}
}
void test3(char c, int *x, int *y) {
if (c == 99) {
*x = 15;
*y = 21;
} else {
*x = 0;
*y = 0;
}
}
Сборка внезапно меняется:
test2(char, int*, int*):
cmp dil, 99
mov DWORD PTR [rsi], 0
mov DWORD PTR [rdx], 0
je .L10
rep ret
.L10:
mov DWORD PTR [rsi], 15
mov DWORD PTR [rdx], 21
ret
test3(char, int*, int*):
cmp dil, 99
je .L14
mov DWORD PTR [rsi], 0
mov DWORD PTR [rdx], 0
ret
.L14:
mov DWORD PTR [rsi], 15
mov DWORD PTR [rdx], 21
ret
Похоже, что единственное отличие состоит в том, что верхние mov
выполняются до или после je
.
Теперь (извините, что моя сборка немного грубая), разве всегда лучше иметь mov
после прыжка, чтобы сохранить сброс трубопроводов? И если да, почему бы оптимизатор (gcc6.2-O3) не использовал лучший метод?